1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGOpenMPRuntime.h" 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/Attr.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/OpenMPClause.h" 21 #include "clang/AST/StmtOpenMP.h" 22 #include "clang/Basic/BitmaskEnum.h" 23 #include "clang/CodeGen/ConstantInitBuilder.h" 24 #include "llvm/ADT/ArrayRef.h" 25 #include "llvm/ADT/SetOperations.h" 26 #include "llvm/Bitcode/BitcodeReader.h" 27 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 28 #include "llvm/IR/DerivedTypes.h" 29 #include "llvm/IR/GlobalValue.h" 30 #include "llvm/IR/Value.h" 31 #include "llvm/Support/Format.h" 32 #include "llvm/Support/raw_ostream.h" 33 #include <cassert> 34 35 using namespace clang; 36 using namespace CodeGen; 37 using namespace llvm::omp; 38 39 namespace { 40 /// Base class for handling code generation inside OpenMP regions. 41 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 42 public: 43 /// Kinds of OpenMP regions used in codegen. 44 enum CGOpenMPRegionKind { 45 /// Region with outlined function for standalone 'parallel' 46 /// directive. 47 ParallelOutlinedRegion, 48 /// Region with outlined function for standalone 'task' directive. 49 TaskOutlinedRegion, 50 /// Region for constructs that do not require function outlining, 51 /// like 'for', 'sections', 'atomic' etc. directives. 52 InlinedRegion, 53 /// Region with outlined function for standalone 'target' directive. 54 TargetRegion, 55 }; 56 57 CGOpenMPRegionInfo(const CapturedStmt &CS, 58 const CGOpenMPRegionKind RegionKind, 59 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 60 bool HasCancel) 61 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 62 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 63 64 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 65 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 66 bool HasCancel) 67 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 68 Kind(Kind), HasCancel(HasCancel) {} 69 70 /// Get a variable or parameter for storing global thread id 71 /// inside OpenMP construct. 72 virtual const VarDecl *getThreadIDVariable() const = 0; 73 74 /// Emit the captured statement body. 75 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 76 77 /// Get an LValue for the current ThreadID variable. 78 /// \return LValue for thread id variable. This LValue always has type int32*. 79 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 80 81 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 82 83 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 84 85 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 86 87 bool hasCancel() const { return HasCancel; } 88 89 static bool classof(const CGCapturedStmtInfo *Info) { 90 return Info->getKind() == CR_OpenMP; 91 } 92 93 ~CGOpenMPRegionInfo() override = default; 94 95 protected: 96 CGOpenMPRegionKind RegionKind; 97 RegionCodeGenTy CodeGen; 98 OpenMPDirectiveKind Kind; 99 bool HasCancel; 100 }; 101 102 /// API for captured statement code generation in OpenMP constructs. 103 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 104 public: 105 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 106 const RegionCodeGenTy &CodeGen, 107 OpenMPDirectiveKind Kind, bool HasCancel, 108 StringRef HelperName) 109 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 110 HasCancel), 111 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 112 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 113 } 114 115 /// Get a variable or parameter for storing global thread id 116 /// inside OpenMP construct. 117 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 118 119 /// Get the name of the capture helper. 120 StringRef getHelperName() const override { return HelperName; } 121 122 static bool classof(const CGCapturedStmtInfo *Info) { 123 return CGOpenMPRegionInfo::classof(Info) && 124 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 125 ParallelOutlinedRegion; 126 } 127 128 private: 129 /// A variable or parameter storing global thread id for OpenMP 130 /// constructs. 131 const VarDecl *ThreadIDVar; 132 StringRef HelperName; 133 }; 134 135 /// API for captured statement code generation in OpenMP constructs. 136 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 137 public: 138 class UntiedTaskActionTy final : public PrePostActionTy { 139 bool Untied; 140 const VarDecl *PartIDVar; 141 const RegionCodeGenTy UntiedCodeGen; 142 llvm::SwitchInst *UntiedSwitch = nullptr; 143 144 public: 145 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 146 const RegionCodeGenTy &UntiedCodeGen) 147 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 148 void Enter(CodeGenFunction &CGF) override { 149 if (Untied) { 150 // Emit task switching point. 151 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 152 CGF.GetAddrOfLocalVar(PartIDVar), 153 PartIDVar->getType()->castAs<PointerType>()); 154 llvm::Value *Res = 155 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 156 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 157 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 158 CGF.EmitBlock(DoneBB); 159 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 160 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 161 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 162 CGF.Builder.GetInsertBlock()); 163 emitUntiedSwitch(CGF); 164 } 165 } 166 void emitUntiedSwitch(CodeGenFunction &CGF) const { 167 if (Untied) { 168 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 169 CGF.GetAddrOfLocalVar(PartIDVar), 170 PartIDVar->getType()->castAs<PointerType>()); 171 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 172 PartIdLVal); 173 UntiedCodeGen(CGF); 174 CodeGenFunction::JumpDest CurPoint = 175 CGF.getJumpDestInCurrentScope(".untied.next."); 176 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 177 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 178 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 179 CGF.Builder.GetInsertBlock()); 180 CGF.EmitBranchThroughCleanup(CurPoint); 181 CGF.EmitBlock(CurPoint.getBlock()); 182 } 183 } 184 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 185 }; 186 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 187 const VarDecl *ThreadIDVar, 188 const RegionCodeGenTy &CodeGen, 189 OpenMPDirectiveKind Kind, bool HasCancel, 190 const UntiedTaskActionTy &Action) 191 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 192 ThreadIDVar(ThreadIDVar), Action(Action) { 193 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 194 } 195 196 /// Get a variable or parameter for storing global thread id 197 /// inside OpenMP construct. 198 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 199 200 /// Get an LValue for the current ThreadID variable. 201 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 202 203 /// Get the name of the capture helper. 204 StringRef getHelperName() const override { return ".omp_outlined."; } 205 206 void emitUntiedSwitch(CodeGenFunction &CGF) override { 207 Action.emitUntiedSwitch(CGF); 208 } 209 210 static bool classof(const CGCapturedStmtInfo *Info) { 211 return CGOpenMPRegionInfo::classof(Info) && 212 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 213 TaskOutlinedRegion; 214 } 215 216 private: 217 /// A variable or parameter storing global thread id for OpenMP 218 /// constructs. 219 const VarDecl *ThreadIDVar; 220 /// Action for emitting code for untied tasks. 221 const UntiedTaskActionTy &Action; 222 }; 223 224 /// API for inlined captured statement code generation in OpenMP 225 /// constructs. 226 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 227 public: 228 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 229 const RegionCodeGenTy &CodeGen, 230 OpenMPDirectiveKind Kind, bool HasCancel) 231 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 232 OldCSI(OldCSI), 233 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 234 235 // Retrieve the value of the context parameter. 236 llvm::Value *getContextValue() const override { 237 if (OuterRegionInfo) 238 return OuterRegionInfo->getContextValue(); 239 llvm_unreachable("No context value for inlined OpenMP region"); 240 } 241 242 void setContextValue(llvm::Value *V) override { 243 if (OuterRegionInfo) { 244 OuterRegionInfo->setContextValue(V); 245 return; 246 } 247 llvm_unreachable("No context value for inlined OpenMP region"); 248 } 249 250 /// Lookup the captured field decl for a variable. 251 const FieldDecl *lookup(const VarDecl *VD) const override { 252 if (OuterRegionInfo) 253 return OuterRegionInfo->lookup(VD); 254 // If there is no outer outlined region,no need to lookup in a list of 255 // captured variables, we can use the original one. 256 return nullptr; 257 } 258 259 FieldDecl *getThisFieldDecl() const override { 260 if (OuterRegionInfo) 261 return OuterRegionInfo->getThisFieldDecl(); 262 return nullptr; 263 } 264 265 /// Get a variable or parameter for storing global thread id 266 /// inside OpenMP construct. 267 const VarDecl *getThreadIDVariable() const override { 268 if (OuterRegionInfo) 269 return OuterRegionInfo->getThreadIDVariable(); 270 return nullptr; 271 } 272 273 /// Get an LValue for the current ThreadID variable. 274 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 275 if (OuterRegionInfo) 276 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 277 llvm_unreachable("No LValue for inlined OpenMP construct"); 278 } 279 280 /// Get the name of the capture helper. 281 StringRef getHelperName() const override { 282 if (auto *OuterRegionInfo = getOldCSI()) 283 return OuterRegionInfo->getHelperName(); 284 llvm_unreachable("No helper name for inlined OpenMP construct"); 285 } 286 287 void emitUntiedSwitch(CodeGenFunction &CGF) override { 288 if (OuterRegionInfo) 289 OuterRegionInfo->emitUntiedSwitch(CGF); 290 } 291 292 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 293 294 static bool classof(const CGCapturedStmtInfo *Info) { 295 return CGOpenMPRegionInfo::classof(Info) && 296 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 297 } 298 299 ~CGOpenMPInlinedRegionInfo() override = default; 300 301 private: 302 /// CodeGen info about outer OpenMP region. 303 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 304 CGOpenMPRegionInfo *OuterRegionInfo; 305 }; 306 307 /// API for captured statement code generation in OpenMP target 308 /// constructs. For this captures, implicit parameters are used instead of the 309 /// captured fields. The name of the target region has to be unique in a given 310 /// application so it is provided by the client, because only the client has 311 /// the information to generate that. 312 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 313 public: 314 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 315 const RegionCodeGenTy &CodeGen, StringRef HelperName) 316 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 317 /*HasCancel=*/false), 318 HelperName(HelperName) {} 319 320 /// This is unused for target regions because each starts executing 321 /// with a single thread. 322 const VarDecl *getThreadIDVariable() const override { return nullptr; } 323 324 /// Get the name of the capture helper. 325 StringRef getHelperName() const override { return HelperName; } 326 327 static bool classof(const CGCapturedStmtInfo *Info) { 328 return CGOpenMPRegionInfo::classof(Info) && 329 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 330 } 331 332 private: 333 StringRef HelperName; 334 }; 335 336 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 337 llvm_unreachable("No codegen for expressions"); 338 } 339 /// API for generation of expressions captured in a innermost OpenMP 340 /// region. 341 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 342 public: 343 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 344 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 345 OMPD_unknown, 346 /*HasCancel=*/false), 347 PrivScope(CGF) { 348 // Make sure the globals captured in the provided statement are local by 349 // using the privatization logic. We assume the same variable is not 350 // captured more than once. 351 for (const auto &C : CS.captures()) { 352 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 353 continue; 354 355 const VarDecl *VD = C.getCapturedVar(); 356 if (VD->isLocalVarDeclOrParm()) 357 continue; 358 359 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 360 /*RefersToEnclosingVariableOrCapture=*/false, 361 VD->getType().getNonReferenceType(), VK_LValue, 362 C.getLocation()); 363 PrivScope.addPrivate( 364 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 365 } 366 (void)PrivScope.Privatize(); 367 } 368 369 /// Lookup the captured field decl for a variable. 370 const FieldDecl *lookup(const VarDecl *VD) const override { 371 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 372 return FD; 373 return nullptr; 374 } 375 376 /// Emit the captured statement body. 377 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 378 llvm_unreachable("No body for expressions"); 379 } 380 381 /// Get a variable or parameter for storing global thread id 382 /// inside OpenMP construct. 383 const VarDecl *getThreadIDVariable() const override { 384 llvm_unreachable("No thread id for expressions"); 385 } 386 387 /// Get the name of the capture helper. 388 StringRef getHelperName() const override { 389 llvm_unreachable("No helper name for expressions"); 390 } 391 392 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 393 394 private: 395 /// Private scope to capture global variables. 396 CodeGenFunction::OMPPrivateScope PrivScope; 397 }; 398 399 /// RAII for emitting code of OpenMP constructs. 400 class InlinedOpenMPRegionRAII { 401 CodeGenFunction &CGF; 402 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 403 FieldDecl *LambdaThisCaptureField = nullptr; 404 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 405 406 public: 407 /// Constructs region for combined constructs. 408 /// \param CodeGen Code generation sequence for combined directives. Includes 409 /// a list of functions used for code generation of implicitly inlined 410 /// regions. 411 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 412 OpenMPDirectiveKind Kind, bool HasCancel) 413 : CGF(CGF) { 414 // Start emission for the construct. 415 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 416 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 417 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 418 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 419 CGF.LambdaThisCaptureField = nullptr; 420 BlockInfo = CGF.BlockInfo; 421 CGF.BlockInfo = nullptr; 422 } 423 424 ~InlinedOpenMPRegionRAII() { 425 // Restore original CapturedStmtInfo only if we're done with code emission. 426 auto *OldCSI = 427 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 428 delete CGF.CapturedStmtInfo; 429 CGF.CapturedStmtInfo = OldCSI; 430 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 431 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 432 CGF.BlockInfo = BlockInfo; 433 } 434 }; 435 436 /// Values for bit flags used in the ident_t to describe the fields. 437 /// All enumeric elements are named and described in accordance with the code 438 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 439 enum OpenMPLocationFlags : unsigned { 440 /// Use trampoline for internal microtask. 441 OMP_IDENT_IMD = 0x01, 442 /// Use c-style ident structure. 443 OMP_IDENT_KMPC = 0x02, 444 /// Atomic reduction option for kmpc_reduce. 445 OMP_ATOMIC_REDUCE = 0x10, 446 /// Explicit 'barrier' directive. 447 OMP_IDENT_BARRIER_EXPL = 0x20, 448 /// Implicit barrier in code. 449 OMP_IDENT_BARRIER_IMPL = 0x40, 450 /// Implicit barrier in 'for' directive. 451 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 452 /// Implicit barrier in 'sections' directive. 453 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 454 /// Implicit barrier in 'single' directive. 455 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 456 /// Call of __kmp_for_static_init for static loop. 457 OMP_IDENT_WORK_LOOP = 0x200, 458 /// Call of __kmp_for_static_init for sections. 459 OMP_IDENT_WORK_SECTIONS = 0x400, 460 /// Call of __kmp_for_static_init for distribute. 461 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 462 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 463 }; 464 465 namespace { 466 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 467 /// Values for bit flags for marking which requires clauses have been used. 468 enum OpenMPOffloadingRequiresDirFlags : int64_t { 469 /// flag undefined. 470 OMP_REQ_UNDEFINED = 0x000, 471 /// no requires clause present. 472 OMP_REQ_NONE = 0x001, 473 /// reverse_offload clause. 474 OMP_REQ_REVERSE_OFFLOAD = 0x002, 475 /// unified_address clause. 476 OMP_REQ_UNIFIED_ADDRESS = 0x004, 477 /// unified_shared_memory clause. 478 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 479 /// dynamic_allocators clause. 480 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 481 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 482 }; 483 484 enum OpenMPOffloadingReservedDeviceIDs { 485 /// Device ID if the device was not defined, runtime should get it 486 /// from environment variables in the spec. 487 OMP_DEVICEID_UNDEF = -1, 488 }; 489 } // anonymous namespace 490 491 /// Describes ident structure that describes a source location. 492 /// All descriptions are taken from 493 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 494 /// Original structure: 495 /// typedef struct ident { 496 /// kmp_int32 reserved_1; /**< might be used in Fortran; 497 /// see above */ 498 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 499 /// KMP_IDENT_KMPC identifies this union 500 /// member */ 501 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 502 /// see above */ 503 ///#if USE_ITT_BUILD 504 /// /* but currently used for storing 505 /// region-specific ITT */ 506 /// /* contextual information. */ 507 ///#endif /* USE_ITT_BUILD */ 508 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 509 /// C++ */ 510 /// char const *psource; /**< String describing the source location. 511 /// The string is composed of semi-colon separated 512 // fields which describe the source file, 513 /// the function and a pair of line numbers that 514 /// delimit the construct. 515 /// */ 516 /// } ident_t; 517 enum IdentFieldIndex { 518 /// might be used in Fortran 519 IdentField_Reserved_1, 520 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 521 IdentField_Flags, 522 /// Not really used in Fortran any more 523 IdentField_Reserved_2, 524 /// Source[4] in Fortran, do not use for C++ 525 IdentField_Reserved_3, 526 /// String describing the source location. The string is composed of 527 /// semi-colon separated fields which describe the source file, the function 528 /// and a pair of line numbers that delimit the construct. 529 IdentField_PSource 530 }; 531 532 /// Schedule types for 'omp for' loops (these enumerators are taken from 533 /// the enum sched_type in kmp.h). 534 enum OpenMPSchedType { 535 /// Lower bound for default (unordered) versions. 536 OMP_sch_lower = 32, 537 OMP_sch_static_chunked = 33, 538 OMP_sch_static = 34, 539 OMP_sch_dynamic_chunked = 35, 540 OMP_sch_guided_chunked = 36, 541 OMP_sch_runtime = 37, 542 OMP_sch_auto = 38, 543 /// static with chunk adjustment (e.g., simd) 544 OMP_sch_static_balanced_chunked = 45, 545 /// Lower bound for 'ordered' versions. 546 OMP_ord_lower = 64, 547 OMP_ord_static_chunked = 65, 548 OMP_ord_static = 66, 549 OMP_ord_dynamic_chunked = 67, 550 OMP_ord_guided_chunked = 68, 551 OMP_ord_runtime = 69, 552 OMP_ord_auto = 70, 553 OMP_sch_default = OMP_sch_static, 554 /// dist_schedule types 555 OMP_dist_sch_static_chunked = 91, 556 OMP_dist_sch_static = 92, 557 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 558 /// Set if the monotonic schedule modifier was present. 559 OMP_sch_modifier_monotonic = (1 << 29), 560 /// Set if the nonmonotonic schedule modifier was present. 561 OMP_sch_modifier_nonmonotonic = (1 << 30), 562 }; 563 564 enum OpenMPRTLFunction { 565 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 566 /// kmpc_micro microtask, ...); 567 OMPRTL__kmpc_fork_call, 568 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 569 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 570 OMPRTL__kmpc_threadprivate_cached, 571 /// Call to void __kmpc_threadprivate_register( ident_t *, 572 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 573 OMPRTL__kmpc_threadprivate_register, 574 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 575 OMPRTL__kmpc_global_thread_num, 576 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 577 // kmp_critical_name *crit); 578 OMPRTL__kmpc_critical, 579 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 580 // global_tid, kmp_critical_name *crit, uintptr_t hint); 581 OMPRTL__kmpc_critical_with_hint, 582 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 583 // kmp_critical_name *crit); 584 OMPRTL__kmpc_end_critical, 585 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 586 // global_tid); 587 OMPRTL__kmpc_cancel_barrier, 588 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 589 OMPRTL__kmpc_barrier, 590 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 591 OMPRTL__kmpc_for_static_fini, 592 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 593 // global_tid); 594 OMPRTL__kmpc_serialized_parallel, 595 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 596 // global_tid); 597 OMPRTL__kmpc_end_serialized_parallel, 598 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 599 // kmp_int32 num_threads); 600 OMPRTL__kmpc_push_num_threads, 601 // Call to void __kmpc_flush(ident_t *loc); 602 OMPRTL__kmpc_flush, 603 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 604 OMPRTL__kmpc_master, 605 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 606 OMPRTL__kmpc_end_master, 607 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 608 // int end_part); 609 OMPRTL__kmpc_omp_taskyield, 610 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 611 OMPRTL__kmpc_single, 612 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 613 OMPRTL__kmpc_end_single, 614 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 615 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 616 // kmp_routine_entry_t *task_entry); 617 OMPRTL__kmpc_omp_task_alloc, 618 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 619 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 620 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 621 // kmp_int64 device_id); 622 OMPRTL__kmpc_omp_target_task_alloc, 623 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 624 // new_task); 625 OMPRTL__kmpc_omp_task, 626 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 627 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 628 // kmp_int32 didit); 629 OMPRTL__kmpc_copyprivate, 630 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 631 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 632 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 633 OMPRTL__kmpc_reduce, 634 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 635 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 636 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 637 // *lck); 638 OMPRTL__kmpc_reduce_nowait, 639 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 640 // kmp_critical_name *lck); 641 OMPRTL__kmpc_end_reduce, 642 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 643 // kmp_critical_name *lck); 644 OMPRTL__kmpc_end_reduce_nowait, 645 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 646 // kmp_task_t * new_task); 647 OMPRTL__kmpc_omp_task_begin_if0, 648 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 649 // kmp_task_t * new_task); 650 OMPRTL__kmpc_omp_task_complete_if0, 651 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 652 OMPRTL__kmpc_ordered, 653 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 654 OMPRTL__kmpc_end_ordered, 655 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 656 // global_tid); 657 OMPRTL__kmpc_omp_taskwait, 658 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 659 OMPRTL__kmpc_taskgroup, 660 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 661 OMPRTL__kmpc_end_taskgroup, 662 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 663 // int proc_bind); 664 OMPRTL__kmpc_push_proc_bind, 665 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 666 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 667 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 668 OMPRTL__kmpc_omp_task_with_deps, 669 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 670 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 671 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 672 OMPRTL__kmpc_omp_wait_deps, 673 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 674 // global_tid, kmp_int32 cncl_kind); 675 OMPRTL__kmpc_cancellationpoint, 676 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 677 // kmp_int32 cncl_kind); 678 OMPRTL__kmpc_cancel, 679 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 680 // kmp_int32 num_teams, kmp_int32 thread_limit); 681 OMPRTL__kmpc_push_num_teams, 682 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 683 // microtask, ...); 684 OMPRTL__kmpc_fork_teams, 685 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 686 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 687 // sched, kmp_uint64 grainsize, void *task_dup); 688 OMPRTL__kmpc_taskloop, 689 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 690 // num_dims, struct kmp_dim *dims); 691 OMPRTL__kmpc_doacross_init, 692 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 693 OMPRTL__kmpc_doacross_fini, 694 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 695 // *vec); 696 OMPRTL__kmpc_doacross_post, 697 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 698 // *vec); 699 OMPRTL__kmpc_doacross_wait, 700 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 701 // *data); 702 OMPRTL__kmpc_task_reduction_init, 703 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 704 // *d); 705 OMPRTL__kmpc_task_reduction_get_th_data, 706 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 707 OMPRTL__kmpc_alloc, 708 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 709 OMPRTL__kmpc_free, 710 711 // 712 // Offloading related calls 713 // 714 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 715 // size); 716 OMPRTL__kmpc_push_target_tripcount, 717 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 718 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 719 // *arg_types); 720 OMPRTL__tgt_target, 721 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 722 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 723 // *arg_types); 724 OMPRTL__tgt_target_nowait, 725 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 726 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 727 // *arg_types, int32_t num_teams, int32_t thread_limit); 728 OMPRTL__tgt_target_teams, 729 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 730 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 731 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 732 OMPRTL__tgt_target_teams_nowait, 733 // Call to void __tgt_register_requires(int64_t flags); 734 OMPRTL__tgt_register_requires, 735 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 736 OMPRTL__tgt_register_lib, 737 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 738 OMPRTL__tgt_unregister_lib, 739 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 740 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 741 OMPRTL__tgt_target_data_begin, 742 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 743 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 744 // *arg_types); 745 OMPRTL__tgt_target_data_begin_nowait, 746 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 747 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 748 OMPRTL__tgt_target_data_end, 749 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 750 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 751 // *arg_types); 752 OMPRTL__tgt_target_data_end_nowait, 753 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 754 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 755 OMPRTL__tgt_target_data_update, 756 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 757 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 758 // *arg_types); 759 OMPRTL__tgt_target_data_update_nowait, 760 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 761 OMPRTL__tgt_mapper_num_components, 762 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 763 // *base, void *begin, int64_t size, int64_t type); 764 OMPRTL__tgt_push_mapper_component, 765 }; 766 767 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 768 /// region. 769 class CleanupTy final : public EHScopeStack::Cleanup { 770 PrePostActionTy *Action; 771 772 public: 773 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 774 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 775 if (!CGF.HaveInsertPoint()) 776 return; 777 Action->Exit(CGF); 778 } 779 }; 780 781 } // anonymous namespace 782 783 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 784 CodeGenFunction::RunCleanupsScope Scope(CGF); 785 if (PrePostAction) { 786 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 787 Callback(CodeGen, CGF, *PrePostAction); 788 } else { 789 PrePostActionTy Action; 790 Callback(CodeGen, CGF, Action); 791 } 792 } 793 794 /// Check if the combiner is a call to UDR combiner and if it is so return the 795 /// UDR decl used for reduction. 796 static const OMPDeclareReductionDecl * 797 getReductionInit(const Expr *ReductionOp) { 798 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 799 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 800 if (const auto *DRE = 801 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 802 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 803 return DRD; 804 return nullptr; 805 } 806 807 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 808 const OMPDeclareReductionDecl *DRD, 809 const Expr *InitOp, 810 Address Private, Address Original, 811 QualType Ty) { 812 if (DRD->getInitializer()) { 813 std::pair<llvm::Function *, llvm::Function *> Reduction = 814 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 815 const auto *CE = cast<CallExpr>(InitOp); 816 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 817 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 818 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 819 const auto *LHSDRE = 820 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 821 const auto *RHSDRE = 822 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 823 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 824 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 825 [=]() { return Private; }); 826 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 827 [=]() { return Original; }); 828 (void)PrivateScope.Privatize(); 829 RValue Func = RValue::get(Reduction.second); 830 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 831 CGF.EmitIgnoredExpr(InitOp); 832 } else { 833 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 834 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 835 auto *GV = new llvm::GlobalVariable( 836 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 837 llvm::GlobalValue::PrivateLinkage, Init, Name); 838 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 839 RValue InitRVal; 840 switch (CGF.getEvaluationKind(Ty)) { 841 case TEK_Scalar: 842 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 843 break; 844 case TEK_Complex: 845 InitRVal = 846 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 847 break; 848 case TEK_Aggregate: 849 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 850 break; 851 } 852 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 853 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 854 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 855 /*IsInitializer=*/false); 856 } 857 } 858 859 /// Emit initialization of arrays of complex types. 860 /// \param DestAddr Address of the array. 861 /// \param Type Type of array. 862 /// \param Init Initial expression of array. 863 /// \param SrcAddr Address of the original array. 864 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 865 QualType Type, bool EmitDeclareReductionInit, 866 const Expr *Init, 867 const OMPDeclareReductionDecl *DRD, 868 Address SrcAddr = Address::invalid()) { 869 // Perform element-by-element initialization. 870 QualType ElementTy; 871 872 // Drill down to the base element type on both arrays. 873 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 874 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 875 DestAddr = 876 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 877 if (DRD) 878 SrcAddr = 879 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 880 881 llvm::Value *SrcBegin = nullptr; 882 if (DRD) 883 SrcBegin = SrcAddr.getPointer(); 884 llvm::Value *DestBegin = DestAddr.getPointer(); 885 // Cast from pointer to array type to pointer to single element. 886 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 887 // The basic structure here is a while-do loop. 888 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 889 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 890 llvm::Value *IsEmpty = 891 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 892 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 893 894 // Enter the loop body, making that address the current address. 895 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 896 CGF.EmitBlock(BodyBB); 897 898 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 899 900 llvm::PHINode *SrcElementPHI = nullptr; 901 Address SrcElementCurrent = Address::invalid(); 902 if (DRD) { 903 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 904 "omp.arraycpy.srcElementPast"); 905 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 906 SrcElementCurrent = 907 Address(SrcElementPHI, 908 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 909 } 910 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 911 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 912 DestElementPHI->addIncoming(DestBegin, EntryBB); 913 Address DestElementCurrent = 914 Address(DestElementPHI, 915 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 916 917 // Emit copy. 918 { 919 CodeGenFunction::RunCleanupsScope InitScope(CGF); 920 if (EmitDeclareReductionInit) { 921 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 922 SrcElementCurrent, ElementTy); 923 } else 924 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 925 /*IsInitializer=*/false); 926 } 927 928 if (DRD) { 929 // Shift the address forward by one element. 930 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 931 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 932 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 933 } 934 935 // Shift the address forward by one element. 936 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 937 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 938 // Check whether we've reached the end. 939 llvm::Value *Done = 940 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 941 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 942 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 943 944 // Done. 945 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 946 } 947 948 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 949 return CGF.EmitOMPSharedLValue(E); 950 } 951 952 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 953 const Expr *E) { 954 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 955 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 956 return LValue(); 957 } 958 959 void ReductionCodeGen::emitAggregateInitialization( 960 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 961 const OMPDeclareReductionDecl *DRD) { 962 // Emit VarDecl with copy init for arrays. 963 // Get the address of the original variable captured in current 964 // captured region. 965 const auto *PrivateVD = 966 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 967 bool EmitDeclareReductionInit = 968 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 969 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 970 EmitDeclareReductionInit, 971 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 972 : PrivateVD->getInit(), 973 DRD, SharedLVal.getAddress(CGF)); 974 } 975 976 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 977 ArrayRef<const Expr *> Privates, 978 ArrayRef<const Expr *> ReductionOps) { 979 ClausesData.reserve(Shareds.size()); 980 SharedAddresses.reserve(Shareds.size()); 981 Sizes.reserve(Shareds.size()); 982 BaseDecls.reserve(Shareds.size()); 983 auto IPriv = Privates.begin(); 984 auto IRed = ReductionOps.begin(); 985 for (const Expr *Ref : Shareds) { 986 ClausesData.emplace_back(Ref, *IPriv, *IRed); 987 std::advance(IPriv, 1); 988 std::advance(IRed, 1); 989 } 990 } 991 992 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 993 assert(SharedAddresses.size() == N && 994 "Number of generated lvalues must be exactly N."); 995 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 996 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 997 SharedAddresses.emplace_back(First, Second); 998 } 999 1000 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 1001 const auto *PrivateVD = 1002 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1003 QualType PrivateType = PrivateVD->getType(); 1004 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1005 if (!PrivateType->isVariablyModifiedType()) { 1006 Sizes.emplace_back( 1007 CGF.getTypeSize( 1008 SharedAddresses[N].first.getType().getNonReferenceType()), 1009 nullptr); 1010 return; 1011 } 1012 llvm::Value *Size; 1013 llvm::Value *SizeInChars; 1014 auto *ElemType = cast<llvm::PointerType>( 1015 SharedAddresses[N].first.getPointer(CGF)->getType()) 1016 ->getElementType(); 1017 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1018 if (AsArraySection) { 1019 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1020 SharedAddresses[N].first.getPointer(CGF)); 1021 Size = CGF.Builder.CreateNUWAdd( 1022 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1023 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1024 } else { 1025 SizeInChars = CGF.getTypeSize( 1026 SharedAddresses[N].first.getType().getNonReferenceType()); 1027 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1028 } 1029 Sizes.emplace_back(SizeInChars, Size); 1030 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1031 CGF, 1032 cast<OpaqueValueExpr>( 1033 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1034 RValue::get(Size)); 1035 CGF.EmitVariablyModifiedType(PrivateType); 1036 } 1037 1038 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1039 llvm::Value *Size) { 1040 const auto *PrivateVD = 1041 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1042 QualType PrivateType = PrivateVD->getType(); 1043 if (!PrivateType->isVariablyModifiedType()) { 1044 assert(!Size && !Sizes[N].second && 1045 "Size should be nullptr for non-variably modified reduction " 1046 "items."); 1047 return; 1048 } 1049 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1050 CGF, 1051 cast<OpaqueValueExpr>( 1052 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1053 RValue::get(Size)); 1054 CGF.EmitVariablyModifiedType(PrivateType); 1055 } 1056 1057 void ReductionCodeGen::emitInitialization( 1058 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1059 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1060 assert(SharedAddresses.size() > N && "No variable was generated"); 1061 const auto *PrivateVD = 1062 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1063 const OMPDeclareReductionDecl *DRD = 1064 getReductionInit(ClausesData[N].ReductionOp); 1065 QualType PrivateType = PrivateVD->getType(); 1066 PrivateAddr = CGF.Builder.CreateElementBitCast( 1067 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1068 QualType SharedType = SharedAddresses[N].first.getType(); 1069 SharedLVal = CGF.MakeAddrLValue( 1070 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1071 CGF.ConvertTypeForMem(SharedType)), 1072 SharedType, SharedAddresses[N].first.getBaseInfo(), 1073 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1074 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1075 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1076 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1077 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1078 PrivateAddr, SharedLVal.getAddress(CGF), 1079 SharedLVal.getType()); 1080 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1081 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1082 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1083 PrivateVD->getType().getQualifiers(), 1084 /*IsInitializer=*/false); 1085 } 1086 } 1087 1088 bool ReductionCodeGen::needCleanups(unsigned N) { 1089 const auto *PrivateVD = 1090 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1091 QualType PrivateType = PrivateVD->getType(); 1092 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1093 return DTorKind != QualType::DK_none; 1094 } 1095 1096 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1097 Address PrivateAddr) { 1098 const auto *PrivateVD = 1099 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1100 QualType PrivateType = PrivateVD->getType(); 1101 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1102 if (needCleanups(N)) { 1103 PrivateAddr = CGF.Builder.CreateElementBitCast( 1104 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1105 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1106 } 1107 } 1108 1109 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1110 LValue BaseLV) { 1111 BaseTy = BaseTy.getNonReferenceType(); 1112 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1113 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1114 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1115 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1116 } else { 1117 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1118 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1119 } 1120 BaseTy = BaseTy->getPointeeType(); 1121 } 1122 return CGF.MakeAddrLValue( 1123 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1124 CGF.ConvertTypeForMem(ElTy)), 1125 BaseLV.getType(), BaseLV.getBaseInfo(), 1126 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1127 } 1128 1129 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1130 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1131 llvm::Value *Addr) { 1132 Address Tmp = Address::invalid(); 1133 Address TopTmp = Address::invalid(); 1134 Address MostTopTmp = Address::invalid(); 1135 BaseTy = BaseTy.getNonReferenceType(); 1136 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1137 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1138 Tmp = CGF.CreateMemTemp(BaseTy); 1139 if (TopTmp.isValid()) 1140 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1141 else 1142 MostTopTmp = Tmp; 1143 TopTmp = Tmp; 1144 BaseTy = BaseTy->getPointeeType(); 1145 } 1146 llvm::Type *Ty = BaseLVType; 1147 if (Tmp.isValid()) 1148 Ty = Tmp.getElementType(); 1149 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1150 if (Tmp.isValid()) { 1151 CGF.Builder.CreateStore(Addr, Tmp); 1152 return MostTopTmp; 1153 } 1154 return Address(Addr, BaseLVAlignment); 1155 } 1156 1157 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1158 const VarDecl *OrigVD = nullptr; 1159 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1160 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1161 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1162 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1163 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1164 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1165 DE = cast<DeclRefExpr>(Base); 1166 OrigVD = cast<VarDecl>(DE->getDecl()); 1167 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1168 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1169 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1170 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1171 DE = cast<DeclRefExpr>(Base); 1172 OrigVD = cast<VarDecl>(DE->getDecl()); 1173 } 1174 return OrigVD; 1175 } 1176 1177 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1178 Address PrivateAddr) { 1179 const DeclRefExpr *DE; 1180 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1181 BaseDecls.emplace_back(OrigVD); 1182 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1183 LValue BaseLValue = 1184 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1185 OriginalBaseLValue); 1186 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1187 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1188 llvm::Value *PrivatePointer = 1189 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1190 PrivateAddr.getPointer(), 1191 SharedAddresses[N].first.getAddress(CGF).getType()); 1192 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1193 return castToBase(CGF, OrigVD->getType(), 1194 SharedAddresses[N].first.getType(), 1195 OriginalBaseLValue.getAddress(CGF).getType(), 1196 OriginalBaseLValue.getAlignment(), Ptr); 1197 } 1198 BaseDecls.emplace_back( 1199 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1200 return PrivateAddr; 1201 } 1202 1203 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1204 const OMPDeclareReductionDecl *DRD = 1205 getReductionInit(ClausesData[N].ReductionOp); 1206 return DRD && DRD->getInitializer(); 1207 } 1208 1209 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1210 return CGF.EmitLoadOfPointerLValue( 1211 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1212 getThreadIDVariable()->getType()->castAs<PointerType>()); 1213 } 1214 1215 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1216 if (!CGF.HaveInsertPoint()) 1217 return; 1218 // 1.2.2 OpenMP Language Terminology 1219 // Structured block - An executable statement with a single entry at the 1220 // top and a single exit at the bottom. 1221 // The point of exit cannot be a branch out of the structured block. 1222 // longjmp() and throw() must not violate the entry/exit criteria. 1223 CGF.EHStack.pushTerminate(); 1224 CodeGen(CGF); 1225 CGF.EHStack.popTerminate(); 1226 } 1227 1228 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1229 CodeGenFunction &CGF) { 1230 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1231 getThreadIDVariable()->getType(), 1232 AlignmentSource::Decl); 1233 } 1234 1235 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1236 QualType FieldTy) { 1237 auto *Field = FieldDecl::Create( 1238 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1239 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1240 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1241 Field->setAccess(AS_public); 1242 DC->addDecl(Field); 1243 return Field; 1244 } 1245 1246 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1247 StringRef Separator) 1248 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1249 OffloadEntriesInfoManager(CGM) { 1250 ASTContext &C = CGM.getContext(); 1251 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1252 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1253 RD->startDefinition(); 1254 // reserved_1 1255 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1256 // flags 1257 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1258 // reserved_2 1259 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1260 // reserved_3 1261 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1262 // psource 1263 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1264 RD->completeDefinition(); 1265 IdentQTy = C.getRecordType(RD); 1266 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1267 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1268 1269 loadOffloadInfoMetadata(); 1270 } 1271 1272 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1273 const GlobalDecl &OldGD, 1274 llvm::GlobalValue *OrigAddr, 1275 bool IsForDefinition) { 1276 // Emit at least a definition for the aliasee if the the address of the 1277 // original function is requested. 1278 if (IsForDefinition || OrigAddr) 1279 (void)CGM.GetAddrOfGlobal(NewGD); 1280 StringRef NewMangledName = CGM.getMangledName(NewGD); 1281 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1282 if (Addr && !Addr->isDeclaration()) { 1283 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1284 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD); 1285 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1286 1287 // Create a reference to the named value. This ensures that it is emitted 1288 // if a deferred decl. 1289 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1290 1291 // Create the new alias itself, but don't set a name yet. 1292 auto *GA = 1293 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1294 1295 if (OrigAddr) { 1296 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1297 1298 GA->takeName(OrigAddr); 1299 OrigAddr->replaceAllUsesWith( 1300 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1301 OrigAddr->eraseFromParent(); 1302 } else { 1303 GA->setName(CGM.getMangledName(OldGD)); 1304 } 1305 1306 // Set attributes which are particular to an alias; this is a 1307 // specialization of the attributes which may be set on a global function. 1308 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1309 D->isWeakImported()) 1310 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1311 1312 CGM.SetCommonAttributes(OldGD, GA); 1313 return true; 1314 } 1315 return false; 1316 } 1317 1318 void CGOpenMPRuntime::clear() { 1319 InternalVars.clear(); 1320 // Clean non-target variable declarations possibly used only in debug info. 1321 for (const auto &Data : EmittedNonTargetVariables) { 1322 if (!Data.getValue().pointsToAliveValue()) 1323 continue; 1324 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1325 if (!GV) 1326 continue; 1327 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1328 continue; 1329 GV->eraseFromParent(); 1330 } 1331 // Emit aliases for the deferred aliasees. 1332 for (const auto &Pair : DeferredVariantFunction) { 1333 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1334 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1335 // If not able to emit alias, just emit original declaration. 1336 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1337 /*IsForDefinition=*/false); 1338 } 1339 } 1340 1341 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1342 SmallString<128> Buffer; 1343 llvm::raw_svector_ostream OS(Buffer); 1344 StringRef Sep = FirstSeparator; 1345 for (StringRef Part : Parts) { 1346 OS << Sep << Part; 1347 Sep = Separator; 1348 } 1349 return OS.str(); 1350 } 1351 1352 static llvm::Function * 1353 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1354 const Expr *CombinerInitializer, const VarDecl *In, 1355 const VarDecl *Out, bool IsCombiner) { 1356 // void .omp_combiner.(Ty *in, Ty *out); 1357 ASTContext &C = CGM.getContext(); 1358 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1359 FunctionArgList Args; 1360 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1361 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1362 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1363 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1364 Args.push_back(&OmpOutParm); 1365 Args.push_back(&OmpInParm); 1366 const CGFunctionInfo &FnInfo = 1367 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1368 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1369 std::string Name = CGM.getOpenMPRuntime().getName( 1370 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1371 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1372 Name, &CGM.getModule()); 1373 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1374 if (CGM.getLangOpts().Optimize) { 1375 Fn->removeFnAttr(llvm::Attribute::NoInline); 1376 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1377 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1378 } 1379 CodeGenFunction CGF(CGM); 1380 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1381 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1382 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1383 Out->getLocation()); 1384 CodeGenFunction::OMPPrivateScope Scope(CGF); 1385 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1386 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1387 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1388 .getAddress(CGF); 1389 }); 1390 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1391 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1392 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1393 .getAddress(CGF); 1394 }); 1395 (void)Scope.Privatize(); 1396 if (!IsCombiner && Out->hasInit() && 1397 !CGF.isTrivialInitializer(Out->getInit())) { 1398 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1399 Out->getType().getQualifiers(), 1400 /*IsInitializer=*/true); 1401 } 1402 if (CombinerInitializer) 1403 CGF.EmitIgnoredExpr(CombinerInitializer); 1404 Scope.ForceCleanup(); 1405 CGF.FinishFunction(); 1406 return Fn; 1407 } 1408 1409 void CGOpenMPRuntime::emitUserDefinedReduction( 1410 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1411 if (UDRMap.count(D) > 0) 1412 return; 1413 llvm::Function *Combiner = emitCombinerOrInitializer( 1414 CGM, D->getType(), D->getCombiner(), 1415 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1416 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1417 /*IsCombiner=*/true); 1418 llvm::Function *Initializer = nullptr; 1419 if (const Expr *Init = D->getInitializer()) { 1420 Initializer = emitCombinerOrInitializer( 1421 CGM, D->getType(), 1422 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1423 : nullptr, 1424 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1425 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1426 /*IsCombiner=*/false); 1427 } 1428 UDRMap.try_emplace(D, Combiner, Initializer); 1429 if (CGF) { 1430 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1431 Decls.second.push_back(D); 1432 } 1433 } 1434 1435 std::pair<llvm::Function *, llvm::Function *> 1436 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1437 auto I = UDRMap.find(D); 1438 if (I != UDRMap.end()) 1439 return I->second; 1440 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1441 return UDRMap.lookup(D); 1442 } 1443 1444 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1445 // Builder if one is present. 1446 struct PushAndPopStackRAII { 1447 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1448 bool HasCancel) 1449 : OMPBuilder(OMPBuilder) { 1450 if (!OMPBuilder) 1451 return; 1452 1453 // The following callback is the crucial part of clangs cleanup process. 1454 // 1455 // NOTE: 1456 // Once the OpenMPIRBuilder is used to create parallel regions (and 1457 // similar), the cancellation destination (Dest below) is determined via 1458 // IP. That means if we have variables to finalize we split the block at IP, 1459 // use the new block (=BB) as destination to build a JumpDest (via 1460 // getJumpDestInCurrentScope(BB)) which then is fed to 1461 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1462 // to push & pop an FinalizationInfo object. 1463 // The FiniCB will still be needed but at the point where the 1464 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1465 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1466 assert(IP.getBlock()->end() == IP.getPoint() && 1467 "Clang CG should cause non-terminated block!"); 1468 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1469 CGF.Builder.restoreIP(IP); 1470 CodeGenFunction::JumpDest Dest = 1471 CGF.getOMPCancelDestination(OMPD_parallel); 1472 CGF.EmitBranchThroughCleanup(Dest); 1473 }; 1474 1475 // TODO: Remove this once we emit parallel regions through the 1476 // OpenMPIRBuilder as it can do this setup internally. 1477 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1478 {FiniCB, OMPD_parallel, HasCancel}); 1479 OMPBuilder->pushFinalizationCB(std::move(FI)); 1480 } 1481 ~PushAndPopStackRAII() { 1482 if (OMPBuilder) 1483 OMPBuilder->popFinalizationCB(); 1484 } 1485 llvm::OpenMPIRBuilder *OMPBuilder; 1486 }; 1487 1488 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1489 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1490 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1491 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1492 assert(ThreadIDVar->getType()->isPointerType() && 1493 "thread id variable must be of type kmp_int32 *"); 1494 CodeGenFunction CGF(CGM, true); 1495 bool HasCancel = false; 1496 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1497 HasCancel = OPD->hasCancel(); 1498 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1499 HasCancel = OPSD->hasCancel(); 1500 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1501 HasCancel = OPFD->hasCancel(); 1502 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1503 HasCancel = OPFD->hasCancel(); 1504 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1505 HasCancel = OPFD->hasCancel(); 1506 else if (const auto *OPFD = 1507 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1508 HasCancel = OPFD->hasCancel(); 1509 else if (const auto *OPFD = 1510 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1511 HasCancel = OPFD->hasCancel(); 1512 1513 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1514 // parallel region to make cancellation barriers work properly. 1515 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder(); 1516 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel); 1517 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1518 HasCancel, OutlinedHelperName); 1519 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1520 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 1521 } 1522 1523 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1524 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1525 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1526 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1527 return emitParallelOrTeamsOutlinedFunction( 1528 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1529 } 1530 1531 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1532 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1533 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1534 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1535 return emitParallelOrTeamsOutlinedFunction( 1536 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1537 } 1538 1539 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1540 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1541 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1542 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1543 bool Tied, unsigned &NumberOfParts) { 1544 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1545 PrePostActionTy &) { 1546 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1547 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1548 llvm::Value *TaskArgs[] = { 1549 UpLoc, ThreadID, 1550 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1551 TaskTVar->getType()->castAs<PointerType>()) 1552 .getPointer(CGF)}; 1553 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1554 }; 1555 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1556 UntiedCodeGen); 1557 CodeGen.setAction(Action); 1558 assert(!ThreadIDVar->getType()->isPointerType() && 1559 "thread id variable must be of type kmp_int32 for tasks"); 1560 const OpenMPDirectiveKind Region = 1561 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1562 : OMPD_task; 1563 const CapturedStmt *CS = D.getCapturedStmt(Region); 1564 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1565 CodeGenFunction CGF(CGM, true); 1566 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1567 InnermostKind, 1568 TD ? TD->hasCancel() : false, Action); 1569 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1570 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1571 if (!Tied) 1572 NumberOfParts = Action.getNumberOfParts(); 1573 return Res; 1574 } 1575 1576 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1577 const RecordDecl *RD, const CGRecordLayout &RL, 1578 ArrayRef<llvm::Constant *> Data) { 1579 llvm::StructType *StructTy = RL.getLLVMType(); 1580 unsigned PrevIdx = 0; 1581 ConstantInitBuilder CIBuilder(CGM); 1582 auto DI = Data.begin(); 1583 for (const FieldDecl *FD : RD->fields()) { 1584 unsigned Idx = RL.getLLVMFieldNo(FD); 1585 // Fill the alignment. 1586 for (unsigned I = PrevIdx; I < Idx; ++I) 1587 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1588 PrevIdx = Idx + 1; 1589 Fields.add(*DI); 1590 ++DI; 1591 } 1592 } 1593 1594 template <class... As> 1595 static llvm::GlobalVariable * 1596 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1597 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1598 As &&... Args) { 1599 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1600 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1601 ConstantInitBuilder CIBuilder(CGM); 1602 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1603 buildStructValue(Fields, CGM, RD, RL, Data); 1604 return Fields.finishAndCreateGlobal( 1605 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1606 std::forward<As>(Args)...); 1607 } 1608 1609 template <typename T> 1610 static void 1611 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1612 ArrayRef<llvm::Constant *> Data, 1613 T &Parent) { 1614 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1615 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1616 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1617 buildStructValue(Fields, CGM, RD, RL, Data); 1618 Fields.finishAndAddTo(Parent); 1619 } 1620 1621 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1622 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1623 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1624 FlagsTy FlagsKey(Flags, Reserved2Flags); 1625 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1626 if (!Entry) { 1627 if (!DefaultOpenMPPSource) { 1628 // Initialize default location for psource field of ident_t structure of 1629 // all ident_t objects. Format is ";file;function;line;column;;". 1630 // Taken from 1631 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1632 DefaultOpenMPPSource = 1633 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1634 DefaultOpenMPPSource = 1635 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1636 } 1637 1638 llvm::Constant *Data[] = { 1639 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1640 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1641 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1642 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1643 llvm::GlobalValue *DefaultOpenMPLocation = 1644 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1645 llvm::GlobalValue::PrivateLinkage); 1646 DefaultOpenMPLocation->setUnnamedAddr( 1647 llvm::GlobalValue::UnnamedAddr::Global); 1648 1649 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1650 } 1651 return Address(Entry, Align); 1652 } 1653 1654 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1655 bool AtCurrentPoint) { 1656 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1657 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1658 1659 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1660 if (AtCurrentPoint) { 1661 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1662 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1663 } else { 1664 Elem.second.ServiceInsertPt = 1665 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1666 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1667 } 1668 } 1669 1670 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1671 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1672 if (Elem.second.ServiceInsertPt) { 1673 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1674 Elem.second.ServiceInsertPt = nullptr; 1675 Ptr->eraseFromParent(); 1676 } 1677 } 1678 1679 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1680 SourceLocation Loc, 1681 unsigned Flags) { 1682 Flags |= OMP_IDENT_KMPC; 1683 // If no debug info is generated - return global default location. 1684 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1685 Loc.isInvalid()) 1686 return getOrCreateDefaultLocation(Flags).getPointer(); 1687 1688 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1689 1690 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1691 Address LocValue = Address::invalid(); 1692 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1693 if (I != OpenMPLocThreadIDMap.end()) 1694 LocValue = Address(I->second.DebugLoc, Align); 1695 1696 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1697 // GetOpenMPThreadID was called before this routine. 1698 if (!LocValue.isValid()) { 1699 // Generate "ident_t .kmpc_loc.addr;" 1700 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1701 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1702 Elem.second.DebugLoc = AI.getPointer(); 1703 LocValue = AI; 1704 1705 if (!Elem.second.ServiceInsertPt) 1706 setLocThreadIdInsertPt(CGF); 1707 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1708 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1709 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1710 CGF.getTypeSize(IdentQTy)); 1711 } 1712 1713 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1714 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1715 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1716 LValue PSource = 1717 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1718 1719 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1720 if (OMPDebugLoc == nullptr) { 1721 SmallString<128> Buffer2; 1722 llvm::raw_svector_ostream OS2(Buffer2); 1723 // Build debug location 1724 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1725 OS2 << ";" << PLoc.getFilename() << ";"; 1726 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1727 OS2 << FD->getQualifiedNameAsString(); 1728 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1729 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1730 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1731 } 1732 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1733 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1734 1735 // Our callers always pass this to a runtime function, so for 1736 // convenience, go ahead and return a naked pointer. 1737 return LocValue.getPointer(); 1738 } 1739 1740 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1741 SourceLocation Loc) { 1742 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1743 1744 llvm::Value *ThreadID = nullptr; 1745 // Check whether we've already cached a load of the thread id in this 1746 // function. 1747 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1748 if (I != OpenMPLocThreadIDMap.end()) { 1749 ThreadID = I->second.ThreadID; 1750 if (ThreadID != nullptr) 1751 return ThreadID; 1752 } 1753 // If exceptions are enabled, do not use parameter to avoid possible crash. 1754 if (auto *OMPRegionInfo = 1755 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1756 if (OMPRegionInfo->getThreadIDVariable()) { 1757 // Check if this an outlined function with thread id passed as argument. 1758 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1759 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1760 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1761 !CGF.getLangOpts().CXXExceptions || 1762 CGF.Builder.GetInsertBlock() == TopBlock || 1763 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1764 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1765 TopBlock || 1766 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1767 CGF.Builder.GetInsertBlock()) { 1768 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1769 // If value loaded in entry block, cache it and use it everywhere in 1770 // function. 1771 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1772 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1773 Elem.second.ThreadID = ThreadID; 1774 } 1775 return ThreadID; 1776 } 1777 } 1778 } 1779 1780 // This is not an outlined function region - need to call __kmpc_int32 1781 // kmpc_global_thread_num(ident_t *loc). 1782 // Generate thread id value and cache this value for use across the 1783 // function. 1784 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1785 if (!Elem.second.ServiceInsertPt) 1786 setLocThreadIdInsertPt(CGF); 1787 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1788 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1789 llvm::CallInst *Call = CGF.Builder.CreateCall( 1790 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1791 emitUpdateLocation(CGF, Loc)); 1792 Call->setCallingConv(CGF.getRuntimeCC()); 1793 Elem.second.ThreadID = Call; 1794 return Call; 1795 } 1796 1797 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1798 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1799 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1800 clearLocThreadIdInsertPt(CGF); 1801 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1802 } 1803 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1804 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1805 UDRMap.erase(D); 1806 FunctionUDRMap.erase(CGF.CurFn); 1807 } 1808 auto I = FunctionUDMMap.find(CGF.CurFn); 1809 if (I != FunctionUDMMap.end()) { 1810 for(auto *D : I->second) 1811 UDMMap.erase(D); 1812 FunctionUDMMap.erase(I); 1813 } 1814 } 1815 1816 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1817 return IdentTy->getPointerTo(); 1818 } 1819 1820 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1821 if (!Kmpc_MicroTy) { 1822 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1823 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1824 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1825 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1826 } 1827 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1828 } 1829 1830 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1831 llvm::FunctionCallee RTLFn = nullptr; 1832 switch (static_cast<OpenMPRTLFunction>(Function)) { 1833 case OMPRTL__kmpc_fork_call: { 1834 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1835 // microtask, ...); 1836 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1837 getKmpc_MicroPointerTy()}; 1838 auto *FnTy = 1839 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1840 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1841 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1842 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1843 llvm::LLVMContext &Ctx = F->getContext(); 1844 llvm::MDBuilder MDB(Ctx); 1845 // Annotate the callback behavior of the __kmpc_fork_call: 1846 // - The callback callee is argument number 2 (microtask). 1847 // - The first two arguments of the callback callee are unknown (-1). 1848 // - All variadic arguments to the __kmpc_fork_call are passed to the 1849 // callback callee. 1850 F->addMetadata( 1851 llvm::LLVMContext::MD_callback, 1852 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1853 2, {-1, -1}, 1854 /* VarArgsArePassed */ true)})); 1855 } 1856 } 1857 break; 1858 } 1859 case OMPRTL__kmpc_global_thread_num: { 1860 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1861 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1862 auto *FnTy = 1863 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1864 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1865 break; 1866 } 1867 case OMPRTL__kmpc_threadprivate_cached: { 1868 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1869 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1870 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1871 CGM.VoidPtrTy, CGM.SizeTy, 1872 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1873 auto *FnTy = 1874 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1875 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1876 break; 1877 } 1878 case OMPRTL__kmpc_critical: { 1879 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1880 // kmp_critical_name *crit); 1881 llvm::Type *TypeParams[] = { 1882 getIdentTyPointerTy(), CGM.Int32Ty, 1883 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1884 auto *FnTy = 1885 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1886 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1887 break; 1888 } 1889 case OMPRTL__kmpc_critical_with_hint: { 1890 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1891 // kmp_critical_name *crit, uintptr_t hint); 1892 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1893 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1894 CGM.IntPtrTy}; 1895 auto *FnTy = 1896 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1897 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1898 break; 1899 } 1900 case OMPRTL__kmpc_threadprivate_register: { 1901 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1902 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1903 // typedef void *(*kmpc_ctor)(void *); 1904 auto *KmpcCtorTy = 1905 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1906 /*isVarArg*/ false)->getPointerTo(); 1907 // typedef void *(*kmpc_cctor)(void *, void *); 1908 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1909 auto *KmpcCopyCtorTy = 1910 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1911 /*isVarArg*/ false) 1912 ->getPointerTo(); 1913 // typedef void (*kmpc_dtor)(void *); 1914 auto *KmpcDtorTy = 1915 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1916 ->getPointerTo(); 1917 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1918 KmpcCopyCtorTy, KmpcDtorTy}; 1919 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1920 /*isVarArg*/ false); 1921 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1922 break; 1923 } 1924 case OMPRTL__kmpc_end_critical: { 1925 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1926 // kmp_critical_name *crit); 1927 llvm::Type *TypeParams[] = { 1928 getIdentTyPointerTy(), CGM.Int32Ty, 1929 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1930 auto *FnTy = 1931 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1932 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1933 break; 1934 } 1935 case OMPRTL__kmpc_cancel_barrier: { 1936 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1937 // global_tid); 1938 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1939 auto *FnTy = 1940 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1941 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1942 break; 1943 } 1944 case OMPRTL__kmpc_barrier: { 1945 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1946 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1947 auto *FnTy = 1948 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1949 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1950 break; 1951 } 1952 case OMPRTL__kmpc_for_static_fini: { 1953 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1954 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1955 auto *FnTy = 1956 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1957 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1958 break; 1959 } 1960 case OMPRTL__kmpc_push_num_threads: { 1961 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1962 // kmp_int32 num_threads) 1963 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1964 CGM.Int32Ty}; 1965 auto *FnTy = 1966 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1967 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1968 break; 1969 } 1970 case OMPRTL__kmpc_serialized_parallel: { 1971 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1972 // global_tid); 1973 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1974 auto *FnTy = 1975 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1976 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1977 break; 1978 } 1979 case OMPRTL__kmpc_end_serialized_parallel: { 1980 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1981 // global_tid); 1982 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1983 auto *FnTy = 1984 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1985 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1986 break; 1987 } 1988 case OMPRTL__kmpc_flush: { 1989 // Build void __kmpc_flush(ident_t *loc); 1990 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1991 auto *FnTy = 1992 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1993 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1994 break; 1995 } 1996 case OMPRTL__kmpc_master: { 1997 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1998 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1999 auto *FnTy = 2000 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2001 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 2002 break; 2003 } 2004 case OMPRTL__kmpc_end_master: { 2005 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 2006 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2007 auto *FnTy = 2008 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2009 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 2010 break; 2011 } 2012 case OMPRTL__kmpc_omp_taskyield: { 2013 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 2014 // int end_part); 2015 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2016 auto *FnTy = 2017 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2018 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 2019 break; 2020 } 2021 case OMPRTL__kmpc_single: { 2022 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 2023 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2024 auto *FnTy = 2025 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2026 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 2027 break; 2028 } 2029 case OMPRTL__kmpc_end_single: { 2030 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 2031 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2032 auto *FnTy = 2033 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2034 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 2035 break; 2036 } 2037 case OMPRTL__kmpc_omp_task_alloc: { 2038 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2039 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2040 // kmp_routine_entry_t *task_entry); 2041 assert(KmpRoutineEntryPtrTy != nullptr && 2042 "Type kmp_routine_entry_t must be created."); 2043 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2044 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 2045 // Return void * and then cast to particular kmp_task_t type. 2046 auto *FnTy = 2047 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2048 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 2049 break; 2050 } 2051 case OMPRTL__kmpc_omp_target_task_alloc: { 2052 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2053 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2054 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2055 assert(KmpRoutineEntryPtrTy != nullptr && 2056 "Type kmp_routine_entry_t must be created."); 2057 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2058 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2059 CGM.Int64Ty}; 2060 // Return void * and then cast to particular kmp_task_t type. 2061 auto *FnTy = 2062 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2063 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2064 break; 2065 } 2066 case OMPRTL__kmpc_omp_task: { 2067 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2068 // *new_task); 2069 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2070 CGM.VoidPtrTy}; 2071 auto *FnTy = 2072 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2073 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2074 break; 2075 } 2076 case OMPRTL__kmpc_copyprivate: { 2077 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2078 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2079 // kmp_int32 didit); 2080 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2081 auto *CpyFnTy = 2082 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2083 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2084 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2085 CGM.Int32Ty}; 2086 auto *FnTy = 2087 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2088 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2089 break; 2090 } 2091 case OMPRTL__kmpc_reduce: { 2092 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2093 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2094 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2095 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2096 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2097 /*isVarArg=*/false); 2098 llvm::Type *TypeParams[] = { 2099 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2100 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2101 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2102 auto *FnTy = 2103 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2104 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2105 break; 2106 } 2107 case OMPRTL__kmpc_reduce_nowait: { 2108 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2109 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2110 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2111 // *lck); 2112 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2113 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2114 /*isVarArg=*/false); 2115 llvm::Type *TypeParams[] = { 2116 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2117 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2118 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2119 auto *FnTy = 2120 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2121 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2122 break; 2123 } 2124 case OMPRTL__kmpc_end_reduce: { 2125 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2126 // kmp_critical_name *lck); 2127 llvm::Type *TypeParams[] = { 2128 getIdentTyPointerTy(), CGM.Int32Ty, 2129 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2130 auto *FnTy = 2131 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2132 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2133 break; 2134 } 2135 case OMPRTL__kmpc_end_reduce_nowait: { 2136 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2137 // kmp_critical_name *lck); 2138 llvm::Type *TypeParams[] = { 2139 getIdentTyPointerTy(), CGM.Int32Ty, 2140 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2141 auto *FnTy = 2142 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2143 RTLFn = 2144 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2145 break; 2146 } 2147 case OMPRTL__kmpc_omp_task_begin_if0: { 2148 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2149 // *new_task); 2150 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2151 CGM.VoidPtrTy}; 2152 auto *FnTy = 2153 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2154 RTLFn = 2155 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2156 break; 2157 } 2158 case OMPRTL__kmpc_omp_task_complete_if0: { 2159 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2160 // *new_task); 2161 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2162 CGM.VoidPtrTy}; 2163 auto *FnTy = 2164 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2165 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2166 /*Name=*/"__kmpc_omp_task_complete_if0"); 2167 break; 2168 } 2169 case OMPRTL__kmpc_ordered: { 2170 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2171 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2172 auto *FnTy = 2173 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2174 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2175 break; 2176 } 2177 case OMPRTL__kmpc_end_ordered: { 2178 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2179 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2180 auto *FnTy = 2181 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2182 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2183 break; 2184 } 2185 case OMPRTL__kmpc_omp_taskwait: { 2186 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2187 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2188 auto *FnTy = 2189 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2190 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2191 break; 2192 } 2193 case OMPRTL__kmpc_taskgroup: { 2194 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2195 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2196 auto *FnTy = 2197 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2198 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2199 break; 2200 } 2201 case OMPRTL__kmpc_end_taskgroup: { 2202 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2203 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2204 auto *FnTy = 2205 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2206 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2207 break; 2208 } 2209 case OMPRTL__kmpc_push_proc_bind: { 2210 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2211 // int proc_bind) 2212 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2213 auto *FnTy = 2214 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2215 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2216 break; 2217 } 2218 case OMPRTL__kmpc_omp_task_with_deps: { 2219 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2220 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2221 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2222 llvm::Type *TypeParams[] = { 2223 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2224 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2225 auto *FnTy = 2226 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2227 RTLFn = 2228 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2229 break; 2230 } 2231 case OMPRTL__kmpc_omp_wait_deps: { 2232 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2233 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2234 // kmp_depend_info_t *noalias_dep_list); 2235 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2236 CGM.Int32Ty, CGM.VoidPtrTy, 2237 CGM.Int32Ty, CGM.VoidPtrTy}; 2238 auto *FnTy = 2239 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2240 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2241 break; 2242 } 2243 case OMPRTL__kmpc_cancellationpoint: { 2244 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2245 // global_tid, kmp_int32 cncl_kind) 2246 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2247 auto *FnTy = 2248 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2249 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2250 break; 2251 } 2252 case OMPRTL__kmpc_cancel: { 2253 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2254 // kmp_int32 cncl_kind) 2255 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2256 auto *FnTy = 2257 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2258 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2259 break; 2260 } 2261 case OMPRTL__kmpc_push_num_teams: { 2262 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2263 // kmp_int32 num_teams, kmp_int32 num_threads) 2264 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2265 CGM.Int32Ty}; 2266 auto *FnTy = 2267 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2268 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2269 break; 2270 } 2271 case OMPRTL__kmpc_fork_teams: { 2272 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2273 // microtask, ...); 2274 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2275 getKmpc_MicroPointerTy()}; 2276 auto *FnTy = 2277 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2278 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2279 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2280 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2281 llvm::LLVMContext &Ctx = F->getContext(); 2282 llvm::MDBuilder MDB(Ctx); 2283 // Annotate the callback behavior of the __kmpc_fork_teams: 2284 // - The callback callee is argument number 2 (microtask). 2285 // - The first two arguments of the callback callee are unknown (-1). 2286 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2287 // callback callee. 2288 F->addMetadata( 2289 llvm::LLVMContext::MD_callback, 2290 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2291 2, {-1, -1}, 2292 /* VarArgsArePassed */ true)})); 2293 } 2294 } 2295 break; 2296 } 2297 case OMPRTL__kmpc_taskloop: { 2298 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2299 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2300 // sched, kmp_uint64 grainsize, void *task_dup); 2301 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2302 CGM.IntTy, 2303 CGM.VoidPtrTy, 2304 CGM.IntTy, 2305 CGM.Int64Ty->getPointerTo(), 2306 CGM.Int64Ty->getPointerTo(), 2307 CGM.Int64Ty, 2308 CGM.IntTy, 2309 CGM.IntTy, 2310 CGM.Int64Ty, 2311 CGM.VoidPtrTy}; 2312 auto *FnTy = 2313 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2314 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2315 break; 2316 } 2317 case OMPRTL__kmpc_doacross_init: { 2318 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2319 // num_dims, struct kmp_dim *dims); 2320 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2321 CGM.Int32Ty, 2322 CGM.Int32Ty, 2323 CGM.VoidPtrTy}; 2324 auto *FnTy = 2325 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2326 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2327 break; 2328 } 2329 case OMPRTL__kmpc_doacross_fini: { 2330 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2331 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2332 auto *FnTy = 2333 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2334 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2335 break; 2336 } 2337 case OMPRTL__kmpc_doacross_post: { 2338 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2339 // *vec); 2340 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2341 CGM.Int64Ty->getPointerTo()}; 2342 auto *FnTy = 2343 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2344 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2345 break; 2346 } 2347 case OMPRTL__kmpc_doacross_wait: { 2348 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2349 // *vec); 2350 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2351 CGM.Int64Ty->getPointerTo()}; 2352 auto *FnTy = 2353 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2354 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2355 break; 2356 } 2357 case OMPRTL__kmpc_task_reduction_init: { 2358 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2359 // *data); 2360 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2361 auto *FnTy = 2362 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2363 RTLFn = 2364 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2365 break; 2366 } 2367 case OMPRTL__kmpc_task_reduction_get_th_data: { 2368 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2369 // *d); 2370 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2371 auto *FnTy = 2372 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2373 RTLFn = CGM.CreateRuntimeFunction( 2374 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2375 break; 2376 } 2377 case OMPRTL__kmpc_alloc: { 2378 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2379 // al); omp_allocator_handle_t type is void *. 2380 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2381 auto *FnTy = 2382 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2383 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2384 break; 2385 } 2386 case OMPRTL__kmpc_free: { 2387 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2388 // al); omp_allocator_handle_t type is void *. 2389 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2390 auto *FnTy = 2391 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2392 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2393 break; 2394 } 2395 case OMPRTL__kmpc_push_target_tripcount: { 2396 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2397 // size); 2398 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2399 llvm::FunctionType *FnTy = 2400 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2401 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2402 break; 2403 } 2404 case OMPRTL__tgt_target: { 2405 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2406 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2407 // *arg_types); 2408 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2409 CGM.VoidPtrTy, 2410 CGM.Int32Ty, 2411 CGM.VoidPtrPtrTy, 2412 CGM.VoidPtrPtrTy, 2413 CGM.Int64Ty->getPointerTo(), 2414 CGM.Int64Ty->getPointerTo()}; 2415 auto *FnTy = 2416 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2417 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2418 break; 2419 } 2420 case OMPRTL__tgt_target_nowait: { 2421 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2422 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2423 // int64_t *arg_types); 2424 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2425 CGM.VoidPtrTy, 2426 CGM.Int32Ty, 2427 CGM.VoidPtrPtrTy, 2428 CGM.VoidPtrPtrTy, 2429 CGM.Int64Ty->getPointerTo(), 2430 CGM.Int64Ty->getPointerTo()}; 2431 auto *FnTy = 2432 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2433 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2434 break; 2435 } 2436 case OMPRTL__tgt_target_teams: { 2437 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2438 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2439 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2440 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2441 CGM.VoidPtrTy, 2442 CGM.Int32Ty, 2443 CGM.VoidPtrPtrTy, 2444 CGM.VoidPtrPtrTy, 2445 CGM.Int64Ty->getPointerTo(), 2446 CGM.Int64Ty->getPointerTo(), 2447 CGM.Int32Ty, 2448 CGM.Int32Ty}; 2449 auto *FnTy = 2450 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2451 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2452 break; 2453 } 2454 case OMPRTL__tgt_target_teams_nowait: { 2455 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2456 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2457 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2458 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2459 CGM.VoidPtrTy, 2460 CGM.Int32Ty, 2461 CGM.VoidPtrPtrTy, 2462 CGM.VoidPtrPtrTy, 2463 CGM.Int64Ty->getPointerTo(), 2464 CGM.Int64Ty->getPointerTo(), 2465 CGM.Int32Ty, 2466 CGM.Int32Ty}; 2467 auto *FnTy = 2468 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2469 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2470 break; 2471 } 2472 case OMPRTL__tgt_register_requires: { 2473 // Build void __tgt_register_requires(int64_t flags); 2474 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2475 auto *FnTy = 2476 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2477 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2478 break; 2479 } 2480 case OMPRTL__tgt_register_lib: { 2481 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 2482 QualType ParamTy = 2483 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2484 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2485 auto *FnTy = 2486 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2487 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 2488 break; 2489 } 2490 case OMPRTL__tgt_unregister_lib: { 2491 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 2492 QualType ParamTy = 2493 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2494 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2495 auto *FnTy = 2496 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2497 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 2498 break; 2499 } 2500 case OMPRTL__tgt_target_data_begin: { 2501 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2502 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2503 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2504 CGM.Int32Ty, 2505 CGM.VoidPtrPtrTy, 2506 CGM.VoidPtrPtrTy, 2507 CGM.Int64Ty->getPointerTo(), 2508 CGM.Int64Ty->getPointerTo()}; 2509 auto *FnTy = 2510 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2511 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2512 break; 2513 } 2514 case OMPRTL__tgt_target_data_begin_nowait: { 2515 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2516 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2517 // *arg_types); 2518 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2519 CGM.Int32Ty, 2520 CGM.VoidPtrPtrTy, 2521 CGM.VoidPtrPtrTy, 2522 CGM.Int64Ty->getPointerTo(), 2523 CGM.Int64Ty->getPointerTo()}; 2524 auto *FnTy = 2525 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2526 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2527 break; 2528 } 2529 case OMPRTL__tgt_target_data_end: { 2530 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2531 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2532 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2533 CGM.Int32Ty, 2534 CGM.VoidPtrPtrTy, 2535 CGM.VoidPtrPtrTy, 2536 CGM.Int64Ty->getPointerTo(), 2537 CGM.Int64Ty->getPointerTo()}; 2538 auto *FnTy = 2539 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2540 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2541 break; 2542 } 2543 case OMPRTL__tgt_target_data_end_nowait: { 2544 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2545 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2546 // *arg_types); 2547 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2548 CGM.Int32Ty, 2549 CGM.VoidPtrPtrTy, 2550 CGM.VoidPtrPtrTy, 2551 CGM.Int64Ty->getPointerTo(), 2552 CGM.Int64Ty->getPointerTo()}; 2553 auto *FnTy = 2554 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2555 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2556 break; 2557 } 2558 case OMPRTL__tgt_target_data_update: { 2559 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2560 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2561 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2562 CGM.Int32Ty, 2563 CGM.VoidPtrPtrTy, 2564 CGM.VoidPtrPtrTy, 2565 CGM.Int64Ty->getPointerTo(), 2566 CGM.Int64Ty->getPointerTo()}; 2567 auto *FnTy = 2568 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2569 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2570 break; 2571 } 2572 case OMPRTL__tgt_target_data_update_nowait: { 2573 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2574 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2575 // *arg_types); 2576 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2577 CGM.Int32Ty, 2578 CGM.VoidPtrPtrTy, 2579 CGM.VoidPtrPtrTy, 2580 CGM.Int64Ty->getPointerTo(), 2581 CGM.Int64Ty->getPointerTo()}; 2582 auto *FnTy = 2583 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2584 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2585 break; 2586 } 2587 case OMPRTL__tgt_mapper_num_components: { 2588 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2589 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2590 auto *FnTy = 2591 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2592 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2593 break; 2594 } 2595 case OMPRTL__tgt_push_mapper_component: { 2596 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2597 // *base, void *begin, int64_t size, int64_t type); 2598 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2599 CGM.Int64Ty, CGM.Int64Ty}; 2600 auto *FnTy = 2601 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2602 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2603 break; 2604 } 2605 } 2606 assert(RTLFn && "Unable to find OpenMP runtime function"); 2607 return RTLFn; 2608 } 2609 2610 llvm::FunctionCallee 2611 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2612 assert((IVSize == 32 || IVSize == 64) && 2613 "IV size is not compatible with the omp runtime"); 2614 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2615 : "__kmpc_for_static_init_4u") 2616 : (IVSigned ? "__kmpc_for_static_init_8" 2617 : "__kmpc_for_static_init_8u"); 2618 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2619 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2620 llvm::Type *TypeParams[] = { 2621 getIdentTyPointerTy(), // loc 2622 CGM.Int32Ty, // tid 2623 CGM.Int32Ty, // schedtype 2624 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2625 PtrTy, // p_lower 2626 PtrTy, // p_upper 2627 PtrTy, // p_stride 2628 ITy, // incr 2629 ITy // chunk 2630 }; 2631 auto *FnTy = 2632 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2633 return CGM.CreateRuntimeFunction(FnTy, Name); 2634 } 2635 2636 llvm::FunctionCallee 2637 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2638 assert((IVSize == 32 || IVSize == 64) && 2639 "IV size is not compatible with the omp runtime"); 2640 StringRef Name = 2641 IVSize == 32 2642 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2643 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2644 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2645 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2646 CGM.Int32Ty, // tid 2647 CGM.Int32Ty, // schedtype 2648 ITy, // lower 2649 ITy, // upper 2650 ITy, // stride 2651 ITy // chunk 2652 }; 2653 auto *FnTy = 2654 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2655 return CGM.CreateRuntimeFunction(FnTy, Name); 2656 } 2657 2658 llvm::FunctionCallee 2659 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2660 assert((IVSize == 32 || IVSize == 64) && 2661 "IV size is not compatible with the omp runtime"); 2662 StringRef Name = 2663 IVSize == 32 2664 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2665 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2666 llvm::Type *TypeParams[] = { 2667 getIdentTyPointerTy(), // loc 2668 CGM.Int32Ty, // tid 2669 }; 2670 auto *FnTy = 2671 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2672 return CGM.CreateRuntimeFunction(FnTy, Name); 2673 } 2674 2675 llvm::FunctionCallee 2676 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2677 assert((IVSize == 32 || IVSize == 64) && 2678 "IV size is not compatible with the omp runtime"); 2679 StringRef Name = 2680 IVSize == 32 2681 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2682 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2683 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2684 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2685 llvm::Type *TypeParams[] = { 2686 getIdentTyPointerTy(), // loc 2687 CGM.Int32Ty, // tid 2688 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2689 PtrTy, // p_lower 2690 PtrTy, // p_upper 2691 PtrTy // p_stride 2692 }; 2693 auto *FnTy = 2694 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2695 return CGM.CreateRuntimeFunction(FnTy, Name); 2696 } 2697 2698 /// Obtain information that uniquely identifies a target entry. This 2699 /// consists of the file and device IDs as well as line number associated with 2700 /// the relevant entry source location. 2701 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2702 unsigned &DeviceID, unsigned &FileID, 2703 unsigned &LineNum) { 2704 SourceManager &SM = C.getSourceManager(); 2705 2706 // The loc should be always valid and have a file ID (the user cannot use 2707 // #pragma directives in macros) 2708 2709 assert(Loc.isValid() && "Source location is expected to be always valid."); 2710 2711 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2712 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2713 2714 llvm::sys::fs::UniqueID ID; 2715 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2716 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2717 << PLoc.getFilename() << EC.message(); 2718 2719 DeviceID = ID.getDevice(); 2720 FileID = ID.getFile(); 2721 LineNum = PLoc.getLine(); 2722 } 2723 2724 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2725 if (CGM.getLangOpts().OpenMPSimd) 2726 return Address::invalid(); 2727 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2728 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2729 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2730 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2731 HasRequiresUnifiedSharedMemory))) { 2732 SmallString<64> PtrName; 2733 { 2734 llvm::raw_svector_ostream OS(PtrName); 2735 OS << CGM.getMangledName(GlobalDecl(VD)); 2736 if (!VD->isExternallyVisible()) { 2737 unsigned DeviceID, FileID, Line; 2738 getTargetEntryUniqueInfo(CGM.getContext(), 2739 VD->getCanonicalDecl()->getBeginLoc(), 2740 DeviceID, FileID, Line); 2741 OS << llvm::format("_%x", FileID); 2742 } 2743 OS << "_decl_tgt_ref_ptr"; 2744 } 2745 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2746 if (!Ptr) { 2747 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2748 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2749 PtrName); 2750 2751 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2752 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2753 2754 if (!CGM.getLangOpts().OpenMPIsDevice) 2755 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2756 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2757 } 2758 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2759 } 2760 return Address::invalid(); 2761 } 2762 2763 llvm::Constant * 2764 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2765 assert(!CGM.getLangOpts().OpenMPUseTLS || 2766 !CGM.getContext().getTargetInfo().isTLSSupported()); 2767 // Lookup the entry, lazily creating it if necessary. 2768 std::string Suffix = getName({"cache", ""}); 2769 return getOrCreateInternalVariable( 2770 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2771 } 2772 2773 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2774 const VarDecl *VD, 2775 Address VDAddr, 2776 SourceLocation Loc) { 2777 if (CGM.getLangOpts().OpenMPUseTLS && 2778 CGM.getContext().getTargetInfo().isTLSSupported()) 2779 return VDAddr; 2780 2781 llvm::Type *VarTy = VDAddr.getElementType(); 2782 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2783 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2784 CGM.Int8PtrTy), 2785 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2786 getOrCreateThreadPrivateCache(VD)}; 2787 return Address(CGF.EmitRuntimeCall( 2788 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2789 VDAddr.getAlignment()); 2790 } 2791 2792 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2793 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2794 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2795 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2796 // library. 2797 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2798 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2799 OMPLoc); 2800 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2801 // to register constructor/destructor for variable. 2802 llvm::Value *Args[] = { 2803 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2804 Ctor, CopyCtor, Dtor}; 2805 CGF.EmitRuntimeCall( 2806 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2807 } 2808 2809 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2810 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2811 bool PerformInit, CodeGenFunction *CGF) { 2812 if (CGM.getLangOpts().OpenMPUseTLS && 2813 CGM.getContext().getTargetInfo().isTLSSupported()) 2814 return nullptr; 2815 2816 VD = VD->getDefinition(CGM.getContext()); 2817 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2818 QualType ASTTy = VD->getType(); 2819 2820 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2821 const Expr *Init = VD->getAnyInitializer(); 2822 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2823 // Generate function that re-emits the declaration's initializer into the 2824 // threadprivate copy of the variable VD 2825 CodeGenFunction CtorCGF(CGM); 2826 FunctionArgList Args; 2827 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2828 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2829 ImplicitParamDecl::Other); 2830 Args.push_back(&Dst); 2831 2832 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2833 CGM.getContext().VoidPtrTy, Args); 2834 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2835 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2836 llvm::Function *Fn = 2837 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2838 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2839 Args, Loc, Loc); 2840 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2841 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2842 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2843 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2844 Arg = CtorCGF.Builder.CreateElementBitCast( 2845 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2846 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2847 /*IsInitializer=*/true); 2848 ArgVal = CtorCGF.EmitLoadOfScalar( 2849 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2850 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2851 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2852 CtorCGF.FinishFunction(); 2853 Ctor = Fn; 2854 } 2855 if (VD->getType().isDestructedType() != QualType::DK_none) { 2856 // Generate function that emits destructor call for the threadprivate copy 2857 // of the variable VD 2858 CodeGenFunction DtorCGF(CGM); 2859 FunctionArgList Args; 2860 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2861 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2862 ImplicitParamDecl::Other); 2863 Args.push_back(&Dst); 2864 2865 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2866 CGM.getContext().VoidTy, Args); 2867 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2868 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2869 llvm::Function *Fn = 2870 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2871 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2872 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2873 Loc, Loc); 2874 // Create a scope with an artificial location for the body of this function. 2875 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2876 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2877 DtorCGF.GetAddrOfLocalVar(&Dst), 2878 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2879 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2880 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2881 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2882 DtorCGF.FinishFunction(); 2883 Dtor = Fn; 2884 } 2885 // Do not emit init function if it is not required. 2886 if (!Ctor && !Dtor) 2887 return nullptr; 2888 2889 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2890 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2891 /*isVarArg=*/false) 2892 ->getPointerTo(); 2893 // Copying constructor for the threadprivate variable. 2894 // Must be NULL - reserved by runtime, but currently it requires that this 2895 // parameter is always NULL. Otherwise it fires assertion. 2896 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2897 if (Ctor == nullptr) { 2898 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2899 /*isVarArg=*/false) 2900 ->getPointerTo(); 2901 Ctor = llvm::Constant::getNullValue(CtorTy); 2902 } 2903 if (Dtor == nullptr) { 2904 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2905 /*isVarArg=*/false) 2906 ->getPointerTo(); 2907 Dtor = llvm::Constant::getNullValue(DtorTy); 2908 } 2909 if (!CGF) { 2910 auto *InitFunctionTy = 2911 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2912 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2913 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2914 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2915 CodeGenFunction InitCGF(CGM); 2916 FunctionArgList ArgList; 2917 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2918 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2919 Loc, Loc); 2920 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2921 InitCGF.FinishFunction(); 2922 return InitFunction; 2923 } 2924 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2925 } 2926 return nullptr; 2927 } 2928 2929 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2930 llvm::GlobalVariable *Addr, 2931 bool PerformInit) { 2932 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2933 !CGM.getLangOpts().OpenMPIsDevice) 2934 return false; 2935 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2936 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2937 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2938 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2939 HasRequiresUnifiedSharedMemory)) 2940 return CGM.getLangOpts().OpenMPIsDevice; 2941 VD = VD->getDefinition(CGM.getContext()); 2942 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2943 return CGM.getLangOpts().OpenMPIsDevice; 2944 2945 QualType ASTTy = VD->getType(); 2946 2947 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2948 // Produce the unique prefix to identify the new target regions. We use 2949 // the source location of the variable declaration which we know to not 2950 // conflict with any target region. 2951 unsigned DeviceID; 2952 unsigned FileID; 2953 unsigned Line; 2954 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2955 SmallString<128> Buffer, Out; 2956 { 2957 llvm::raw_svector_ostream OS(Buffer); 2958 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2959 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2960 } 2961 2962 const Expr *Init = VD->getAnyInitializer(); 2963 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2964 llvm::Constant *Ctor; 2965 llvm::Constant *ID; 2966 if (CGM.getLangOpts().OpenMPIsDevice) { 2967 // Generate function that re-emits the declaration's initializer into 2968 // the threadprivate copy of the variable VD 2969 CodeGenFunction CtorCGF(CGM); 2970 2971 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2972 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2973 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2974 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2975 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2976 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2977 FunctionArgList(), Loc, Loc); 2978 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2979 CtorCGF.EmitAnyExprToMem(Init, 2980 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2981 Init->getType().getQualifiers(), 2982 /*IsInitializer=*/true); 2983 CtorCGF.FinishFunction(); 2984 Ctor = Fn; 2985 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2986 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2987 } else { 2988 Ctor = new llvm::GlobalVariable( 2989 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2990 llvm::GlobalValue::PrivateLinkage, 2991 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2992 ID = Ctor; 2993 } 2994 2995 // Register the information for the entry associated with the constructor. 2996 Out.clear(); 2997 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2998 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2999 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 3000 } 3001 if (VD->getType().isDestructedType() != QualType::DK_none) { 3002 llvm::Constant *Dtor; 3003 llvm::Constant *ID; 3004 if (CGM.getLangOpts().OpenMPIsDevice) { 3005 // Generate function that emits destructor call for the threadprivate 3006 // copy of the variable VD 3007 CodeGenFunction DtorCGF(CGM); 3008 3009 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 3010 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 3011 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 3012 FTy, Twine(Buffer, "_dtor"), FI, Loc); 3013 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 3014 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 3015 FunctionArgList(), Loc, Loc); 3016 // Create a scope with an artificial location for the body of this 3017 // function. 3018 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 3019 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 3020 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 3021 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 3022 DtorCGF.FinishFunction(); 3023 Dtor = Fn; 3024 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 3025 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 3026 } else { 3027 Dtor = new llvm::GlobalVariable( 3028 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 3029 llvm::GlobalValue::PrivateLinkage, 3030 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 3031 ID = Dtor; 3032 } 3033 // Register the information for the entry associated with the destructor. 3034 Out.clear(); 3035 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 3036 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 3037 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 3038 } 3039 return CGM.getLangOpts().OpenMPIsDevice; 3040 } 3041 3042 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 3043 QualType VarType, 3044 StringRef Name) { 3045 std::string Suffix = getName({"artificial", ""}); 3046 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 3047 llvm::Value *GAddr = 3048 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 3049 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 3050 CGM.getTarget().isTLSSupported()) { 3051 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 3052 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 3053 } 3054 std::string CacheSuffix = getName({"cache", ""}); 3055 llvm::Value *Args[] = { 3056 emitUpdateLocation(CGF, SourceLocation()), 3057 getThreadID(CGF, SourceLocation()), 3058 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3059 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3060 /*isSigned=*/false), 3061 getOrCreateInternalVariable( 3062 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3063 return Address( 3064 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3065 CGF.EmitRuntimeCall( 3066 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3067 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3068 CGM.getContext().getTypeAlignInChars(VarType)); 3069 } 3070 3071 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3072 const RegionCodeGenTy &ThenGen, 3073 const RegionCodeGenTy &ElseGen) { 3074 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3075 3076 // If the condition constant folds and can be elided, try to avoid emitting 3077 // the condition and the dead arm of the if/else. 3078 bool CondConstant; 3079 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3080 if (CondConstant) 3081 ThenGen(CGF); 3082 else 3083 ElseGen(CGF); 3084 return; 3085 } 3086 3087 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3088 // emit the conditional branch. 3089 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3090 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3091 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3092 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3093 3094 // Emit the 'then' code. 3095 CGF.EmitBlock(ThenBlock); 3096 ThenGen(CGF); 3097 CGF.EmitBranch(ContBlock); 3098 // Emit the 'else' code if present. 3099 // There is no need to emit line number for unconditional branch. 3100 (void)ApplyDebugLocation::CreateEmpty(CGF); 3101 CGF.EmitBlock(ElseBlock); 3102 ElseGen(CGF); 3103 // There is no need to emit line number for unconditional branch. 3104 (void)ApplyDebugLocation::CreateEmpty(CGF); 3105 CGF.EmitBranch(ContBlock); 3106 // Emit the continuation block for code after the if. 3107 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3108 } 3109 3110 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3111 llvm::Function *OutlinedFn, 3112 ArrayRef<llvm::Value *> CapturedVars, 3113 const Expr *IfCond) { 3114 if (!CGF.HaveInsertPoint()) 3115 return; 3116 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3117 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3118 PrePostActionTy &) { 3119 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3120 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3121 llvm::Value *Args[] = { 3122 RTLoc, 3123 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3124 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3125 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3126 RealArgs.append(std::begin(Args), std::end(Args)); 3127 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3128 3129 llvm::FunctionCallee RTLFn = 3130 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3131 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3132 }; 3133 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3134 PrePostActionTy &) { 3135 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3136 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3137 // Build calls: 3138 // __kmpc_serialized_parallel(&Loc, GTid); 3139 llvm::Value *Args[] = {RTLoc, ThreadID}; 3140 CGF.EmitRuntimeCall( 3141 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3142 3143 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3144 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3145 Address ZeroAddrBound = 3146 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3147 /*Name=*/".bound.zero.addr"); 3148 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3149 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3150 // ThreadId for serialized parallels is 0. 3151 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3152 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3153 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3154 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3155 3156 // __kmpc_end_serialized_parallel(&Loc, GTid); 3157 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3158 CGF.EmitRuntimeCall( 3159 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3160 EndArgs); 3161 }; 3162 if (IfCond) { 3163 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3164 } else { 3165 RegionCodeGenTy ThenRCG(ThenGen); 3166 ThenRCG(CGF); 3167 } 3168 } 3169 3170 // If we're inside an (outlined) parallel region, use the region info's 3171 // thread-ID variable (it is passed in a first argument of the outlined function 3172 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3173 // regular serial code region, get thread ID by calling kmp_int32 3174 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3175 // return the address of that temp. 3176 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3177 SourceLocation Loc) { 3178 if (auto *OMPRegionInfo = 3179 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3180 if (OMPRegionInfo->getThreadIDVariable()) 3181 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3182 3183 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3184 QualType Int32Ty = 3185 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3186 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3187 CGF.EmitStoreOfScalar(ThreadID, 3188 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3189 3190 return ThreadIDTemp; 3191 } 3192 3193 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3194 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3195 SmallString<256> Buffer; 3196 llvm::raw_svector_ostream Out(Buffer); 3197 Out << Name; 3198 StringRef RuntimeName = Out.str(); 3199 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3200 if (Elem.second) { 3201 assert(Elem.second->getType()->getPointerElementType() == Ty && 3202 "OMP internal variable has different type than requested"); 3203 return &*Elem.second; 3204 } 3205 3206 return Elem.second = new llvm::GlobalVariable( 3207 CGM.getModule(), Ty, /*IsConstant*/ false, 3208 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3209 Elem.first(), /*InsertBefore=*/nullptr, 3210 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3211 } 3212 3213 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3214 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3215 std::string Name = getName({Prefix, "var"}); 3216 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3217 } 3218 3219 namespace { 3220 /// Common pre(post)-action for different OpenMP constructs. 3221 class CommonActionTy final : public PrePostActionTy { 3222 llvm::FunctionCallee EnterCallee; 3223 ArrayRef<llvm::Value *> EnterArgs; 3224 llvm::FunctionCallee ExitCallee; 3225 ArrayRef<llvm::Value *> ExitArgs; 3226 bool Conditional; 3227 llvm::BasicBlock *ContBlock = nullptr; 3228 3229 public: 3230 CommonActionTy(llvm::FunctionCallee EnterCallee, 3231 ArrayRef<llvm::Value *> EnterArgs, 3232 llvm::FunctionCallee ExitCallee, 3233 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3234 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3235 ExitArgs(ExitArgs), Conditional(Conditional) {} 3236 void Enter(CodeGenFunction &CGF) override { 3237 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3238 if (Conditional) { 3239 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3240 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3241 ContBlock = CGF.createBasicBlock("omp_if.end"); 3242 // Generate the branch (If-stmt) 3243 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3244 CGF.EmitBlock(ThenBlock); 3245 } 3246 } 3247 void Done(CodeGenFunction &CGF) { 3248 // Emit the rest of blocks/branches 3249 CGF.EmitBranch(ContBlock); 3250 CGF.EmitBlock(ContBlock, true); 3251 } 3252 void Exit(CodeGenFunction &CGF) override { 3253 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3254 } 3255 }; 3256 } // anonymous namespace 3257 3258 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3259 StringRef CriticalName, 3260 const RegionCodeGenTy &CriticalOpGen, 3261 SourceLocation Loc, const Expr *Hint) { 3262 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3263 // CriticalOpGen(); 3264 // __kmpc_end_critical(ident_t *, gtid, Lock); 3265 // Prepare arguments and build a call to __kmpc_critical 3266 if (!CGF.HaveInsertPoint()) 3267 return; 3268 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3269 getCriticalRegionLock(CriticalName)}; 3270 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3271 std::end(Args)); 3272 if (Hint) { 3273 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3274 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3275 } 3276 CommonActionTy Action( 3277 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3278 : OMPRTL__kmpc_critical), 3279 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3280 CriticalOpGen.setAction(Action); 3281 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3282 } 3283 3284 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3285 const RegionCodeGenTy &MasterOpGen, 3286 SourceLocation Loc) { 3287 if (!CGF.HaveInsertPoint()) 3288 return; 3289 // if(__kmpc_master(ident_t *, gtid)) { 3290 // MasterOpGen(); 3291 // __kmpc_end_master(ident_t *, gtid); 3292 // } 3293 // Prepare arguments and build a call to __kmpc_master 3294 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3295 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3296 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3297 /*Conditional=*/true); 3298 MasterOpGen.setAction(Action); 3299 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3300 Action.Done(CGF); 3301 } 3302 3303 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3304 SourceLocation Loc) { 3305 if (!CGF.HaveInsertPoint()) 3306 return; 3307 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3308 llvm::Value *Args[] = { 3309 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3310 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3311 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3312 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3313 Region->emitUntiedSwitch(CGF); 3314 } 3315 3316 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3317 const RegionCodeGenTy &TaskgroupOpGen, 3318 SourceLocation Loc) { 3319 if (!CGF.HaveInsertPoint()) 3320 return; 3321 // __kmpc_taskgroup(ident_t *, gtid); 3322 // TaskgroupOpGen(); 3323 // __kmpc_end_taskgroup(ident_t *, gtid); 3324 // Prepare arguments and build a call to __kmpc_taskgroup 3325 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3326 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3327 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3328 Args); 3329 TaskgroupOpGen.setAction(Action); 3330 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3331 } 3332 3333 /// Given an array of pointers to variables, project the address of a 3334 /// given variable. 3335 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3336 unsigned Index, const VarDecl *Var) { 3337 // Pull out the pointer to the variable. 3338 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3339 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3340 3341 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3342 Addr = CGF.Builder.CreateElementBitCast( 3343 Addr, CGF.ConvertTypeForMem(Var->getType())); 3344 return Addr; 3345 } 3346 3347 static llvm::Value *emitCopyprivateCopyFunction( 3348 CodeGenModule &CGM, llvm::Type *ArgsType, 3349 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3350 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3351 SourceLocation Loc) { 3352 ASTContext &C = CGM.getContext(); 3353 // void copy_func(void *LHSArg, void *RHSArg); 3354 FunctionArgList Args; 3355 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3356 ImplicitParamDecl::Other); 3357 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3358 ImplicitParamDecl::Other); 3359 Args.push_back(&LHSArg); 3360 Args.push_back(&RHSArg); 3361 const auto &CGFI = 3362 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3363 std::string Name = 3364 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3365 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3366 llvm::GlobalValue::InternalLinkage, Name, 3367 &CGM.getModule()); 3368 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3369 Fn->setDoesNotRecurse(); 3370 CodeGenFunction CGF(CGM); 3371 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3372 // Dest = (void*[n])(LHSArg); 3373 // Src = (void*[n])(RHSArg); 3374 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3375 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3376 ArgsType), CGF.getPointerAlign()); 3377 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3378 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3379 ArgsType), CGF.getPointerAlign()); 3380 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3381 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3382 // ... 3383 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3384 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3385 const auto *DestVar = 3386 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3387 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3388 3389 const auto *SrcVar = 3390 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3391 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3392 3393 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3394 QualType Type = VD->getType(); 3395 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3396 } 3397 CGF.FinishFunction(); 3398 return Fn; 3399 } 3400 3401 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3402 const RegionCodeGenTy &SingleOpGen, 3403 SourceLocation Loc, 3404 ArrayRef<const Expr *> CopyprivateVars, 3405 ArrayRef<const Expr *> SrcExprs, 3406 ArrayRef<const Expr *> DstExprs, 3407 ArrayRef<const Expr *> AssignmentOps) { 3408 if (!CGF.HaveInsertPoint()) 3409 return; 3410 assert(CopyprivateVars.size() == SrcExprs.size() && 3411 CopyprivateVars.size() == DstExprs.size() && 3412 CopyprivateVars.size() == AssignmentOps.size()); 3413 ASTContext &C = CGM.getContext(); 3414 // int32 did_it = 0; 3415 // if(__kmpc_single(ident_t *, gtid)) { 3416 // SingleOpGen(); 3417 // __kmpc_end_single(ident_t *, gtid); 3418 // did_it = 1; 3419 // } 3420 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3421 // <copy_func>, did_it); 3422 3423 Address DidIt = Address::invalid(); 3424 if (!CopyprivateVars.empty()) { 3425 // int32 did_it = 0; 3426 QualType KmpInt32Ty = 3427 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3428 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3429 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3430 } 3431 // Prepare arguments and build a call to __kmpc_single 3432 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3433 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3434 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3435 /*Conditional=*/true); 3436 SingleOpGen.setAction(Action); 3437 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3438 if (DidIt.isValid()) { 3439 // did_it = 1; 3440 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3441 } 3442 Action.Done(CGF); 3443 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3444 // <copy_func>, did_it); 3445 if (DidIt.isValid()) { 3446 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3447 QualType CopyprivateArrayTy = C.getConstantArrayType( 3448 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3449 /*IndexTypeQuals=*/0); 3450 // Create a list of all private variables for copyprivate. 3451 Address CopyprivateList = 3452 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3453 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3454 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3455 CGF.Builder.CreateStore( 3456 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3457 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3458 CGF.VoidPtrTy), 3459 Elem); 3460 } 3461 // Build function that copies private values from single region to all other 3462 // threads in the corresponding parallel region. 3463 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3464 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3465 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3466 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3467 Address CL = 3468 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3469 CGF.VoidPtrTy); 3470 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3471 llvm::Value *Args[] = { 3472 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3473 getThreadID(CGF, Loc), // i32 <gtid> 3474 BufSize, // size_t <buf_size> 3475 CL.getPointer(), // void *<copyprivate list> 3476 CpyFn, // void (*) (void *, void *) <copy_func> 3477 DidItVal // i32 did_it 3478 }; 3479 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3480 } 3481 } 3482 3483 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3484 const RegionCodeGenTy &OrderedOpGen, 3485 SourceLocation Loc, bool IsThreads) { 3486 if (!CGF.HaveInsertPoint()) 3487 return; 3488 // __kmpc_ordered(ident_t *, gtid); 3489 // OrderedOpGen(); 3490 // __kmpc_end_ordered(ident_t *, gtid); 3491 // Prepare arguments and build a call to __kmpc_ordered 3492 if (IsThreads) { 3493 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3494 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3495 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3496 Args); 3497 OrderedOpGen.setAction(Action); 3498 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3499 return; 3500 } 3501 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3502 } 3503 3504 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3505 unsigned Flags; 3506 if (Kind == OMPD_for) 3507 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3508 else if (Kind == OMPD_sections) 3509 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3510 else if (Kind == OMPD_single) 3511 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3512 else if (Kind == OMPD_barrier) 3513 Flags = OMP_IDENT_BARRIER_EXPL; 3514 else 3515 Flags = OMP_IDENT_BARRIER_IMPL; 3516 return Flags; 3517 } 3518 3519 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3520 CodeGenFunction &CGF, const OMPLoopDirective &S, 3521 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3522 // Check if the loop directive is actually a doacross loop directive. In this 3523 // case choose static, 1 schedule. 3524 if (llvm::any_of( 3525 S.getClausesOfKind<OMPOrderedClause>(), 3526 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3527 ScheduleKind = OMPC_SCHEDULE_static; 3528 // Chunk size is 1 in this case. 3529 llvm::APInt ChunkSize(32, 1); 3530 ChunkExpr = IntegerLiteral::Create( 3531 CGF.getContext(), ChunkSize, 3532 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3533 SourceLocation()); 3534 } 3535 } 3536 3537 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3538 OpenMPDirectiveKind Kind, bool EmitChecks, 3539 bool ForceSimpleCall) { 3540 // Check if we should use the OMPBuilder 3541 auto *OMPRegionInfo = 3542 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 3543 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3544 if (OMPBuilder) { 3545 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier( 3546 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 3547 return; 3548 } 3549 3550 if (!CGF.HaveInsertPoint()) 3551 return; 3552 // Build call __kmpc_cancel_barrier(loc, thread_id); 3553 // Build call __kmpc_barrier(loc, thread_id); 3554 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3555 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3556 // thread_id); 3557 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3558 getThreadID(CGF, Loc)}; 3559 if (OMPRegionInfo) { 3560 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3561 llvm::Value *Result = CGF.EmitRuntimeCall( 3562 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3563 if (EmitChecks) { 3564 // if (__kmpc_cancel_barrier()) { 3565 // exit from construct; 3566 // } 3567 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3568 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3569 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3570 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3571 CGF.EmitBlock(ExitBB); 3572 // exit from construct; 3573 CodeGenFunction::JumpDest CancelDestination = 3574 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3575 CGF.EmitBranchThroughCleanup(CancelDestination); 3576 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3577 } 3578 return; 3579 } 3580 } 3581 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3582 } 3583 3584 /// Map the OpenMP loop schedule to the runtime enumeration. 3585 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3586 bool Chunked, bool Ordered) { 3587 switch (ScheduleKind) { 3588 case OMPC_SCHEDULE_static: 3589 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3590 : (Ordered ? OMP_ord_static : OMP_sch_static); 3591 case OMPC_SCHEDULE_dynamic: 3592 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3593 case OMPC_SCHEDULE_guided: 3594 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3595 case OMPC_SCHEDULE_runtime: 3596 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3597 case OMPC_SCHEDULE_auto: 3598 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3599 case OMPC_SCHEDULE_unknown: 3600 assert(!Chunked && "chunk was specified but schedule kind not known"); 3601 return Ordered ? OMP_ord_static : OMP_sch_static; 3602 } 3603 llvm_unreachable("Unexpected runtime schedule"); 3604 } 3605 3606 /// Map the OpenMP distribute schedule to the runtime enumeration. 3607 static OpenMPSchedType 3608 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3609 // only static is allowed for dist_schedule 3610 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3611 } 3612 3613 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3614 bool Chunked) const { 3615 OpenMPSchedType Schedule = 3616 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3617 return Schedule == OMP_sch_static; 3618 } 3619 3620 bool CGOpenMPRuntime::isStaticNonchunked( 3621 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3622 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3623 return Schedule == OMP_dist_sch_static; 3624 } 3625 3626 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3627 bool Chunked) const { 3628 OpenMPSchedType Schedule = 3629 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3630 return Schedule == OMP_sch_static_chunked; 3631 } 3632 3633 bool CGOpenMPRuntime::isStaticChunked( 3634 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3635 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3636 return Schedule == OMP_dist_sch_static_chunked; 3637 } 3638 3639 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3640 OpenMPSchedType Schedule = 3641 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3642 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3643 return Schedule != OMP_sch_static; 3644 } 3645 3646 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3647 OpenMPScheduleClauseModifier M1, 3648 OpenMPScheduleClauseModifier M2) { 3649 int Modifier = 0; 3650 switch (M1) { 3651 case OMPC_SCHEDULE_MODIFIER_monotonic: 3652 Modifier = OMP_sch_modifier_monotonic; 3653 break; 3654 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3655 Modifier = OMP_sch_modifier_nonmonotonic; 3656 break; 3657 case OMPC_SCHEDULE_MODIFIER_simd: 3658 if (Schedule == OMP_sch_static_chunked) 3659 Schedule = OMP_sch_static_balanced_chunked; 3660 break; 3661 case OMPC_SCHEDULE_MODIFIER_last: 3662 case OMPC_SCHEDULE_MODIFIER_unknown: 3663 break; 3664 } 3665 switch (M2) { 3666 case OMPC_SCHEDULE_MODIFIER_monotonic: 3667 Modifier = OMP_sch_modifier_monotonic; 3668 break; 3669 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3670 Modifier = OMP_sch_modifier_nonmonotonic; 3671 break; 3672 case OMPC_SCHEDULE_MODIFIER_simd: 3673 if (Schedule == OMP_sch_static_chunked) 3674 Schedule = OMP_sch_static_balanced_chunked; 3675 break; 3676 case OMPC_SCHEDULE_MODIFIER_last: 3677 case OMPC_SCHEDULE_MODIFIER_unknown: 3678 break; 3679 } 3680 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3681 // If the static schedule kind is specified or if the ordered clause is 3682 // specified, and if the nonmonotonic modifier is not specified, the effect is 3683 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3684 // modifier is specified, the effect is as if the nonmonotonic modifier is 3685 // specified. 3686 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3687 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3688 Schedule == OMP_sch_static_balanced_chunked || 3689 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3690 Schedule == OMP_dist_sch_static_chunked || 3691 Schedule == OMP_dist_sch_static)) 3692 Modifier = OMP_sch_modifier_nonmonotonic; 3693 } 3694 return Schedule | Modifier; 3695 } 3696 3697 void CGOpenMPRuntime::emitForDispatchInit( 3698 CodeGenFunction &CGF, SourceLocation Loc, 3699 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3700 bool Ordered, const DispatchRTInput &DispatchValues) { 3701 if (!CGF.HaveInsertPoint()) 3702 return; 3703 OpenMPSchedType Schedule = getRuntimeSchedule( 3704 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3705 assert(Ordered || 3706 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3707 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3708 Schedule != OMP_sch_static_balanced_chunked)); 3709 // Call __kmpc_dispatch_init( 3710 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3711 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3712 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3713 3714 // If the Chunk was not specified in the clause - use default value 1. 3715 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3716 : CGF.Builder.getIntN(IVSize, 1); 3717 llvm::Value *Args[] = { 3718 emitUpdateLocation(CGF, Loc), 3719 getThreadID(CGF, Loc), 3720 CGF.Builder.getInt32(addMonoNonMonoModifier( 3721 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3722 DispatchValues.LB, // Lower 3723 DispatchValues.UB, // Upper 3724 CGF.Builder.getIntN(IVSize, 1), // Stride 3725 Chunk // Chunk 3726 }; 3727 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3728 } 3729 3730 static void emitForStaticInitCall( 3731 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3732 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3733 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3734 const CGOpenMPRuntime::StaticRTInput &Values) { 3735 if (!CGF.HaveInsertPoint()) 3736 return; 3737 3738 assert(!Values.Ordered); 3739 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3740 Schedule == OMP_sch_static_balanced_chunked || 3741 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3742 Schedule == OMP_dist_sch_static || 3743 Schedule == OMP_dist_sch_static_chunked); 3744 3745 // Call __kmpc_for_static_init( 3746 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3747 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3748 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3749 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3750 llvm::Value *Chunk = Values.Chunk; 3751 if (Chunk == nullptr) { 3752 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3753 Schedule == OMP_dist_sch_static) && 3754 "expected static non-chunked schedule"); 3755 // If the Chunk was not specified in the clause - use default value 1. 3756 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3757 } else { 3758 assert((Schedule == OMP_sch_static_chunked || 3759 Schedule == OMP_sch_static_balanced_chunked || 3760 Schedule == OMP_ord_static_chunked || 3761 Schedule == OMP_dist_sch_static_chunked) && 3762 "expected static chunked schedule"); 3763 } 3764 llvm::Value *Args[] = { 3765 UpdateLocation, 3766 ThreadId, 3767 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3768 M2)), // Schedule type 3769 Values.IL.getPointer(), // &isLastIter 3770 Values.LB.getPointer(), // &LB 3771 Values.UB.getPointer(), // &UB 3772 Values.ST.getPointer(), // &Stride 3773 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3774 Chunk // Chunk 3775 }; 3776 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3777 } 3778 3779 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3780 SourceLocation Loc, 3781 OpenMPDirectiveKind DKind, 3782 const OpenMPScheduleTy &ScheduleKind, 3783 const StaticRTInput &Values) { 3784 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3785 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3786 assert(isOpenMPWorksharingDirective(DKind) && 3787 "Expected loop-based or sections-based directive."); 3788 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3789 isOpenMPLoopDirective(DKind) 3790 ? OMP_IDENT_WORK_LOOP 3791 : OMP_IDENT_WORK_SECTIONS); 3792 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3793 llvm::FunctionCallee StaticInitFunction = 3794 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3795 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3796 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3797 } 3798 3799 void CGOpenMPRuntime::emitDistributeStaticInit( 3800 CodeGenFunction &CGF, SourceLocation Loc, 3801 OpenMPDistScheduleClauseKind SchedKind, 3802 const CGOpenMPRuntime::StaticRTInput &Values) { 3803 OpenMPSchedType ScheduleNum = 3804 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3805 llvm::Value *UpdatedLocation = 3806 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3807 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3808 llvm::FunctionCallee StaticInitFunction = 3809 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3810 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3811 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3812 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3813 } 3814 3815 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3816 SourceLocation Loc, 3817 OpenMPDirectiveKind DKind) { 3818 if (!CGF.HaveInsertPoint()) 3819 return; 3820 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3821 llvm::Value *Args[] = { 3822 emitUpdateLocation(CGF, Loc, 3823 isOpenMPDistributeDirective(DKind) 3824 ? OMP_IDENT_WORK_DISTRIBUTE 3825 : isOpenMPLoopDirective(DKind) 3826 ? OMP_IDENT_WORK_LOOP 3827 : OMP_IDENT_WORK_SECTIONS), 3828 getThreadID(CGF, Loc)}; 3829 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3830 Args); 3831 } 3832 3833 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3834 SourceLocation Loc, 3835 unsigned IVSize, 3836 bool IVSigned) { 3837 if (!CGF.HaveInsertPoint()) 3838 return; 3839 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3840 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3841 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3842 } 3843 3844 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3845 SourceLocation Loc, unsigned IVSize, 3846 bool IVSigned, Address IL, 3847 Address LB, Address UB, 3848 Address ST) { 3849 // Call __kmpc_dispatch_next( 3850 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3851 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3852 // kmp_int[32|64] *p_stride); 3853 llvm::Value *Args[] = { 3854 emitUpdateLocation(CGF, Loc), 3855 getThreadID(CGF, Loc), 3856 IL.getPointer(), // &isLastIter 3857 LB.getPointer(), // &Lower 3858 UB.getPointer(), // &Upper 3859 ST.getPointer() // &Stride 3860 }; 3861 llvm::Value *Call = 3862 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3863 return CGF.EmitScalarConversion( 3864 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3865 CGF.getContext().BoolTy, Loc); 3866 } 3867 3868 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3869 llvm::Value *NumThreads, 3870 SourceLocation Loc) { 3871 if (!CGF.HaveInsertPoint()) 3872 return; 3873 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3874 llvm::Value *Args[] = { 3875 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3876 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3877 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3878 Args); 3879 } 3880 3881 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3882 ProcBindKind ProcBind, 3883 SourceLocation Loc) { 3884 if (!CGF.HaveInsertPoint()) 3885 return; 3886 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 3887 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3888 llvm::Value *Args[] = { 3889 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3890 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 3891 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3892 } 3893 3894 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3895 SourceLocation Loc) { 3896 if (!CGF.HaveInsertPoint()) 3897 return; 3898 // Build call void __kmpc_flush(ident_t *loc) 3899 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3900 emitUpdateLocation(CGF, Loc)); 3901 } 3902 3903 namespace { 3904 /// Indexes of fields for type kmp_task_t. 3905 enum KmpTaskTFields { 3906 /// List of shared variables. 3907 KmpTaskTShareds, 3908 /// Task routine. 3909 KmpTaskTRoutine, 3910 /// Partition id for the untied tasks. 3911 KmpTaskTPartId, 3912 /// Function with call of destructors for private variables. 3913 Data1, 3914 /// Task priority. 3915 Data2, 3916 /// (Taskloops only) Lower bound. 3917 KmpTaskTLowerBound, 3918 /// (Taskloops only) Upper bound. 3919 KmpTaskTUpperBound, 3920 /// (Taskloops only) Stride. 3921 KmpTaskTStride, 3922 /// (Taskloops only) Is last iteration flag. 3923 KmpTaskTLastIter, 3924 /// (Taskloops only) Reduction data. 3925 KmpTaskTReductions, 3926 }; 3927 } // anonymous namespace 3928 3929 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3930 return OffloadEntriesTargetRegion.empty() && 3931 OffloadEntriesDeviceGlobalVar.empty(); 3932 } 3933 3934 /// Initialize target region entry. 3935 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3936 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3937 StringRef ParentName, unsigned LineNum, 3938 unsigned Order) { 3939 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3940 "only required for the device " 3941 "code generation."); 3942 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3943 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3944 OMPTargetRegionEntryTargetRegion); 3945 ++OffloadingEntriesNum; 3946 } 3947 3948 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3949 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3950 StringRef ParentName, unsigned LineNum, 3951 llvm::Constant *Addr, llvm::Constant *ID, 3952 OMPTargetRegionEntryKind Flags) { 3953 // If we are emitting code for a target, the entry is already initialized, 3954 // only has to be registered. 3955 if (CGM.getLangOpts().OpenMPIsDevice) { 3956 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3957 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3958 DiagnosticsEngine::Error, 3959 "Unable to find target region on line '%0' in the device code."); 3960 CGM.getDiags().Report(DiagID) << LineNum; 3961 return; 3962 } 3963 auto &Entry = 3964 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3965 assert(Entry.isValid() && "Entry not initialized!"); 3966 Entry.setAddress(Addr); 3967 Entry.setID(ID); 3968 Entry.setFlags(Flags); 3969 } else { 3970 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3971 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3972 ++OffloadingEntriesNum; 3973 } 3974 } 3975 3976 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3977 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3978 unsigned LineNum) const { 3979 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3980 if (PerDevice == OffloadEntriesTargetRegion.end()) 3981 return false; 3982 auto PerFile = PerDevice->second.find(FileID); 3983 if (PerFile == PerDevice->second.end()) 3984 return false; 3985 auto PerParentName = PerFile->second.find(ParentName); 3986 if (PerParentName == PerFile->second.end()) 3987 return false; 3988 auto PerLine = PerParentName->second.find(LineNum); 3989 if (PerLine == PerParentName->second.end()) 3990 return false; 3991 // Fail if this entry is already registered. 3992 if (PerLine->second.getAddress() || PerLine->second.getID()) 3993 return false; 3994 return true; 3995 } 3996 3997 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3998 const OffloadTargetRegionEntryInfoActTy &Action) { 3999 // Scan all target region entries and perform the provided action. 4000 for (const auto &D : OffloadEntriesTargetRegion) 4001 for (const auto &F : D.second) 4002 for (const auto &P : F.second) 4003 for (const auto &L : P.second) 4004 Action(D.first, F.first, P.first(), L.first, L.second); 4005 } 4006 4007 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4008 initializeDeviceGlobalVarEntryInfo(StringRef Name, 4009 OMPTargetGlobalVarEntryKind Flags, 4010 unsigned Order) { 4011 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 4012 "only required for the device " 4013 "code generation."); 4014 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 4015 ++OffloadingEntriesNum; 4016 } 4017 4018 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4019 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 4020 CharUnits VarSize, 4021 OMPTargetGlobalVarEntryKind Flags, 4022 llvm::GlobalValue::LinkageTypes Linkage) { 4023 if (CGM.getLangOpts().OpenMPIsDevice) { 4024 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4025 assert(Entry.isValid() && Entry.getFlags() == Flags && 4026 "Entry not initialized!"); 4027 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4028 "Resetting with the new address."); 4029 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 4030 if (Entry.getVarSize().isZero()) { 4031 Entry.setVarSize(VarSize); 4032 Entry.setLinkage(Linkage); 4033 } 4034 return; 4035 } 4036 Entry.setVarSize(VarSize); 4037 Entry.setLinkage(Linkage); 4038 Entry.setAddress(Addr); 4039 } else { 4040 if (hasDeviceGlobalVarEntryInfo(VarName)) { 4041 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4042 assert(Entry.isValid() && Entry.getFlags() == Flags && 4043 "Entry not initialized!"); 4044 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4045 "Resetting with the new address."); 4046 if (Entry.getVarSize().isZero()) { 4047 Entry.setVarSize(VarSize); 4048 Entry.setLinkage(Linkage); 4049 } 4050 return; 4051 } 4052 OffloadEntriesDeviceGlobalVar.try_emplace( 4053 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4054 ++OffloadingEntriesNum; 4055 } 4056 } 4057 4058 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4059 actOnDeviceGlobalVarEntriesInfo( 4060 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4061 // Scan all target region entries and perform the provided action. 4062 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4063 Action(E.getKey(), E.getValue()); 4064 } 4065 4066 void CGOpenMPRuntime::createOffloadEntry( 4067 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4068 llvm::GlobalValue::LinkageTypes Linkage) { 4069 StringRef Name = Addr->getName(); 4070 llvm::Module &M = CGM.getModule(); 4071 llvm::LLVMContext &C = M.getContext(); 4072 4073 // Create constant string with the name. 4074 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4075 4076 std::string StringName = getName({"omp_offloading", "entry_name"}); 4077 auto *Str = new llvm::GlobalVariable( 4078 M, StrPtrInit->getType(), /*isConstant=*/true, 4079 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4080 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4081 4082 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4083 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4084 llvm::ConstantInt::get(CGM.SizeTy, Size), 4085 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4086 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4087 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4088 llvm::GlobalVariable *Entry = createGlobalStruct( 4089 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4090 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4091 4092 // The entry has to be created in the section the linker expects it to be. 4093 Entry->setSection("omp_offloading_entries"); 4094 } 4095 4096 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4097 // Emit the offloading entries and metadata so that the device codegen side 4098 // can easily figure out what to emit. The produced metadata looks like 4099 // this: 4100 // 4101 // !omp_offload.info = !{!1, ...} 4102 // 4103 // Right now we only generate metadata for function that contain target 4104 // regions. 4105 4106 // If we are in simd mode or there are no entries, we don't need to do 4107 // anything. 4108 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4109 return; 4110 4111 llvm::Module &M = CGM.getModule(); 4112 llvm::LLVMContext &C = M.getContext(); 4113 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4114 SourceLocation, StringRef>, 4115 16> 4116 OrderedEntries(OffloadEntriesInfoManager.size()); 4117 llvm::SmallVector<StringRef, 16> ParentFunctions( 4118 OffloadEntriesInfoManager.size()); 4119 4120 // Auxiliary methods to create metadata values and strings. 4121 auto &&GetMDInt = [this](unsigned V) { 4122 return llvm::ConstantAsMetadata::get( 4123 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4124 }; 4125 4126 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4127 4128 // Create the offloading info metadata node. 4129 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4130 4131 // Create function that emits metadata for each target region entry; 4132 auto &&TargetRegionMetadataEmitter = 4133 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4134 &GetMDString]( 4135 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4136 unsigned Line, 4137 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4138 // Generate metadata for target regions. Each entry of this metadata 4139 // contains: 4140 // - Entry 0 -> Kind of this type of metadata (0). 4141 // - Entry 1 -> Device ID of the file where the entry was identified. 4142 // - Entry 2 -> File ID of the file where the entry was identified. 4143 // - Entry 3 -> Mangled name of the function where the entry was 4144 // identified. 4145 // - Entry 4 -> Line in the file where the entry was identified. 4146 // - Entry 5 -> Order the entry was created. 4147 // The first element of the metadata node is the kind. 4148 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4149 GetMDInt(FileID), GetMDString(ParentName), 4150 GetMDInt(Line), GetMDInt(E.getOrder())}; 4151 4152 SourceLocation Loc; 4153 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4154 E = CGM.getContext().getSourceManager().fileinfo_end(); 4155 I != E; ++I) { 4156 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4157 I->getFirst()->getUniqueID().getFile() == FileID) { 4158 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4159 I->getFirst(), Line, 1); 4160 break; 4161 } 4162 } 4163 // Save this entry in the right position of the ordered entries array. 4164 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4165 ParentFunctions[E.getOrder()] = ParentName; 4166 4167 // Add metadata to the named metadata node. 4168 MD->addOperand(llvm::MDNode::get(C, Ops)); 4169 }; 4170 4171 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4172 TargetRegionMetadataEmitter); 4173 4174 // Create function that emits metadata for each device global variable entry; 4175 auto &&DeviceGlobalVarMetadataEmitter = 4176 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4177 MD](StringRef MangledName, 4178 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4179 &E) { 4180 // Generate metadata for global variables. Each entry of this metadata 4181 // contains: 4182 // - Entry 0 -> Kind of this type of metadata (1). 4183 // - Entry 1 -> Mangled name of the variable. 4184 // - Entry 2 -> Declare target kind. 4185 // - Entry 3 -> Order the entry was created. 4186 // The first element of the metadata node is the kind. 4187 llvm::Metadata *Ops[] = { 4188 GetMDInt(E.getKind()), GetMDString(MangledName), 4189 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4190 4191 // Save this entry in the right position of the ordered entries array. 4192 OrderedEntries[E.getOrder()] = 4193 std::make_tuple(&E, SourceLocation(), MangledName); 4194 4195 // Add metadata to the named metadata node. 4196 MD->addOperand(llvm::MDNode::get(C, Ops)); 4197 }; 4198 4199 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4200 DeviceGlobalVarMetadataEmitter); 4201 4202 for (const auto &E : OrderedEntries) { 4203 assert(std::get<0>(E) && "All ordered entries must exist!"); 4204 if (const auto *CE = 4205 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4206 std::get<0>(E))) { 4207 if (!CE->getID() || !CE->getAddress()) { 4208 // Do not blame the entry if the parent funtion is not emitted. 4209 StringRef FnName = ParentFunctions[CE->getOrder()]; 4210 if (!CGM.GetGlobalValue(FnName)) 4211 continue; 4212 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4213 DiagnosticsEngine::Error, 4214 "Offloading entry for target region in %0 is incorrect: either the " 4215 "address or the ID is invalid."); 4216 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4217 continue; 4218 } 4219 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4220 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4221 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4222 OffloadEntryInfoDeviceGlobalVar>( 4223 std::get<0>(E))) { 4224 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4225 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4226 CE->getFlags()); 4227 switch (Flags) { 4228 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4229 if (CGM.getLangOpts().OpenMPIsDevice && 4230 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4231 continue; 4232 if (!CE->getAddress()) { 4233 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4234 DiagnosticsEngine::Error, "Offloading entry for declare target " 4235 "variable %0 is incorrect: the " 4236 "address is invalid."); 4237 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4238 continue; 4239 } 4240 // The vaiable has no definition - no need to add the entry. 4241 if (CE->getVarSize().isZero()) 4242 continue; 4243 break; 4244 } 4245 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4246 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4247 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4248 "Declaret target link address is set."); 4249 if (CGM.getLangOpts().OpenMPIsDevice) 4250 continue; 4251 if (!CE->getAddress()) { 4252 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4253 DiagnosticsEngine::Error, 4254 "Offloading entry for declare target variable is incorrect: the " 4255 "address is invalid."); 4256 CGM.getDiags().Report(DiagID); 4257 continue; 4258 } 4259 break; 4260 } 4261 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4262 CE->getVarSize().getQuantity(), Flags, 4263 CE->getLinkage()); 4264 } else { 4265 llvm_unreachable("Unsupported entry kind."); 4266 } 4267 } 4268 } 4269 4270 /// Loads all the offload entries information from the host IR 4271 /// metadata. 4272 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4273 // If we are in target mode, load the metadata from the host IR. This code has 4274 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4275 4276 if (!CGM.getLangOpts().OpenMPIsDevice) 4277 return; 4278 4279 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4280 return; 4281 4282 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4283 if (auto EC = Buf.getError()) { 4284 CGM.getDiags().Report(diag::err_cannot_open_file) 4285 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4286 return; 4287 } 4288 4289 llvm::LLVMContext C; 4290 auto ME = expectedToErrorOrAndEmitErrors( 4291 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4292 4293 if (auto EC = ME.getError()) { 4294 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4295 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4296 CGM.getDiags().Report(DiagID) 4297 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4298 return; 4299 } 4300 4301 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4302 if (!MD) 4303 return; 4304 4305 for (llvm::MDNode *MN : MD->operands()) { 4306 auto &&GetMDInt = [MN](unsigned Idx) { 4307 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4308 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4309 }; 4310 4311 auto &&GetMDString = [MN](unsigned Idx) { 4312 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4313 return V->getString(); 4314 }; 4315 4316 switch (GetMDInt(0)) { 4317 default: 4318 llvm_unreachable("Unexpected metadata!"); 4319 break; 4320 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4321 OffloadingEntryInfoTargetRegion: 4322 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4323 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4324 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4325 /*Order=*/GetMDInt(5)); 4326 break; 4327 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4328 OffloadingEntryInfoDeviceGlobalVar: 4329 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4330 /*MangledName=*/GetMDString(1), 4331 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4332 /*Flags=*/GetMDInt(2)), 4333 /*Order=*/GetMDInt(3)); 4334 break; 4335 } 4336 } 4337 } 4338 4339 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4340 if (!KmpRoutineEntryPtrTy) { 4341 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4342 ASTContext &C = CGM.getContext(); 4343 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4344 FunctionProtoType::ExtProtoInfo EPI; 4345 KmpRoutineEntryPtrQTy = C.getPointerType( 4346 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4347 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4348 } 4349 } 4350 4351 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4352 // Make sure the type of the entry is already created. This is the type we 4353 // have to create: 4354 // struct __tgt_offload_entry{ 4355 // void *addr; // Pointer to the offload entry info. 4356 // // (function or global) 4357 // char *name; // Name of the function or global. 4358 // size_t size; // Size of the entry info (0 if it a function). 4359 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4360 // int32_t reserved; // Reserved, to use by the runtime library. 4361 // }; 4362 if (TgtOffloadEntryQTy.isNull()) { 4363 ASTContext &C = CGM.getContext(); 4364 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4365 RD->startDefinition(); 4366 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4367 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4368 addFieldToRecordDecl(C, RD, C.getSizeType()); 4369 addFieldToRecordDecl( 4370 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4371 addFieldToRecordDecl( 4372 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4373 RD->completeDefinition(); 4374 RD->addAttr(PackedAttr::CreateImplicit(C)); 4375 TgtOffloadEntryQTy = C.getRecordType(RD); 4376 } 4377 return TgtOffloadEntryQTy; 4378 } 4379 4380 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 4381 // These are the types we need to build: 4382 // struct __tgt_device_image{ 4383 // void *ImageStart; // Pointer to the target code start. 4384 // void *ImageEnd; // Pointer to the target code end. 4385 // // We also add the host entries to the device image, as it may be useful 4386 // // for the target runtime to have access to that information. 4387 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 4388 // // the entries. 4389 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4390 // // entries (non inclusive). 4391 // }; 4392 if (TgtDeviceImageQTy.isNull()) { 4393 ASTContext &C = CGM.getContext(); 4394 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); 4395 RD->startDefinition(); 4396 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4397 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4398 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4399 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4400 RD->completeDefinition(); 4401 TgtDeviceImageQTy = C.getRecordType(RD); 4402 } 4403 return TgtDeviceImageQTy; 4404 } 4405 4406 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 4407 // struct __tgt_bin_desc{ 4408 // int32_t NumDevices; // Number of devices supported. 4409 // __tgt_device_image *DeviceImages; // Arrays of device images 4410 // // (one per device). 4411 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 4412 // // entries. 4413 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4414 // // entries (non inclusive). 4415 // }; 4416 if (TgtBinaryDescriptorQTy.isNull()) { 4417 ASTContext &C = CGM.getContext(); 4418 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); 4419 RD->startDefinition(); 4420 addFieldToRecordDecl( 4421 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4422 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 4423 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4424 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4425 RD->completeDefinition(); 4426 TgtBinaryDescriptorQTy = C.getRecordType(RD); 4427 } 4428 return TgtBinaryDescriptorQTy; 4429 } 4430 4431 namespace { 4432 struct PrivateHelpersTy { 4433 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4434 const VarDecl *PrivateElemInit) 4435 : Original(Original), PrivateCopy(PrivateCopy), 4436 PrivateElemInit(PrivateElemInit) {} 4437 const VarDecl *Original; 4438 const VarDecl *PrivateCopy; 4439 const VarDecl *PrivateElemInit; 4440 }; 4441 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4442 } // anonymous namespace 4443 4444 static RecordDecl * 4445 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4446 if (!Privates.empty()) { 4447 ASTContext &C = CGM.getContext(); 4448 // Build struct .kmp_privates_t. { 4449 // /* private vars */ 4450 // }; 4451 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4452 RD->startDefinition(); 4453 for (const auto &Pair : Privates) { 4454 const VarDecl *VD = Pair.second.Original; 4455 QualType Type = VD->getType().getNonReferenceType(); 4456 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4457 if (VD->hasAttrs()) { 4458 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4459 E(VD->getAttrs().end()); 4460 I != E; ++I) 4461 FD->addAttr(*I); 4462 } 4463 } 4464 RD->completeDefinition(); 4465 return RD; 4466 } 4467 return nullptr; 4468 } 4469 4470 static RecordDecl * 4471 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4472 QualType KmpInt32Ty, 4473 QualType KmpRoutineEntryPointerQTy) { 4474 ASTContext &C = CGM.getContext(); 4475 // Build struct kmp_task_t { 4476 // void * shareds; 4477 // kmp_routine_entry_t routine; 4478 // kmp_int32 part_id; 4479 // kmp_cmplrdata_t data1; 4480 // kmp_cmplrdata_t data2; 4481 // For taskloops additional fields: 4482 // kmp_uint64 lb; 4483 // kmp_uint64 ub; 4484 // kmp_int64 st; 4485 // kmp_int32 liter; 4486 // void * reductions; 4487 // }; 4488 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4489 UD->startDefinition(); 4490 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4491 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4492 UD->completeDefinition(); 4493 QualType KmpCmplrdataTy = C.getRecordType(UD); 4494 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4495 RD->startDefinition(); 4496 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4497 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4498 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4499 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4500 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4501 if (isOpenMPTaskLoopDirective(Kind)) { 4502 QualType KmpUInt64Ty = 4503 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4504 QualType KmpInt64Ty = 4505 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4506 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4507 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4508 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4509 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4510 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4511 } 4512 RD->completeDefinition(); 4513 return RD; 4514 } 4515 4516 static RecordDecl * 4517 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4518 ArrayRef<PrivateDataTy> Privates) { 4519 ASTContext &C = CGM.getContext(); 4520 // Build struct kmp_task_t_with_privates { 4521 // kmp_task_t task_data; 4522 // .kmp_privates_t. privates; 4523 // }; 4524 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4525 RD->startDefinition(); 4526 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4527 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4528 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4529 RD->completeDefinition(); 4530 return RD; 4531 } 4532 4533 /// Emit a proxy function which accepts kmp_task_t as the second 4534 /// argument. 4535 /// \code 4536 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4537 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4538 /// For taskloops: 4539 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4540 /// tt->reductions, tt->shareds); 4541 /// return 0; 4542 /// } 4543 /// \endcode 4544 static llvm::Function * 4545 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4546 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4547 QualType KmpTaskTWithPrivatesPtrQTy, 4548 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4549 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4550 llvm::Value *TaskPrivatesMap) { 4551 ASTContext &C = CGM.getContext(); 4552 FunctionArgList Args; 4553 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4554 ImplicitParamDecl::Other); 4555 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4556 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4557 ImplicitParamDecl::Other); 4558 Args.push_back(&GtidArg); 4559 Args.push_back(&TaskTypeArg); 4560 const auto &TaskEntryFnInfo = 4561 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4562 llvm::FunctionType *TaskEntryTy = 4563 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4564 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4565 auto *TaskEntry = llvm::Function::Create( 4566 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4567 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4568 TaskEntry->setDoesNotRecurse(); 4569 CodeGenFunction CGF(CGM); 4570 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4571 Loc, Loc); 4572 4573 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4574 // tt, 4575 // For taskloops: 4576 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4577 // tt->task_data.shareds); 4578 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4579 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4580 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4581 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4582 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4583 const auto *KmpTaskTWithPrivatesQTyRD = 4584 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4585 LValue Base = 4586 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4587 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4588 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4589 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4590 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4591 4592 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4593 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4594 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4595 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4596 CGF.ConvertTypeForMem(SharedsPtrTy)); 4597 4598 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4599 llvm::Value *PrivatesParam; 4600 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4601 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4602 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4603 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4604 } else { 4605 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4606 } 4607 4608 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4609 TaskPrivatesMap, 4610 CGF.Builder 4611 .CreatePointerBitCastOrAddrSpaceCast( 4612 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4613 .getPointer()}; 4614 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4615 std::end(CommonArgs)); 4616 if (isOpenMPTaskLoopDirective(Kind)) { 4617 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4618 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4619 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4620 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4621 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4622 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4623 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4624 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4625 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4626 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4627 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4628 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4629 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4630 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4631 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4632 CallArgs.push_back(LBParam); 4633 CallArgs.push_back(UBParam); 4634 CallArgs.push_back(StParam); 4635 CallArgs.push_back(LIParam); 4636 CallArgs.push_back(RParam); 4637 } 4638 CallArgs.push_back(SharedsParam); 4639 4640 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4641 CallArgs); 4642 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4643 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4644 CGF.FinishFunction(); 4645 return TaskEntry; 4646 } 4647 4648 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4649 SourceLocation Loc, 4650 QualType KmpInt32Ty, 4651 QualType KmpTaskTWithPrivatesPtrQTy, 4652 QualType KmpTaskTWithPrivatesQTy) { 4653 ASTContext &C = CGM.getContext(); 4654 FunctionArgList Args; 4655 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4656 ImplicitParamDecl::Other); 4657 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4658 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4659 ImplicitParamDecl::Other); 4660 Args.push_back(&GtidArg); 4661 Args.push_back(&TaskTypeArg); 4662 const auto &DestructorFnInfo = 4663 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4664 llvm::FunctionType *DestructorFnTy = 4665 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4666 std::string Name = 4667 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4668 auto *DestructorFn = 4669 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4670 Name, &CGM.getModule()); 4671 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4672 DestructorFnInfo); 4673 DestructorFn->setDoesNotRecurse(); 4674 CodeGenFunction CGF(CGM); 4675 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4676 Args, Loc, Loc); 4677 4678 LValue Base = CGF.EmitLoadOfPointerLValue( 4679 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4680 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4681 const auto *KmpTaskTWithPrivatesQTyRD = 4682 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4683 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4684 Base = CGF.EmitLValueForField(Base, *FI); 4685 for (const auto *Field : 4686 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4687 if (QualType::DestructionKind DtorKind = 4688 Field->getType().isDestructedType()) { 4689 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4690 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4691 } 4692 } 4693 CGF.FinishFunction(); 4694 return DestructorFn; 4695 } 4696 4697 /// Emit a privates mapping function for correct handling of private and 4698 /// firstprivate variables. 4699 /// \code 4700 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4701 /// **noalias priv1,..., <tyn> **noalias privn) { 4702 /// *priv1 = &.privates.priv1; 4703 /// ...; 4704 /// *privn = &.privates.privn; 4705 /// } 4706 /// \endcode 4707 static llvm::Value * 4708 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4709 ArrayRef<const Expr *> PrivateVars, 4710 ArrayRef<const Expr *> FirstprivateVars, 4711 ArrayRef<const Expr *> LastprivateVars, 4712 QualType PrivatesQTy, 4713 ArrayRef<PrivateDataTy> Privates) { 4714 ASTContext &C = CGM.getContext(); 4715 FunctionArgList Args; 4716 ImplicitParamDecl TaskPrivatesArg( 4717 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4718 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4719 ImplicitParamDecl::Other); 4720 Args.push_back(&TaskPrivatesArg); 4721 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4722 unsigned Counter = 1; 4723 for (const Expr *E : PrivateVars) { 4724 Args.push_back(ImplicitParamDecl::Create( 4725 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4726 C.getPointerType(C.getPointerType(E->getType())) 4727 .withConst() 4728 .withRestrict(), 4729 ImplicitParamDecl::Other)); 4730 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4731 PrivateVarsPos[VD] = Counter; 4732 ++Counter; 4733 } 4734 for (const Expr *E : FirstprivateVars) { 4735 Args.push_back(ImplicitParamDecl::Create( 4736 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4737 C.getPointerType(C.getPointerType(E->getType())) 4738 .withConst() 4739 .withRestrict(), 4740 ImplicitParamDecl::Other)); 4741 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4742 PrivateVarsPos[VD] = Counter; 4743 ++Counter; 4744 } 4745 for (const Expr *E : LastprivateVars) { 4746 Args.push_back(ImplicitParamDecl::Create( 4747 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4748 C.getPointerType(C.getPointerType(E->getType())) 4749 .withConst() 4750 .withRestrict(), 4751 ImplicitParamDecl::Other)); 4752 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4753 PrivateVarsPos[VD] = Counter; 4754 ++Counter; 4755 } 4756 const auto &TaskPrivatesMapFnInfo = 4757 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4758 llvm::FunctionType *TaskPrivatesMapTy = 4759 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4760 std::string Name = 4761 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4762 auto *TaskPrivatesMap = llvm::Function::Create( 4763 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4764 &CGM.getModule()); 4765 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4766 TaskPrivatesMapFnInfo); 4767 if (CGM.getLangOpts().Optimize) { 4768 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4769 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4770 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4771 } 4772 CodeGenFunction CGF(CGM); 4773 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4774 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4775 4776 // *privi = &.privates.privi; 4777 LValue Base = CGF.EmitLoadOfPointerLValue( 4778 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4779 TaskPrivatesArg.getType()->castAs<PointerType>()); 4780 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4781 Counter = 0; 4782 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4783 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4784 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4785 LValue RefLVal = 4786 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4787 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4788 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4789 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4790 ++Counter; 4791 } 4792 CGF.FinishFunction(); 4793 return TaskPrivatesMap; 4794 } 4795 4796 /// Emit initialization for private variables in task-based directives. 4797 static void emitPrivatesInit(CodeGenFunction &CGF, 4798 const OMPExecutableDirective &D, 4799 Address KmpTaskSharedsPtr, LValue TDBase, 4800 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4801 QualType SharedsTy, QualType SharedsPtrTy, 4802 const OMPTaskDataTy &Data, 4803 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4804 ASTContext &C = CGF.getContext(); 4805 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4806 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4807 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4808 ? OMPD_taskloop 4809 : OMPD_task; 4810 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4811 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4812 LValue SrcBase; 4813 bool IsTargetTask = 4814 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4815 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4816 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4817 // PointersArray and SizesArray. The original variables for these arrays are 4818 // not captured and we get their addresses explicitly. 4819 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4820 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4821 SrcBase = CGF.MakeAddrLValue( 4822 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4823 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4824 SharedsTy); 4825 } 4826 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4827 for (const PrivateDataTy &Pair : Privates) { 4828 const VarDecl *VD = Pair.second.PrivateCopy; 4829 const Expr *Init = VD->getAnyInitializer(); 4830 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4831 !CGF.isTrivialInitializer(Init)))) { 4832 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4833 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4834 const VarDecl *OriginalVD = Pair.second.Original; 4835 // Check if the variable is the target-based BasePointersArray, 4836 // PointersArray or SizesArray. 4837 LValue SharedRefLValue; 4838 QualType Type = PrivateLValue.getType(); 4839 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4840 if (IsTargetTask && !SharedField) { 4841 assert(isa<ImplicitParamDecl>(OriginalVD) && 4842 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4843 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4844 ->getNumParams() == 0 && 4845 isa<TranslationUnitDecl>( 4846 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4847 ->getDeclContext()) && 4848 "Expected artificial target data variable."); 4849 SharedRefLValue = 4850 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4851 } else { 4852 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4853 SharedRefLValue = CGF.MakeAddrLValue( 4854 Address(SharedRefLValue.getPointer(CGF), 4855 C.getDeclAlign(OriginalVD)), 4856 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4857 SharedRefLValue.getTBAAInfo()); 4858 } 4859 if (Type->isArrayType()) { 4860 // Initialize firstprivate array. 4861 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4862 // Perform simple memcpy. 4863 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4864 } else { 4865 // Initialize firstprivate array using element-by-element 4866 // initialization. 4867 CGF.EmitOMPAggregateAssign( 4868 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4869 Type, 4870 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4871 Address SrcElement) { 4872 // Clean up any temporaries needed by the initialization. 4873 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4874 InitScope.addPrivate( 4875 Elem, [SrcElement]() -> Address { return SrcElement; }); 4876 (void)InitScope.Privatize(); 4877 // Emit initialization for single element. 4878 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4879 CGF, &CapturesInfo); 4880 CGF.EmitAnyExprToMem(Init, DestElement, 4881 Init->getType().getQualifiers(), 4882 /*IsInitializer=*/false); 4883 }); 4884 } 4885 } else { 4886 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4887 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4888 return SharedRefLValue.getAddress(CGF); 4889 }); 4890 (void)InitScope.Privatize(); 4891 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4892 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4893 /*capturedByInit=*/false); 4894 } 4895 } else { 4896 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4897 } 4898 } 4899 ++FI; 4900 } 4901 } 4902 4903 /// Check if duplication function is required for taskloops. 4904 static bool checkInitIsRequired(CodeGenFunction &CGF, 4905 ArrayRef<PrivateDataTy> Privates) { 4906 bool InitRequired = false; 4907 for (const PrivateDataTy &Pair : Privates) { 4908 const VarDecl *VD = Pair.second.PrivateCopy; 4909 const Expr *Init = VD->getAnyInitializer(); 4910 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4911 !CGF.isTrivialInitializer(Init)); 4912 if (InitRequired) 4913 break; 4914 } 4915 return InitRequired; 4916 } 4917 4918 4919 /// Emit task_dup function (for initialization of 4920 /// private/firstprivate/lastprivate vars and last_iter flag) 4921 /// \code 4922 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4923 /// lastpriv) { 4924 /// // setup lastprivate flag 4925 /// task_dst->last = lastpriv; 4926 /// // could be constructor calls here... 4927 /// } 4928 /// \endcode 4929 static llvm::Value * 4930 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4931 const OMPExecutableDirective &D, 4932 QualType KmpTaskTWithPrivatesPtrQTy, 4933 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4934 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4935 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4936 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4937 ASTContext &C = CGM.getContext(); 4938 FunctionArgList Args; 4939 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4940 KmpTaskTWithPrivatesPtrQTy, 4941 ImplicitParamDecl::Other); 4942 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4943 KmpTaskTWithPrivatesPtrQTy, 4944 ImplicitParamDecl::Other); 4945 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4946 ImplicitParamDecl::Other); 4947 Args.push_back(&DstArg); 4948 Args.push_back(&SrcArg); 4949 Args.push_back(&LastprivArg); 4950 const auto &TaskDupFnInfo = 4951 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4952 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4953 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4954 auto *TaskDup = llvm::Function::Create( 4955 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4956 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4957 TaskDup->setDoesNotRecurse(); 4958 CodeGenFunction CGF(CGM); 4959 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4960 Loc); 4961 4962 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4963 CGF.GetAddrOfLocalVar(&DstArg), 4964 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4965 // task_dst->liter = lastpriv; 4966 if (WithLastIter) { 4967 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4968 LValue Base = CGF.EmitLValueForField( 4969 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4970 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4971 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4972 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4973 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4974 } 4975 4976 // Emit initial values for private copies (if any). 4977 assert(!Privates.empty()); 4978 Address KmpTaskSharedsPtr = Address::invalid(); 4979 if (!Data.FirstprivateVars.empty()) { 4980 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4981 CGF.GetAddrOfLocalVar(&SrcArg), 4982 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4983 LValue Base = CGF.EmitLValueForField( 4984 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4985 KmpTaskSharedsPtr = Address( 4986 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4987 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4988 KmpTaskTShareds)), 4989 Loc), 4990 CGF.getNaturalTypeAlignment(SharedsTy)); 4991 } 4992 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4993 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4994 CGF.FinishFunction(); 4995 return TaskDup; 4996 } 4997 4998 /// Checks if destructor function is required to be generated. 4999 /// \return true if cleanups are required, false otherwise. 5000 static bool 5001 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 5002 bool NeedsCleanup = false; 5003 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 5004 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 5005 for (const FieldDecl *FD : PrivateRD->fields()) { 5006 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 5007 if (NeedsCleanup) 5008 break; 5009 } 5010 return NeedsCleanup; 5011 } 5012 5013 CGOpenMPRuntime::TaskResultTy 5014 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 5015 const OMPExecutableDirective &D, 5016 llvm::Function *TaskFunction, QualType SharedsTy, 5017 Address Shareds, const OMPTaskDataTy &Data) { 5018 ASTContext &C = CGM.getContext(); 5019 llvm::SmallVector<PrivateDataTy, 4> Privates; 5020 // Aggregate privates and sort them by the alignment. 5021 auto I = Data.PrivateCopies.begin(); 5022 for (const Expr *E : Data.PrivateVars) { 5023 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5024 Privates.emplace_back( 5025 C.getDeclAlign(VD), 5026 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5027 /*PrivateElemInit=*/nullptr)); 5028 ++I; 5029 } 5030 I = Data.FirstprivateCopies.begin(); 5031 auto IElemInitRef = Data.FirstprivateInits.begin(); 5032 for (const Expr *E : Data.FirstprivateVars) { 5033 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5034 Privates.emplace_back( 5035 C.getDeclAlign(VD), 5036 PrivateHelpersTy( 5037 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5038 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 5039 ++I; 5040 ++IElemInitRef; 5041 } 5042 I = Data.LastprivateCopies.begin(); 5043 for (const Expr *E : Data.LastprivateVars) { 5044 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5045 Privates.emplace_back( 5046 C.getDeclAlign(VD), 5047 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5048 /*PrivateElemInit=*/nullptr)); 5049 ++I; 5050 } 5051 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5052 return L.first > R.first; 5053 }); 5054 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5055 // Build type kmp_routine_entry_t (if not built yet). 5056 emitKmpRoutineEntryT(KmpInt32Ty); 5057 // Build type kmp_task_t (if not built yet). 5058 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5059 if (SavedKmpTaskloopTQTy.isNull()) { 5060 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5061 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5062 } 5063 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5064 } else { 5065 assert((D.getDirectiveKind() == OMPD_task || 5066 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5067 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5068 "Expected taskloop, task or target directive"); 5069 if (SavedKmpTaskTQTy.isNull()) { 5070 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5071 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5072 } 5073 KmpTaskTQTy = SavedKmpTaskTQTy; 5074 } 5075 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5076 // Build particular struct kmp_task_t for the given task. 5077 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5078 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5079 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5080 QualType KmpTaskTWithPrivatesPtrQTy = 5081 C.getPointerType(KmpTaskTWithPrivatesQTy); 5082 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5083 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5084 KmpTaskTWithPrivatesTy->getPointerTo(); 5085 llvm::Value *KmpTaskTWithPrivatesTySize = 5086 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5087 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5088 5089 // Emit initial values for private copies (if any). 5090 llvm::Value *TaskPrivatesMap = nullptr; 5091 llvm::Type *TaskPrivatesMapTy = 5092 std::next(TaskFunction->arg_begin(), 3)->getType(); 5093 if (!Privates.empty()) { 5094 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5095 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5096 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5097 FI->getType(), Privates); 5098 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5099 TaskPrivatesMap, TaskPrivatesMapTy); 5100 } else { 5101 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5102 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5103 } 5104 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5105 // kmp_task_t *tt); 5106 llvm::Function *TaskEntry = emitProxyTaskFunction( 5107 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5108 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5109 TaskPrivatesMap); 5110 5111 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5112 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5113 // kmp_routine_entry_t *task_entry); 5114 // Task flags. Format is taken from 5115 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5116 // description of kmp_tasking_flags struct. 5117 enum { 5118 TiedFlag = 0x1, 5119 FinalFlag = 0x2, 5120 DestructorsFlag = 0x8, 5121 PriorityFlag = 0x20 5122 }; 5123 unsigned Flags = Data.Tied ? TiedFlag : 0; 5124 bool NeedsCleanup = false; 5125 if (!Privates.empty()) { 5126 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5127 if (NeedsCleanup) 5128 Flags = Flags | DestructorsFlag; 5129 } 5130 if (Data.Priority.getInt()) 5131 Flags = Flags | PriorityFlag; 5132 llvm::Value *TaskFlags = 5133 Data.Final.getPointer() 5134 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5135 CGF.Builder.getInt32(FinalFlag), 5136 CGF.Builder.getInt32(/*C=*/0)) 5137 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5138 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5139 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5140 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5141 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5142 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5143 TaskEntry, KmpRoutineEntryPtrTy)}; 5144 llvm::Value *NewTask; 5145 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5146 // Check if we have any device clause associated with the directive. 5147 const Expr *Device = nullptr; 5148 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5149 Device = C->getDevice(); 5150 // Emit device ID if any otherwise use default value. 5151 llvm::Value *DeviceID; 5152 if (Device) 5153 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5154 CGF.Int64Ty, /*isSigned=*/true); 5155 else 5156 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5157 AllocArgs.push_back(DeviceID); 5158 NewTask = CGF.EmitRuntimeCall( 5159 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5160 } else { 5161 NewTask = CGF.EmitRuntimeCall( 5162 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5163 } 5164 llvm::Value *NewTaskNewTaskTTy = 5165 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5166 NewTask, KmpTaskTWithPrivatesPtrTy); 5167 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5168 KmpTaskTWithPrivatesQTy); 5169 LValue TDBase = 5170 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5171 // Fill the data in the resulting kmp_task_t record. 5172 // Copy shareds if there are any. 5173 Address KmpTaskSharedsPtr = Address::invalid(); 5174 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5175 KmpTaskSharedsPtr = 5176 Address(CGF.EmitLoadOfScalar( 5177 CGF.EmitLValueForField( 5178 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5179 KmpTaskTShareds)), 5180 Loc), 5181 CGF.getNaturalTypeAlignment(SharedsTy)); 5182 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5183 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5184 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5185 } 5186 // Emit initial values for private copies (if any). 5187 TaskResultTy Result; 5188 if (!Privates.empty()) { 5189 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5190 SharedsTy, SharedsPtrTy, Data, Privates, 5191 /*ForDup=*/false); 5192 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5193 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5194 Result.TaskDupFn = emitTaskDupFunction( 5195 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5196 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5197 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5198 } 5199 } 5200 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5201 enum { Priority = 0, Destructors = 1 }; 5202 // Provide pointer to function with destructors for privates. 5203 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5204 const RecordDecl *KmpCmplrdataUD = 5205 (*FI)->getType()->getAsUnionType()->getDecl(); 5206 if (NeedsCleanup) { 5207 llvm::Value *DestructorFn = emitDestructorsFunction( 5208 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5209 KmpTaskTWithPrivatesQTy); 5210 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5211 LValue DestructorsLV = CGF.EmitLValueForField( 5212 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5213 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5214 DestructorFn, KmpRoutineEntryPtrTy), 5215 DestructorsLV); 5216 } 5217 // Set priority. 5218 if (Data.Priority.getInt()) { 5219 LValue Data2LV = CGF.EmitLValueForField( 5220 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5221 LValue PriorityLV = CGF.EmitLValueForField( 5222 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5223 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5224 } 5225 Result.NewTask = NewTask; 5226 Result.TaskEntry = TaskEntry; 5227 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5228 Result.TDBase = TDBase; 5229 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5230 return Result; 5231 } 5232 5233 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5234 const OMPExecutableDirective &D, 5235 llvm::Function *TaskFunction, 5236 QualType SharedsTy, Address Shareds, 5237 const Expr *IfCond, 5238 const OMPTaskDataTy &Data) { 5239 if (!CGF.HaveInsertPoint()) 5240 return; 5241 5242 TaskResultTy Result = 5243 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5244 llvm::Value *NewTask = Result.NewTask; 5245 llvm::Function *TaskEntry = Result.TaskEntry; 5246 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5247 LValue TDBase = Result.TDBase; 5248 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5249 ASTContext &C = CGM.getContext(); 5250 // Process list of dependences. 5251 Address DependenciesArray = Address::invalid(); 5252 unsigned NumDependencies = Data.Dependences.size(); 5253 if (NumDependencies) { 5254 // Dependence kind for RTL. 5255 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5256 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5257 RecordDecl *KmpDependInfoRD; 5258 QualType FlagsTy = 5259 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5260 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5261 if (KmpDependInfoTy.isNull()) { 5262 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5263 KmpDependInfoRD->startDefinition(); 5264 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5265 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5266 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5267 KmpDependInfoRD->completeDefinition(); 5268 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5269 } else { 5270 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5271 } 5272 // Define type kmp_depend_info[<Dependences.size()>]; 5273 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5274 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5275 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5276 // kmp_depend_info[<Dependences.size()>] deps; 5277 DependenciesArray = 5278 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5279 for (unsigned I = 0; I < NumDependencies; ++I) { 5280 const Expr *E = Data.Dependences[I].second; 5281 LValue Addr = CGF.EmitLValue(E); 5282 llvm::Value *Size; 5283 QualType Ty = E->getType(); 5284 if (const auto *ASE = 5285 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5286 LValue UpAddrLVal = 5287 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5288 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5289 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5290 llvm::Value *LowIntPtr = 5291 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy); 5292 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5293 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5294 } else { 5295 Size = CGF.getTypeSize(Ty); 5296 } 5297 LValue Base = CGF.MakeAddrLValue( 5298 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5299 KmpDependInfoTy); 5300 // deps[i].base_addr = &<Dependences[i].second>; 5301 LValue BaseAddrLVal = CGF.EmitLValueForField( 5302 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5303 CGF.EmitStoreOfScalar( 5304 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy), 5305 BaseAddrLVal); 5306 // deps[i].len = sizeof(<Dependences[i].second>); 5307 LValue LenLVal = CGF.EmitLValueForField( 5308 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5309 CGF.EmitStoreOfScalar(Size, LenLVal); 5310 // deps[i].flags = <Dependences[i].first>; 5311 RTLDependenceKindTy DepKind; 5312 switch (Data.Dependences[I].first) { 5313 case OMPC_DEPEND_in: 5314 DepKind = DepIn; 5315 break; 5316 // Out and InOut dependencies must use the same code. 5317 case OMPC_DEPEND_out: 5318 case OMPC_DEPEND_inout: 5319 DepKind = DepInOut; 5320 break; 5321 case OMPC_DEPEND_mutexinoutset: 5322 DepKind = DepMutexInOutSet; 5323 break; 5324 case OMPC_DEPEND_source: 5325 case OMPC_DEPEND_sink: 5326 case OMPC_DEPEND_unknown: 5327 llvm_unreachable("Unknown task dependence type"); 5328 } 5329 LValue FlagsLVal = CGF.EmitLValueForField( 5330 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5331 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5332 FlagsLVal); 5333 } 5334 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5335 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5336 } 5337 5338 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5339 // libcall. 5340 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5341 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5342 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5343 // list is not empty 5344 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5345 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5346 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5347 llvm::Value *DepTaskArgs[7]; 5348 if (NumDependencies) { 5349 DepTaskArgs[0] = UpLoc; 5350 DepTaskArgs[1] = ThreadID; 5351 DepTaskArgs[2] = NewTask; 5352 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5353 DepTaskArgs[4] = DependenciesArray.getPointer(); 5354 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5355 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5356 } 5357 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5358 &TaskArgs, 5359 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5360 if (!Data.Tied) { 5361 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5362 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5363 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5364 } 5365 if (NumDependencies) { 5366 CGF.EmitRuntimeCall( 5367 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5368 } else { 5369 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5370 TaskArgs); 5371 } 5372 // Check if parent region is untied and build return for untied task; 5373 if (auto *Region = 5374 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5375 Region->emitUntiedSwitch(CGF); 5376 }; 5377 5378 llvm::Value *DepWaitTaskArgs[6]; 5379 if (NumDependencies) { 5380 DepWaitTaskArgs[0] = UpLoc; 5381 DepWaitTaskArgs[1] = ThreadID; 5382 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5383 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5384 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5385 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5386 } 5387 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5388 NumDependencies, &DepWaitTaskArgs, 5389 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5390 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5391 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5392 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5393 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5394 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5395 // is specified. 5396 if (NumDependencies) 5397 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5398 DepWaitTaskArgs); 5399 // Call proxy_task_entry(gtid, new_task); 5400 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5401 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5402 Action.Enter(CGF); 5403 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5404 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5405 OutlinedFnArgs); 5406 }; 5407 5408 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5409 // kmp_task_t *new_task); 5410 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5411 // kmp_task_t *new_task); 5412 RegionCodeGenTy RCG(CodeGen); 5413 CommonActionTy Action( 5414 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5415 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5416 RCG.setAction(Action); 5417 RCG(CGF); 5418 }; 5419 5420 if (IfCond) { 5421 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5422 } else { 5423 RegionCodeGenTy ThenRCG(ThenCodeGen); 5424 ThenRCG(CGF); 5425 } 5426 } 5427 5428 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5429 const OMPLoopDirective &D, 5430 llvm::Function *TaskFunction, 5431 QualType SharedsTy, Address Shareds, 5432 const Expr *IfCond, 5433 const OMPTaskDataTy &Data) { 5434 if (!CGF.HaveInsertPoint()) 5435 return; 5436 TaskResultTy Result = 5437 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5438 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5439 // libcall. 5440 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5441 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5442 // sched, kmp_uint64 grainsize, void *task_dup); 5443 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5444 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5445 llvm::Value *IfVal; 5446 if (IfCond) { 5447 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5448 /*isSigned=*/true); 5449 } else { 5450 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5451 } 5452 5453 LValue LBLVal = CGF.EmitLValueForField( 5454 Result.TDBase, 5455 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5456 const auto *LBVar = 5457 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5458 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5459 LBLVal.getQuals(), 5460 /*IsInitializer=*/true); 5461 LValue UBLVal = CGF.EmitLValueForField( 5462 Result.TDBase, 5463 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5464 const auto *UBVar = 5465 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5466 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5467 UBLVal.getQuals(), 5468 /*IsInitializer=*/true); 5469 LValue StLVal = CGF.EmitLValueForField( 5470 Result.TDBase, 5471 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5472 const auto *StVar = 5473 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5474 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5475 StLVal.getQuals(), 5476 /*IsInitializer=*/true); 5477 // Store reductions address. 5478 LValue RedLVal = CGF.EmitLValueForField( 5479 Result.TDBase, 5480 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5481 if (Data.Reductions) { 5482 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5483 } else { 5484 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5485 CGF.getContext().VoidPtrTy); 5486 } 5487 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5488 llvm::Value *TaskArgs[] = { 5489 UpLoc, 5490 ThreadID, 5491 Result.NewTask, 5492 IfVal, 5493 LBLVal.getPointer(CGF), 5494 UBLVal.getPointer(CGF), 5495 CGF.EmitLoadOfScalar(StLVal, Loc), 5496 llvm::ConstantInt::getSigned( 5497 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5498 llvm::ConstantInt::getSigned( 5499 CGF.IntTy, Data.Schedule.getPointer() 5500 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5501 : NoSchedule), 5502 Data.Schedule.getPointer() 5503 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5504 /*isSigned=*/false) 5505 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5506 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5507 Result.TaskDupFn, CGF.VoidPtrTy) 5508 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5509 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5510 } 5511 5512 /// Emit reduction operation for each element of array (required for 5513 /// array sections) LHS op = RHS. 5514 /// \param Type Type of array. 5515 /// \param LHSVar Variable on the left side of the reduction operation 5516 /// (references element of array in original variable). 5517 /// \param RHSVar Variable on the right side of the reduction operation 5518 /// (references element of array in original variable). 5519 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5520 /// RHSVar. 5521 static void EmitOMPAggregateReduction( 5522 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5523 const VarDecl *RHSVar, 5524 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5525 const Expr *, const Expr *)> &RedOpGen, 5526 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5527 const Expr *UpExpr = nullptr) { 5528 // Perform element-by-element initialization. 5529 QualType ElementTy; 5530 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5531 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5532 5533 // Drill down to the base element type on both arrays. 5534 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5535 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5536 5537 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5538 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5539 // Cast from pointer to array type to pointer to single element. 5540 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5541 // The basic structure here is a while-do loop. 5542 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5543 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5544 llvm::Value *IsEmpty = 5545 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5546 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5547 5548 // Enter the loop body, making that address the current address. 5549 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5550 CGF.EmitBlock(BodyBB); 5551 5552 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5553 5554 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5555 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5556 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5557 Address RHSElementCurrent = 5558 Address(RHSElementPHI, 5559 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5560 5561 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5562 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5563 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5564 Address LHSElementCurrent = 5565 Address(LHSElementPHI, 5566 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5567 5568 // Emit copy. 5569 CodeGenFunction::OMPPrivateScope Scope(CGF); 5570 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5571 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5572 Scope.Privatize(); 5573 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5574 Scope.ForceCleanup(); 5575 5576 // Shift the address forward by one element. 5577 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5578 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5579 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5580 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5581 // Check whether we've reached the end. 5582 llvm::Value *Done = 5583 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5584 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5585 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5586 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5587 5588 // Done. 5589 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5590 } 5591 5592 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5593 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5594 /// UDR combiner function. 5595 static void emitReductionCombiner(CodeGenFunction &CGF, 5596 const Expr *ReductionOp) { 5597 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5598 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5599 if (const auto *DRE = 5600 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5601 if (const auto *DRD = 5602 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5603 std::pair<llvm::Function *, llvm::Function *> Reduction = 5604 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5605 RValue Func = RValue::get(Reduction.first); 5606 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5607 CGF.EmitIgnoredExpr(ReductionOp); 5608 return; 5609 } 5610 CGF.EmitIgnoredExpr(ReductionOp); 5611 } 5612 5613 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5614 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5615 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5616 ArrayRef<const Expr *> ReductionOps) { 5617 ASTContext &C = CGM.getContext(); 5618 5619 // void reduction_func(void *LHSArg, void *RHSArg); 5620 FunctionArgList Args; 5621 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5622 ImplicitParamDecl::Other); 5623 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5624 ImplicitParamDecl::Other); 5625 Args.push_back(&LHSArg); 5626 Args.push_back(&RHSArg); 5627 const auto &CGFI = 5628 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5629 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5630 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5631 llvm::GlobalValue::InternalLinkage, Name, 5632 &CGM.getModule()); 5633 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5634 Fn->setDoesNotRecurse(); 5635 CodeGenFunction CGF(CGM); 5636 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5637 5638 // Dst = (void*[n])(LHSArg); 5639 // Src = (void*[n])(RHSArg); 5640 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5641 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5642 ArgsType), CGF.getPointerAlign()); 5643 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5644 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5645 ArgsType), CGF.getPointerAlign()); 5646 5647 // ... 5648 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5649 // ... 5650 CodeGenFunction::OMPPrivateScope Scope(CGF); 5651 auto IPriv = Privates.begin(); 5652 unsigned Idx = 0; 5653 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5654 const auto *RHSVar = 5655 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5656 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5657 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5658 }); 5659 const auto *LHSVar = 5660 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5661 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5662 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5663 }); 5664 QualType PrivTy = (*IPriv)->getType(); 5665 if (PrivTy->isVariablyModifiedType()) { 5666 // Get array size and emit VLA type. 5667 ++Idx; 5668 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5669 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5670 const VariableArrayType *VLA = 5671 CGF.getContext().getAsVariableArrayType(PrivTy); 5672 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5673 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5674 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5675 CGF.EmitVariablyModifiedType(PrivTy); 5676 } 5677 } 5678 Scope.Privatize(); 5679 IPriv = Privates.begin(); 5680 auto ILHS = LHSExprs.begin(); 5681 auto IRHS = RHSExprs.begin(); 5682 for (const Expr *E : ReductionOps) { 5683 if ((*IPriv)->getType()->isArrayType()) { 5684 // Emit reduction for array section. 5685 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5686 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5687 EmitOMPAggregateReduction( 5688 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5689 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5690 emitReductionCombiner(CGF, E); 5691 }); 5692 } else { 5693 // Emit reduction for array subscript or single variable. 5694 emitReductionCombiner(CGF, E); 5695 } 5696 ++IPriv; 5697 ++ILHS; 5698 ++IRHS; 5699 } 5700 Scope.ForceCleanup(); 5701 CGF.FinishFunction(); 5702 return Fn; 5703 } 5704 5705 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5706 const Expr *ReductionOp, 5707 const Expr *PrivateRef, 5708 const DeclRefExpr *LHS, 5709 const DeclRefExpr *RHS) { 5710 if (PrivateRef->getType()->isArrayType()) { 5711 // Emit reduction for array section. 5712 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5713 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5714 EmitOMPAggregateReduction( 5715 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5716 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5717 emitReductionCombiner(CGF, ReductionOp); 5718 }); 5719 } else { 5720 // Emit reduction for array subscript or single variable. 5721 emitReductionCombiner(CGF, ReductionOp); 5722 } 5723 } 5724 5725 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5726 ArrayRef<const Expr *> Privates, 5727 ArrayRef<const Expr *> LHSExprs, 5728 ArrayRef<const Expr *> RHSExprs, 5729 ArrayRef<const Expr *> ReductionOps, 5730 ReductionOptionsTy Options) { 5731 if (!CGF.HaveInsertPoint()) 5732 return; 5733 5734 bool WithNowait = Options.WithNowait; 5735 bool SimpleReduction = Options.SimpleReduction; 5736 5737 // Next code should be emitted for reduction: 5738 // 5739 // static kmp_critical_name lock = { 0 }; 5740 // 5741 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5742 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5743 // ... 5744 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5745 // *(Type<n>-1*)rhs[<n>-1]); 5746 // } 5747 // 5748 // ... 5749 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5750 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5751 // RedList, reduce_func, &<lock>)) { 5752 // case 1: 5753 // ... 5754 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5755 // ... 5756 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5757 // break; 5758 // case 2: 5759 // ... 5760 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5761 // ... 5762 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5763 // break; 5764 // default:; 5765 // } 5766 // 5767 // if SimpleReduction is true, only the next code is generated: 5768 // ... 5769 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5770 // ... 5771 5772 ASTContext &C = CGM.getContext(); 5773 5774 if (SimpleReduction) { 5775 CodeGenFunction::RunCleanupsScope Scope(CGF); 5776 auto IPriv = Privates.begin(); 5777 auto ILHS = LHSExprs.begin(); 5778 auto IRHS = RHSExprs.begin(); 5779 for (const Expr *E : ReductionOps) { 5780 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5781 cast<DeclRefExpr>(*IRHS)); 5782 ++IPriv; 5783 ++ILHS; 5784 ++IRHS; 5785 } 5786 return; 5787 } 5788 5789 // 1. Build a list of reduction variables. 5790 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5791 auto Size = RHSExprs.size(); 5792 for (const Expr *E : Privates) { 5793 if (E->getType()->isVariablyModifiedType()) 5794 // Reserve place for array size. 5795 ++Size; 5796 } 5797 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5798 QualType ReductionArrayTy = 5799 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5800 /*IndexTypeQuals=*/0); 5801 Address ReductionList = 5802 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5803 auto IPriv = Privates.begin(); 5804 unsigned Idx = 0; 5805 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5806 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5807 CGF.Builder.CreateStore( 5808 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5809 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5810 Elem); 5811 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5812 // Store array size. 5813 ++Idx; 5814 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5815 llvm::Value *Size = CGF.Builder.CreateIntCast( 5816 CGF.getVLASize( 5817 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5818 .NumElts, 5819 CGF.SizeTy, /*isSigned=*/false); 5820 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5821 Elem); 5822 } 5823 } 5824 5825 // 2. Emit reduce_func(). 5826 llvm::Function *ReductionFn = emitReductionFunction( 5827 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5828 LHSExprs, RHSExprs, ReductionOps); 5829 5830 // 3. Create static kmp_critical_name lock = { 0 }; 5831 std::string Name = getName({"reduction"}); 5832 llvm::Value *Lock = getCriticalRegionLock(Name); 5833 5834 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5835 // RedList, reduce_func, &<lock>); 5836 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5837 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5838 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5839 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5840 ReductionList.getPointer(), CGF.VoidPtrTy); 5841 llvm::Value *Args[] = { 5842 IdentTLoc, // ident_t *<loc> 5843 ThreadId, // i32 <gtid> 5844 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5845 ReductionArrayTySize, // size_type sizeof(RedList) 5846 RL, // void *RedList 5847 ReductionFn, // void (*) (void *, void *) <reduce_func> 5848 Lock // kmp_critical_name *&<lock> 5849 }; 5850 llvm::Value *Res = CGF.EmitRuntimeCall( 5851 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5852 : OMPRTL__kmpc_reduce), 5853 Args); 5854 5855 // 5. Build switch(res) 5856 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5857 llvm::SwitchInst *SwInst = 5858 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5859 5860 // 6. Build case 1: 5861 // ... 5862 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5863 // ... 5864 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5865 // break; 5866 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5867 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5868 CGF.EmitBlock(Case1BB); 5869 5870 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5871 llvm::Value *EndArgs[] = { 5872 IdentTLoc, // ident_t *<loc> 5873 ThreadId, // i32 <gtid> 5874 Lock // kmp_critical_name *&<lock> 5875 }; 5876 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5877 CodeGenFunction &CGF, PrePostActionTy &Action) { 5878 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5879 auto IPriv = Privates.begin(); 5880 auto ILHS = LHSExprs.begin(); 5881 auto IRHS = RHSExprs.begin(); 5882 for (const Expr *E : ReductionOps) { 5883 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5884 cast<DeclRefExpr>(*IRHS)); 5885 ++IPriv; 5886 ++ILHS; 5887 ++IRHS; 5888 } 5889 }; 5890 RegionCodeGenTy RCG(CodeGen); 5891 CommonActionTy Action( 5892 nullptr, llvm::None, 5893 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5894 : OMPRTL__kmpc_end_reduce), 5895 EndArgs); 5896 RCG.setAction(Action); 5897 RCG(CGF); 5898 5899 CGF.EmitBranch(DefaultBB); 5900 5901 // 7. Build case 2: 5902 // ... 5903 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5904 // ... 5905 // break; 5906 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5907 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5908 CGF.EmitBlock(Case2BB); 5909 5910 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5911 CodeGenFunction &CGF, PrePostActionTy &Action) { 5912 auto ILHS = LHSExprs.begin(); 5913 auto IRHS = RHSExprs.begin(); 5914 auto IPriv = Privates.begin(); 5915 for (const Expr *E : ReductionOps) { 5916 const Expr *XExpr = nullptr; 5917 const Expr *EExpr = nullptr; 5918 const Expr *UpExpr = nullptr; 5919 BinaryOperatorKind BO = BO_Comma; 5920 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5921 if (BO->getOpcode() == BO_Assign) { 5922 XExpr = BO->getLHS(); 5923 UpExpr = BO->getRHS(); 5924 } 5925 } 5926 // Try to emit update expression as a simple atomic. 5927 const Expr *RHSExpr = UpExpr; 5928 if (RHSExpr) { 5929 // Analyze RHS part of the whole expression. 5930 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5931 RHSExpr->IgnoreParenImpCasts())) { 5932 // If this is a conditional operator, analyze its condition for 5933 // min/max reduction operator. 5934 RHSExpr = ACO->getCond(); 5935 } 5936 if (const auto *BORHS = 5937 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5938 EExpr = BORHS->getRHS(); 5939 BO = BORHS->getOpcode(); 5940 } 5941 } 5942 if (XExpr) { 5943 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5944 auto &&AtomicRedGen = [BO, VD, 5945 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5946 const Expr *EExpr, const Expr *UpExpr) { 5947 LValue X = CGF.EmitLValue(XExpr); 5948 RValue E; 5949 if (EExpr) 5950 E = CGF.EmitAnyExpr(EExpr); 5951 CGF.EmitOMPAtomicSimpleUpdateExpr( 5952 X, E, BO, /*IsXLHSInRHSPart=*/true, 5953 llvm::AtomicOrdering::Monotonic, Loc, 5954 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5955 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5956 PrivateScope.addPrivate( 5957 VD, [&CGF, VD, XRValue, Loc]() { 5958 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5959 CGF.emitOMPSimpleStore( 5960 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5961 VD->getType().getNonReferenceType(), Loc); 5962 return LHSTemp; 5963 }); 5964 (void)PrivateScope.Privatize(); 5965 return CGF.EmitAnyExpr(UpExpr); 5966 }); 5967 }; 5968 if ((*IPriv)->getType()->isArrayType()) { 5969 // Emit atomic reduction for array section. 5970 const auto *RHSVar = 5971 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5972 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5973 AtomicRedGen, XExpr, EExpr, UpExpr); 5974 } else { 5975 // Emit atomic reduction for array subscript or single variable. 5976 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5977 } 5978 } else { 5979 // Emit as a critical region. 5980 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5981 const Expr *, const Expr *) { 5982 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5983 std::string Name = RT.getName({"atomic_reduction"}); 5984 RT.emitCriticalRegion( 5985 CGF, Name, 5986 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5987 Action.Enter(CGF); 5988 emitReductionCombiner(CGF, E); 5989 }, 5990 Loc); 5991 }; 5992 if ((*IPriv)->getType()->isArrayType()) { 5993 const auto *LHSVar = 5994 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5995 const auto *RHSVar = 5996 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5997 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5998 CritRedGen); 5999 } else { 6000 CritRedGen(CGF, nullptr, nullptr, nullptr); 6001 } 6002 } 6003 ++ILHS; 6004 ++IRHS; 6005 ++IPriv; 6006 } 6007 }; 6008 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 6009 if (!WithNowait) { 6010 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 6011 llvm::Value *EndArgs[] = { 6012 IdentTLoc, // ident_t *<loc> 6013 ThreadId, // i32 <gtid> 6014 Lock // kmp_critical_name *&<lock> 6015 }; 6016 CommonActionTy Action(nullptr, llvm::None, 6017 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 6018 EndArgs); 6019 AtomicRCG.setAction(Action); 6020 AtomicRCG(CGF); 6021 } else { 6022 AtomicRCG(CGF); 6023 } 6024 6025 CGF.EmitBranch(DefaultBB); 6026 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 6027 } 6028 6029 /// Generates unique name for artificial threadprivate variables. 6030 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 6031 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 6032 const Expr *Ref) { 6033 SmallString<256> Buffer; 6034 llvm::raw_svector_ostream Out(Buffer); 6035 const clang::DeclRefExpr *DE; 6036 const VarDecl *D = ::getBaseDecl(Ref, DE); 6037 if (!D) 6038 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 6039 D = D->getCanonicalDecl(); 6040 std::string Name = CGM.getOpenMPRuntime().getName( 6041 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 6042 Out << Prefix << Name << "_" 6043 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 6044 return Out.str(); 6045 } 6046 6047 /// Emits reduction initializer function: 6048 /// \code 6049 /// void @.red_init(void* %arg) { 6050 /// %0 = bitcast void* %arg to <type>* 6051 /// store <type> <init>, <type>* %0 6052 /// ret void 6053 /// } 6054 /// \endcode 6055 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6056 SourceLocation Loc, 6057 ReductionCodeGen &RCG, unsigned N) { 6058 ASTContext &C = CGM.getContext(); 6059 FunctionArgList Args; 6060 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6061 ImplicitParamDecl::Other); 6062 Args.emplace_back(&Param); 6063 const auto &FnInfo = 6064 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6065 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6066 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6067 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6068 Name, &CGM.getModule()); 6069 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6070 Fn->setDoesNotRecurse(); 6071 CodeGenFunction CGF(CGM); 6072 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6073 Address PrivateAddr = CGF.EmitLoadOfPointer( 6074 CGF.GetAddrOfLocalVar(&Param), 6075 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6076 llvm::Value *Size = nullptr; 6077 // If the size of the reduction item is non-constant, load it from global 6078 // threadprivate variable. 6079 if (RCG.getSizes(N).second) { 6080 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6081 CGF, CGM.getContext().getSizeType(), 6082 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6083 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6084 CGM.getContext().getSizeType(), Loc); 6085 } 6086 RCG.emitAggregateType(CGF, N, Size); 6087 LValue SharedLVal; 6088 // If initializer uses initializer from declare reduction construct, emit a 6089 // pointer to the address of the original reduction item (reuired by reduction 6090 // initializer) 6091 if (RCG.usesReductionInitializer(N)) { 6092 Address SharedAddr = 6093 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6094 CGF, CGM.getContext().VoidPtrTy, 6095 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6096 SharedAddr = CGF.EmitLoadOfPointer( 6097 SharedAddr, 6098 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6099 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6100 } else { 6101 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6102 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6103 CGM.getContext().VoidPtrTy); 6104 } 6105 // Emit the initializer: 6106 // %0 = bitcast void* %arg to <type>* 6107 // store <type> <init>, <type>* %0 6108 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6109 [](CodeGenFunction &) { return false; }); 6110 CGF.FinishFunction(); 6111 return Fn; 6112 } 6113 6114 /// Emits reduction combiner function: 6115 /// \code 6116 /// void @.red_comb(void* %arg0, void* %arg1) { 6117 /// %lhs = bitcast void* %arg0 to <type>* 6118 /// %rhs = bitcast void* %arg1 to <type>* 6119 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6120 /// store <type> %2, <type>* %lhs 6121 /// ret void 6122 /// } 6123 /// \endcode 6124 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6125 SourceLocation Loc, 6126 ReductionCodeGen &RCG, unsigned N, 6127 const Expr *ReductionOp, 6128 const Expr *LHS, const Expr *RHS, 6129 const Expr *PrivateRef) { 6130 ASTContext &C = CGM.getContext(); 6131 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6132 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6133 FunctionArgList Args; 6134 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6135 C.VoidPtrTy, ImplicitParamDecl::Other); 6136 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6137 ImplicitParamDecl::Other); 6138 Args.emplace_back(&ParamInOut); 6139 Args.emplace_back(&ParamIn); 6140 const auto &FnInfo = 6141 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6142 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6143 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6144 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6145 Name, &CGM.getModule()); 6146 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6147 Fn->setDoesNotRecurse(); 6148 CodeGenFunction CGF(CGM); 6149 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6150 llvm::Value *Size = nullptr; 6151 // If the size of the reduction item is non-constant, load it from global 6152 // threadprivate variable. 6153 if (RCG.getSizes(N).second) { 6154 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6155 CGF, CGM.getContext().getSizeType(), 6156 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6157 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6158 CGM.getContext().getSizeType(), Loc); 6159 } 6160 RCG.emitAggregateType(CGF, N, Size); 6161 // Remap lhs and rhs variables to the addresses of the function arguments. 6162 // %lhs = bitcast void* %arg0 to <type>* 6163 // %rhs = bitcast void* %arg1 to <type>* 6164 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6165 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6166 // Pull out the pointer to the variable. 6167 Address PtrAddr = CGF.EmitLoadOfPointer( 6168 CGF.GetAddrOfLocalVar(&ParamInOut), 6169 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6170 return CGF.Builder.CreateElementBitCast( 6171 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6172 }); 6173 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6174 // Pull out the pointer to the variable. 6175 Address PtrAddr = CGF.EmitLoadOfPointer( 6176 CGF.GetAddrOfLocalVar(&ParamIn), 6177 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6178 return CGF.Builder.CreateElementBitCast( 6179 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6180 }); 6181 PrivateScope.Privatize(); 6182 // Emit the combiner body: 6183 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6184 // store <type> %2, <type>* %lhs 6185 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6186 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6187 cast<DeclRefExpr>(RHS)); 6188 CGF.FinishFunction(); 6189 return Fn; 6190 } 6191 6192 /// Emits reduction finalizer function: 6193 /// \code 6194 /// void @.red_fini(void* %arg) { 6195 /// %0 = bitcast void* %arg to <type>* 6196 /// <destroy>(<type>* %0) 6197 /// ret void 6198 /// } 6199 /// \endcode 6200 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6201 SourceLocation Loc, 6202 ReductionCodeGen &RCG, unsigned N) { 6203 if (!RCG.needCleanups(N)) 6204 return nullptr; 6205 ASTContext &C = CGM.getContext(); 6206 FunctionArgList Args; 6207 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6208 ImplicitParamDecl::Other); 6209 Args.emplace_back(&Param); 6210 const auto &FnInfo = 6211 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6212 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6213 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6214 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6215 Name, &CGM.getModule()); 6216 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6217 Fn->setDoesNotRecurse(); 6218 CodeGenFunction CGF(CGM); 6219 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6220 Address PrivateAddr = CGF.EmitLoadOfPointer( 6221 CGF.GetAddrOfLocalVar(&Param), 6222 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6223 llvm::Value *Size = nullptr; 6224 // If the size of the reduction item is non-constant, load it from global 6225 // threadprivate variable. 6226 if (RCG.getSizes(N).second) { 6227 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6228 CGF, CGM.getContext().getSizeType(), 6229 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6230 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6231 CGM.getContext().getSizeType(), Loc); 6232 } 6233 RCG.emitAggregateType(CGF, N, Size); 6234 // Emit the finalizer body: 6235 // <destroy>(<type>* %0) 6236 RCG.emitCleanups(CGF, N, PrivateAddr); 6237 CGF.FinishFunction(Loc); 6238 return Fn; 6239 } 6240 6241 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6242 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6243 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6244 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6245 return nullptr; 6246 6247 // Build typedef struct: 6248 // kmp_task_red_input { 6249 // void *reduce_shar; // shared reduction item 6250 // size_t reduce_size; // size of data item 6251 // void *reduce_init; // data initialization routine 6252 // void *reduce_fini; // data finalization routine 6253 // void *reduce_comb; // data combiner routine 6254 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6255 // } kmp_task_red_input_t; 6256 ASTContext &C = CGM.getContext(); 6257 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6258 RD->startDefinition(); 6259 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6260 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6261 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6262 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6263 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6264 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6265 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6266 RD->completeDefinition(); 6267 QualType RDType = C.getRecordType(RD); 6268 unsigned Size = Data.ReductionVars.size(); 6269 llvm::APInt ArraySize(/*numBits=*/64, Size); 6270 QualType ArrayRDType = C.getConstantArrayType( 6271 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6272 // kmp_task_red_input_t .rd_input.[Size]; 6273 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6274 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6275 Data.ReductionOps); 6276 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6277 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6278 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6279 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6280 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6281 TaskRedInput.getPointer(), Idxs, 6282 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6283 ".rd_input.gep."); 6284 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6285 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6286 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6287 RCG.emitSharedLValue(CGF, Cnt); 6288 llvm::Value *CastedShared = 6289 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6290 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6291 RCG.emitAggregateType(CGF, Cnt); 6292 llvm::Value *SizeValInChars; 6293 llvm::Value *SizeVal; 6294 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6295 // We use delayed creation/initialization for VLAs, array sections and 6296 // custom reduction initializations. It is required because runtime does not 6297 // provide the way to pass the sizes of VLAs/array sections to 6298 // initializer/combiner/finalizer functions and does not pass the pointer to 6299 // original reduction item to the initializer. Instead threadprivate global 6300 // variables are used to store these values and use them in the functions. 6301 bool DelayedCreation = !!SizeVal; 6302 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6303 /*isSigned=*/false); 6304 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6305 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6306 // ElemLVal.reduce_init = init; 6307 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6308 llvm::Value *InitAddr = 6309 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6310 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6311 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6312 // ElemLVal.reduce_fini = fini; 6313 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6314 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6315 llvm::Value *FiniAddr = Fini 6316 ? CGF.EmitCastToVoidPtr(Fini) 6317 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6318 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6319 // ElemLVal.reduce_comb = comb; 6320 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6321 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6322 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6323 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6324 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6325 // ElemLVal.flags = 0; 6326 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6327 if (DelayedCreation) { 6328 CGF.EmitStoreOfScalar( 6329 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6330 FlagsLVal); 6331 } else 6332 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6333 FlagsLVal.getType()); 6334 } 6335 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6336 // *data); 6337 llvm::Value *Args[] = { 6338 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6339 /*isSigned=*/true), 6340 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6341 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6342 CGM.VoidPtrTy)}; 6343 return CGF.EmitRuntimeCall( 6344 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6345 } 6346 6347 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6348 SourceLocation Loc, 6349 ReductionCodeGen &RCG, 6350 unsigned N) { 6351 auto Sizes = RCG.getSizes(N); 6352 // Emit threadprivate global variable if the type is non-constant 6353 // (Sizes.second = nullptr). 6354 if (Sizes.second) { 6355 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6356 /*isSigned=*/false); 6357 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6358 CGF, CGM.getContext().getSizeType(), 6359 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6360 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6361 } 6362 // Store address of the original reduction item if custom initializer is used. 6363 if (RCG.usesReductionInitializer(N)) { 6364 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6365 CGF, CGM.getContext().VoidPtrTy, 6366 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6367 CGF.Builder.CreateStore( 6368 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6369 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy), 6370 SharedAddr, /*IsVolatile=*/false); 6371 } 6372 } 6373 6374 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6375 SourceLocation Loc, 6376 llvm::Value *ReductionsPtr, 6377 LValue SharedLVal) { 6378 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6379 // *d); 6380 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6381 CGM.IntTy, 6382 /*isSigned=*/true), 6383 ReductionsPtr, 6384 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6385 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6386 return Address( 6387 CGF.EmitRuntimeCall( 6388 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6389 SharedLVal.getAlignment()); 6390 } 6391 6392 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6393 SourceLocation Loc) { 6394 if (!CGF.HaveInsertPoint()) 6395 return; 6396 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6397 // global_tid); 6398 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6399 // Ignore return result until untied tasks are supported. 6400 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6401 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6402 Region->emitUntiedSwitch(CGF); 6403 } 6404 6405 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6406 OpenMPDirectiveKind InnerKind, 6407 const RegionCodeGenTy &CodeGen, 6408 bool HasCancel) { 6409 if (!CGF.HaveInsertPoint()) 6410 return; 6411 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6412 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6413 } 6414 6415 namespace { 6416 enum RTCancelKind { 6417 CancelNoreq = 0, 6418 CancelParallel = 1, 6419 CancelLoop = 2, 6420 CancelSections = 3, 6421 CancelTaskgroup = 4 6422 }; 6423 } // anonymous namespace 6424 6425 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6426 RTCancelKind CancelKind = CancelNoreq; 6427 if (CancelRegion == OMPD_parallel) 6428 CancelKind = CancelParallel; 6429 else if (CancelRegion == OMPD_for) 6430 CancelKind = CancelLoop; 6431 else if (CancelRegion == OMPD_sections) 6432 CancelKind = CancelSections; 6433 else { 6434 assert(CancelRegion == OMPD_taskgroup); 6435 CancelKind = CancelTaskgroup; 6436 } 6437 return CancelKind; 6438 } 6439 6440 void CGOpenMPRuntime::emitCancellationPointCall( 6441 CodeGenFunction &CGF, SourceLocation Loc, 6442 OpenMPDirectiveKind CancelRegion) { 6443 if (!CGF.HaveInsertPoint()) 6444 return; 6445 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6446 // global_tid, kmp_int32 cncl_kind); 6447 if (auto *OMPRegionInfo = 6448 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6449 // For 'cancellation point taskgroup', the task region info may not have a 6450 // cancel. This may instead happen in another adjacent task. 6451 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6452 llvm::Value *Args[] = { 6453 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6454 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6455 // Ignore return result until untied tasks are supported. 6456 llvm::Value *Result = CGF.EmitRuntimeCall( 6457 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6458 // if (__kmpc_cancellationpoint()) { 6459 // exit from construct; 6460 // } 6461 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6462 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6463 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6464 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6465 CGF.EmitBlock(ExitBB); 6466 // exit from construct; 6467 CodeGenFunction::JumpDest CancelDest = 6468 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6469 CGF.EmitBranchThroughCleanup(CancelDest); 6470 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6471 } 6472 } 6473 } 6474 6475 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6476 const Expr *IfCond, 6477 OpenMPDirectiveKind CancelRegion) { 6478 if (!CGF.HaveInsertPoint()) 6479 return; 6480 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6481 // kmp_int32 cncl_kind); 6482 if (auto *OMPRegionInfo = 6483 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6484 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6485 PrePostActionTy &) { 6486 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6487 llvm::Value *Args[] = { 6488 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6489 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6490 // Ignore return result until untied tasks are supported. 6491 llvm::Value *Result = CGF.EmitRuntimeCall( 6492 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6493 // if (__kmpc_cancel()) { 6494 // exit from construct; 6495 // } 6496 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6497 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6498 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6499 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6500 CGF.EmitBlock(ExitBB); 6501 // exit from construct; 6502 CodeGenFunction::JumpDest CancelDest = 6503 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6504 CGF.EmitBranchThroughCleanup(CancelDest); 6505 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6506 }; 6507 if (IfCond) { 6508 emitIfClause(CGF, IfCond, ThenGen, 6509 [](CodeGenFunction &, PrePostActionTy &) {}); 6510 } else { 6511 RegionCodeGenTy ThenRCG(ThenGen); 6512 ThenRCG(CGF); 6513 } 6514 } 6515 } 6516 6517 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6518 const OMPExecutableDirective &D, StringRef ParentName, 6519 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6520 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6521 assert(!ParentName.empty() && "Invalid target region parent name!"); 6522 HasEmittedTargetRegion = true; 6523 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6524 IsOffloadEntry, CodeGen); 6525 } 6526 6527 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6528 const OMPExecutableDirective &D, StringRef ParentName, 6529 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6530 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6531 // Create a unique name for the entry function using the source location 6532 // information of the current target region. The name will be something like: 6533 // 6534 // __omp_offloading_DD_FFFF_PP_lBB 6535 // 6536 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6537 // mangled name of the function that encloses the target region and BB is the 6538 // line number of the target region. 6539 6540 unsigned DeviceID; 6541 unsigned FileID; 6542 unsigned Line; 6543 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6544 Line); 6545 SmallString<64> EntryFnName; 6546 { 6547 llvm::raw_svector_ostream OS(EntryFnName); 6548 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6549 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6550 } 6551 6552 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6553 6554 CodeGenFunction CGF(CGM, true); 6555 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6556 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6557 6558 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 6559 6560 // If this target outline function is not an offload entry, we don't need to 6561 // register it. 6562 if (!IsOffloadEntry) 6563 return; 6564 6565 // The target region ID is used by the runtime library to identify the current 6566 // target region, so it only has to be unique and not necessarily point to 6567 // anything. It could be the pointer to the outlined function that implements 6568 // the target region, but we aren't using that so that the compiler doesn't 6569 // need to keep that, and could therefore inline the host function if proven 6570 // worthwhile during optimization. In the other hand, if emitting code for the 6571 // device, the ID has to be the function address so that it can retrieved from 6572 // the offloading entry and launched by the runtime library. We also mark the 6573 // outlined function to have external linkage in case we are emitting code for 6574 // the device, because these functions will be entry points to the device. 6575 6576 if (CGM.getLangOpts().OpenMPIsDevice) { 6577 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6578 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6579 OutlinedFn->setDSOLocal(false); 6580 } else { 6581 std::string Name = getName({EntryFnName, "region_id"}); 6582 OutlinedFnID = new llvm::GlobalVariable( 6583 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6584 llvm::GlobalValue::WeakAnyLinkage, 6585 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6586 } 6587 6588 // Register the information for the entry associated with this target region. 6589 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6590 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6591 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6592 } 6593 6594 /// Checks if the expression is constant or does not have non-trivial function 6595 /// calls. 6596 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6597 // We can skip constant expressions. 6598 // We can skip expressions with trivial calls or simple expressions. 6599 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6600 !E->hasNonTrivialCall(Ctx)) && 6601 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6602 } 6603 6604 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6605 const Stmt *Body) { 6606 const Stmt *Child = Body->IgnoreContainers(); 6607 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6608 Child = nullptr; 6609 for (const Stmt *S : C->body()) { 6610 if (const auto *E = dyn_cast<Expr>(S)) { 6611 if (isTrivial(Ctx, E)) 6612 continue; 6613 } 6614 // Some of the statements can be ignored. 6615 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6616 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6617 continue; 6618 // Analyze declarations. 6619 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6620 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6621 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6622 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6623 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6624 isa<UsingDirectiveDecl>(D) || 6625 isa<OMPDeclareReductionDecl>(D) || 6626 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6627 return true; 6628 const auto *VD = dyn_cast<VarDecl>(D); 6629 if (!VD) 6630 return false; 6631 return VD->isConstexpr() || 6632 ((VD->getType().isTrivialType(Ctx) || 6633 VD->getType()->isReferenceType()) && 6634 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6635 })) 6636 continue; 6637 } 6638 // Found multiple children - cannot get the one child only. 6639 if (Child) 6640 return nullptr; 6641 Child = S; 6642 } 6643 if (Child) 6644 Child = Child->IgnoreContainers(); 6645 } 6646 return Child; 6647 } 6648 6649 /// Emit the number of teams for a target directive. Inspect the num_teams 6650 /// clause associated with a teams construct combined or closely nested 6651 /// with the target directive. 6652 /// 6653 /// Emit a team of size one for directives such as 'target parallel' that 6654 /// have no associated teams construct. 6655 /// 6656 /// Otherwise, return nullptr. 6657 static llvm::Value * 6658 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6659 const OMPExecutableDirective &D) { 6660 assert(!CGF.getLangOpts().OpenMPIsDevice && 6661 "Clauses associated with the teams directive expected to be emitted " 6662 "only for the host!"); 6663 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6664 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6665 "Expected target-based executable directive."); 6666 CGBuilderTy &Bld = CGF.Builder; 6667 switch (DirectiveKind) { 6668 case OMPD_target: { 6669 const auto *CS = D.getInnermostCapturedStmt(); 6670 const auto *Body = 6671 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6672 const Stmt *ChildStmt = 6673 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6674 if (const auto *NestedDir = 6675 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6676 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6677 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6678 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6679 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6680 const Expr *NumTeams = 6681 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6682 llvm::Value *NumTeamsVal = 6683 CGF.EmitScalarExpr(NumTeams, 6684 /*IgnoreResultAssign*/ true); 6685 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6686 /*isSigned=*/true); 6687 } 6688 return Bld.getInt32(0); 6689 } 6690 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6691 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6692 return Bld.getInt32(1); 6693 return Bld.getInt32(0); 6694 } 6695 return nullptr; 6696 } 6697 case OMPD_target_teams: 6698 case OMPD_target_teams_distribute: 6699 case OMPD_target_teams_distribute_simd: 6700 case OMPD_target_teams_distribute_parallel_for: 6701 case OMPD_target_teams_distribute_parallel_for_simd: { 6702 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6703 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6704 const Expr *NumTeams = 6705 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6706 llvm::Value *NumTeamsVal = 6707 CGF.EmitScalarExpr(NumTeams, 6708 /*IgnoreResultAssign*/ true); 6709 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6710 /*isSigned=*/true); 6711 } 6712 return Bld.getInt32(0); 6713 } 6714 case OMPD_target_parallel: 6715 case OMPD_target_parallel_for: 6716 case OMPD_target_parallel_for_simd: 6717 case OMPD_target_simd: 6718 return Bld.getInt32(1); 6719 case OMPD_parallel: 6720 case OMPD_for: 6721 case OMPD_parallel_for: 6722 case OMPD_parallel_master: 6723 case OMPD_parallel_sections: 6724 case OMPD_for_simd: 6725 case OMPD_parallel_for_simd: 6726 case OMPD_cancel: 6727 case OMPD_cancellation_point: 6728 case OMPD_ordered: 6729 case OMPD_threadprivate: 6730 case OMPD_allocate: 6731 case OMPD_task: 6732 case OMPD_simd: 6733 case OMPD_sections: 6734 case OMPD_section: 6735 case OMPD_single: 6736 case OMPD_master: 6737 case OMPD_critical: 6738 case OMPD_taskyield: 6739 case OMPD_barrier: 6740 case OMPD_taskwait: 6741 case OMPD_taskgroup: 6742 case OMPD_atomic: 6743 case OMPD_flush: 6744 case OMPD_teams: 6745 case OMPD_target_data: 6746 case OMPD_target_exit_data: 6747 case OMPD_target_enter_data: 6748 case OMPD_distribute: 6749 case OMPD_distribute_simd: 6750 case OMPD_distribute_parallel_for: 6751 case OMPD_distribute_parallel_for_simd: 6752 case OMPD_teams_distribute: 6753 case OMPD_teams_distribute_simd: 6754 case OMPD_teams_distribute_parallel_for: 6755 case OMPD_teams_distribute_parallel_for_simd: 6756 case OMPD_target_update: 6757 case OMPD_declare_simd: 6758 case OMPD_declare_variant: 6759 case OMPD_declare_target: 6760 case OMPD_end_declare_target: 6761 case OMPD_declare_reduction: 6762 case OMPD_declare_mapper: 6763 case OMPD_taskloop: 6764 case OMPD_taskloop_simd: 6765 case OMPD_master_taskloop: 6766 case OMPD_master_taskloop_simd: 6767 case OMPD_parallel_master_taskloop: 6768 case OMPD_parallel_master_taskloop_simd: 6769 case OMPD_requires: 6770 case OMPD_unknown: 6771 break; 6772 } 6773 llvm_unreachable("Unexpected directive kind."); 6774 } 6775 6776 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6777 llvm::Value *DefaultThreadLimitVal) { 6778 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6779 CGF.getContext(), CS->getCapturedStmt()); 6780 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6781 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6782 llvm::Value *NumThreads = nullptr; 6783 llvm::Value *CondVal = nullptr; 6784 // Handle if clause. If if clause present, the number of threads is 6785 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6786 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6787 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6788 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6789 const OMPIfClause *IfClause = nullptr; 6790 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6791 if (C->getNameModifier() == OMPD_unknown || 6792 C->getNameModifier() == OMPD_parallel) { 6793 IfClause = C; 6794 break; 6795 } 6796 } 6797 if (IfClause) { 6798 const Expr *Cond = IfClause->getCondition(); 6799 bool Result; 6800 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6801 if (!Result) 6802 return CGF.Builder.getInt32(1); 6803 } else { 6804 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6805 if (const auto *PreInit = 6806 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6807 for (const auto *I : PreInit->decls()) { 6808 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6809 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6810 } else { 6811 CodeGenFunction::AutoVarEmission Emission = 6812 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6813 CGF.EmitAutoVarCleanups(Emission); 6814 } 6815 } 6816 } 6817 CondVal = CGF.EvaluateExprAsBool(Cond); 6818 } 6819 } 6820 } 6821 // Check the value of num_threads clause iff if clause was not specified 6822 // or is not evaluated to false. 6823 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6824 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6825 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6826 const auto *NumThreadsClause = 6827 Dir->getSingleClause<OMPNumThreadsClause>(); 6828 CodeGenFunction::LexicalScope Scope( 6829 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6830 if (const auto *PreInit = 6831 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6832 for (const auto *I : PreInit->decls()) { 6833 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6834 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6835 } else { 6836 CodeGenFunction::AutoVarEmission Emission = 6837 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6838 CGF.EmitAutoVarCleanups(Emission); 6839 } 6840 } 6841 } 6842 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6843 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6844 /*isSigned=*/false); 6845 if (DefaultThreadLimitVal) 6846 NumThreads = CGF.Builder.CreateSelect( 6847 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6848 DefaultThreadLimitVal, NumThreads); 6849 } else { 6850 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6851 : CGF.Builder.getInt32(0); 6852 } 6853 // Process condition of the if clause. 6854 if (CondVal) { 6855 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6856 CGF.Builder.getInt32(1)); 6857 } 6858 return NumThreads; 6859 } 6860 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6861 return CGF.Builder.getInt32(1); 6862 return DefaultThreadLimitVal; 6863 } 6864 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6865 : CGF.Builder.getInt32(0); 6866 } 6867 6868 /// Emit the number of threads for a target directive. Inspect the 6869 /// thread_limit clause associated with a teams construct combined or closely 6870 /// nested with the target directive. 6871 /// 6872 /// Emit the num_threads clause for directives such as 'target parallel' that 6873 /// have no associated teams construct. 6874 /// 6875 /// Otherwise, return nullptr. 6876 static llvm::Value * 6877 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6878 const OMPExecutableDirective &D) { 6879 assert(!CGF.getLangOpts().OpenMPIsDevice && 6880 "Clauses associated with the teams directive expected to be emitted " 6881 "only for the host!"); 6882 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6883 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6884 "Expected target-based executable directive."); 6885 CGBuilderTy &Bld = CGF.Builder; 6886 llvm::Value *ThreadLimitVal = nullptr; 6887 llvm::Value *NumThreadsVal = nullptr; 6888 switch (DirectiveKind) { 6889 case OMPD_target: { 6890 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6891 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6892 return NumThreads; 6893 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6894 CGF.getContext(), CS->getCapturedStmt()); 6895 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6896 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6897 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6898 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6899 const auto *ThreadLimitClause = 6900 Dir->getSingleClause<OMPThreadLimitClause>(); 6901 CodeGenFunction::LexicalScope Scope( 6902 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6903 if (const auto *PreInit = 6904 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6905 for (const auto *I : PreInit->decls()) { 6906 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6907 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6908 } else { 6909 CodeGenFunction::AutoVarEmission Emission = 6910 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6911 CGF.EmitAutoVarCleanups(Emission); 6912 } 6913 } 6914 } 6915 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6916 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6917 ThreadLimitVal = 6918 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6919 } 6920 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6921 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6922 CS = Dir->getInnermostCapturedStmt(); 6923 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6924 CGF.getContext(), CS->getCapturedStmt()); 6925 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6926 } 6927 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6928 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6929 CS = Dir->getInnermostCapturedStmt(); 6930 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6931 return NumThreads; 6932 } 6933 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6934 return Bld.getInt32(1); 6935 } 6936 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6937 } 6938 case OMPD_target_teams: { 6939 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6940 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6941 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6942 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6943 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6944 ThreadLimitVal = 6945 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6946 } 6947 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6948 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6949 return NumThreads; 6950 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6951 CGF.getContext(), CS->getCapturedStmt()); 6952 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6953 if (Dir->getDirectiveKind() == OMPD_distribute) { 6954 CS = Dir->getInnermostCapturedStmt(); 6955 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6956 return NumThreads; 6957 } 6958 } 6959 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6960 } 6961 case OMPD_target_teams_distribute: 6962 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6963 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6964 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6965 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6966 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6967 ThreadLimitVal = 6968 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6969 } 6970 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6971 case OMPD_target_parallel: 6972 case OMPD_target_parallel_for: 6973 case OMPD_target_parallel_for_simd: 6974 case OMPD_target_teams_distribute_parallel_for: 6975 case OMPD_target_teams_distribute_parallel_for_simd: { 6976 llvm::Value *CondVal = nullptr; 6977 // Handle if clause. If if clause present, the number of threads is 6978 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6979 if (D.hasClausesOfKind<OMPIfClause>()) { 6980 const OMPIfClause *IfClause = nullptr; 6981 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6982 if (C->getNameModifier() == OMPD_unknown || 6983 C->getNameModifier() == OMPD_parallel) { 6984 IfClause = C; 6985 break; 6986 } 6987 } 6988 if (IfClause) { 6989 const Expr *Cond = IfClause->getCondition(); 6990 bool Result; 6991 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6992 if (!Result) 6993 return Bld.getInt32(1); 6994 } else { 6995 CodeGenFunction::RunCleanupsScope Scope(CGF); 6996 CondVal = CGF.EvaluateExprAsBool(Cond); 6997 } 6998 } 6999 } 7000 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7001 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7002 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7003 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7004 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7005 ThreadLimitVal = 7006 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7007 } 7008 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7009 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7010 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7011 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7012 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7013 NumThreadsVal = 7014 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7015 ThreadLimitVal = ThreadLimitVal 7016 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7017 ThreadLimitVal), 7018 NumThreadsVal, ThreadLimitVal) 7019 : NumThreadsVal; 7020 } 7021 if (!ThreadLimitVal) 7022 ThreadLimitVal = Bld.getInt32(0); 7023 if (CondVal) 7024 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7025 return ThreadLimitVal; 7026 } 7027 case OMPD_target_teams_distribute_simd: 7028 case OMPD_target_simd: 7029 return Bld.getInt32(1); 7030 case OMPD_parallel: 7031 case OMPD_for: 7032 case OMPD_parallel_for: 7033 case OMPD_parallel_master: 7034 case OMPD_parallel_sections: 7035 case OMPD_for_simd: 7036 case OMPD_parallel_for_simd: 7037 case OMPD_cancel: 7038 case OMPD_cancellation_point: 7039 case OMPD_ordered: 7040 case OMPD_threadprivate: 7041 case OMPD_allocate: 7042 case OMPD_task: 7043 case OMPD_simd: 7044 case OMPD_sections: 7045 case OMPD_section: 7046 case OMPD_single: 7047 case OMPD_master: 7048 case OMPD_critical: 7049 case OMPD_taskyield: 7050 case OMPD_barrier: 7051 case OMPD_taskwait: 7052 case OMPD_taskgroup: 7053 case OMPD_atomic: 7054 case OMPD_flush: 7055 case OMPD_teams: 7056 case OMPD_target_data: 7057 case OMPD_target_exit_data: 7058 case OMPD_target_enter_data: 7059 case OMPD_distribute: 7060 case OMPD_distribute_simd: 7061 case OMPD_distribute_parallel_for: 7062 case OMPD_distribute_parallel_for_simd: 7063 case OMPD_teams_distribute: 7064 case OMPD_teams_distribute_simd: 7065 case OMPD_teams_distribute_parallel_for: 7066 case OMPD_teams_distribute_parallel_for_simd: 7067 case OMPD_target_update: 7068 case OMPD_declare_simd: 7069 case OMPD_declare_variant: 7070 case OMPD_declare_target: 7071 case OMPD_end_declare_target: 7072 case OMPD_declare_reduction: 7073 case OMPD_declare_mapper: 7074 case OMPD_taskloop: 7075 case OMPD_taskloop_simd: 7076 case OMPD_master_taskloop: 7077 case OMPD_master_taskloop_simd: 7078 case OMPD_parallel_master_taskloop: 7079 case OMPD_parallel_master_taskloop_simd: 7080 case OMPD_requires: 7081 case OMPD_unknown: 7082 break; 7083 } 7084 llvm_unreachable("Unsupported directive kind."); 7085 } 7086 7087 namespace { 7088 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7089 7090 // Utility to handle information from clauses associated with a given 7091 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7092 // It provides a convenient interface to obtain the information and generate 7093 // code for that information. 7094 class MappableExprsHandler { 7095 public: 7096 /// Values for bit flags used to specify the mapping type for 7097 /// offloading. 7098 enum OpenMPOffloadMappingFlags : uint64_t { 7099 /// No flags 7100 OMP_MAP_NONE = 0x0, 7101 /// Allocate memory on the device and move data from host to device. 7102 OMP_MAP_TO = 0x01, 7103 /// Allocate memory on the device and move data from device to host. 7104 OMP_MAP_FROM = 0x02, 7105 /// Always perform the requested mapping action on the element, even 7106 /// if it was already mapped before. 7107 OMP_MAP_ALWAYS = 0x04, 7108 /// Delete the element from the device environment, ignoring the 7109 /// current reference count associated with the element. 7110 OMP_MAP_DELETE = 0x08, 7111 /// The element being mapped is a pointer-pointee pair; both the 7112 /// pointer and the pointee should be mapped. 7113 OMP_MAP_PTR_AND_OBJ = 0x10, 7114 /// This flags signals that the base address of an entry should be 7115 /// passed to the target kernel as an argument. 7116 OMP_MAP_TARGET_PARAM = 0x20, 7117 /// Signal that the runtime library has to return the device pointer 7118 /// in the current position for the data being mapped. Used when we have the 7119 /// use_device_ptr clause. 7120 OMP_MAP_RETURN_PARAM = 0x40, 7121 /// This flag signals that the reference being passed is a pointer to 7122 /// private data. 7123 OMP_MAP_PRIVATE = 0x80, 7124 /// Pass the element to the device by value. 7125 OMP_MAP_LITERAL = 0x100, 7126 /// Implicit map 7127 OMP_MAP_IMPLICIT = 0x200, 7128 /// Close is a hint to the runtime to allocate memory close to 7129 /// the target device. 7130 OMP_MAP_CLOSE = 0x400, 7131 /// The 16 MSBs of the flags indicate whether the entry is member of some 7132 /// struct/class. 7133 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7134 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7135 }; 7136 7137 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7138 static unsigned getFlagMemberOffset() { 7139 unsigned Offset = 0; 7140 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7141 Remain = Remain >> 1) 7142 Offset++; 7143 return Offset; 7144 } 7145 7146 /// Class that associates information with a base pointer to be passed to the 7147 /// runtime library. 7148 class BasePointerInfo { 7149 /// The base pointer. 7150 llvm::Value *Ptr = nullptr; 7151 /// The base declaration that refers to this device pointer, or null if 7152 /// there is none. 7153 const ValueDecl *DevPtrDecl = nullptr; 7154 7155 public: 7156 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7157 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7158 llvm::Value *operator*() const { return Ptr; } 7159 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7160 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7161 }; 7162 7163 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7164 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7165 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7166 7167 /// Map between a struct and the its lowest & highest elements which have been 7168 /// mapped. 7169 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7170 /// HE(FieldIndex, Pointer)} 7171 struct StructRangeInfoTy { 7172 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7173 0, Address::invalid()}; 7174 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7175 0, Address::invalid()}; 7176 Address Base = Address::invalid(); 7177 }; 7178 7179 private: 7180 /// Kind that defines how a device pointer has to be returned. 7181 struct MapInfo { 7182 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7183 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7184 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7185 bool ReturnDevicePointer = false; 7186 bool IsImplicit = false; 7187 7188 MapInfo() = default; 7189 MapInfo( 7190 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7191 OpenMPMapClauseKind MapType, 7192 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7193 bool ReturnDevicePointer, bool IsImplicit) 7194 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7195 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7196 }; 7197 7198 /// If use_device_ptr is used on a pointer which is a struct member and there 7199 /// is no map information about it, then emission of that entry is deferred 7200 /// until the whole struct has been processed. 7201 struct DeferredDevicePtrEntryTy { 7202 const Expr *IE = nullptr; 7203 const ValueDecl *VD = nullptr; 7204 7205 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7206 : IE(IE), VD(VD) {} 7207 }; 7208 7209 /// The target directive from where the mappable clauses were extracted. It 7210 /// is either a executable directive or a user-defined mapper directive. 7211 llvm::PointerUnion<const OMPExecutableDirective *, 7212 const OMPDeclareMapperDecl *> 7213 CurDir; 7214 7215 /// Function the directive is being generated for. 7216 CodeGenFunction &CGF; 7217 7218 /// Set of all first private variables in the current directive. 7219 /// bool data is set to true if the variable is implicitly marked as 7220 /// firstprivate, false otherwise. 7221 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7222 7223 /// Map between device pointer declarations and their expression components. 7224 /// The key value for declarations in 'this' is null. 7225 llvm::DenseMap< 7226 const ValueDecl *, 7227 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7228 DevPointersMap; 7229 7230 llvm::Value *getExprTypeSize(const Expr *E) const { 7231 QualType ExprTy = E->getType().getCanonicalType(); 7232 7233 // Reference types are ignored for mapping purposes. 7234 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7235 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7236 7237 // Given that an array section is considered a built-in type, we need to 7238 // do the calculation based on the length of the section instead of relying 7239 // on CGF.getTypeSize(E->getType()). 7240 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7241 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7242 OAE->getBase()->IgnoreParenImpCasts()) 7243 .getCanonicalType(); 7244 7245 // If there is no length associated with the expression and lower bound is 7246 // not specified too, that means we are using the whole length of the 7247 // base. 7248 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7249 !OAE->getLowerBound()) 7250 return CGF.getTypeSize(BaseTy); 7251 7252 llvm::Value *ElemSize; 7253 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7254 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7255 } else { 7256 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7257 assert(ATy && "Expecting array type if not a pointer type."); 7258 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7259 } 7260 7261 // If we don't have a length at this point, that is because we have an 7262 // array section with a single element. 7263 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7264 return ElemSize; 7265 7266 if (const Expr *LenExpr = OAE->getLength()) { 7267 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7268 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7269 CGF.getContext().getSizeType(), 7270 LenExpr->getExprLoc()); 7271 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7272 } 7273 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7274 OAE->getLowerBound() && "expected array_section[lb:]."); 7275 // Size = sizetype - lb * elemtype; 7276 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7277 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7278 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7279 CGF.getContext().getSizeType(), 7280 OAE->getLowerBound()->getExprLoc()); 7281 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7282 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7283 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7284 LengthVal = CGF.Builder.CreateSelect( 7285 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7286 return LengthVal; 7287 } 7288 return CGF.getTypeSize(ExprTy); 7289 } 7290 7291 /// Return the corresponding bits for a given map clause modifier. Add 7292 /// a flag marking the map as a pointer if requested. Add a flag marking the 7293 /// map as the first one of a series of maps that relate to the same map 7294 /// expression. 7295 OpenMPOffloadMappingFlags getMapTypeBits( 7296 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7297 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7298 OpenMPOffloadMappingFlags Bits = 7299 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7300 switch (MapType) { 7301 case OMPC_MAP_alloc: 7302 case OMPC_MAP_release: 7303 // alloc and release is the default behavior in the runtime library, i.e. 7304 // if we don't pass any bits alloc/release that is what the runtime is 7305 // going to do. Therefore, we don't need to signal anything for these two 7306 // type modifiers. 7307 break; 7308 case OMPC_MAP_to: 7309 Bits |= OMP_MAP_TO; 7310 break; 7311 case OMPC_MAP_from: 7312 Bits |= OMP_MAP_FROM; 7313 break; 7314 case OMPC_MAP_tofrom: 7315 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7316 break; 7317 case OMPC_MAP_delete: 7318 Bits |= OMP_MAP_DELETE; 7319 break; 7320 case OMPC_MAP_unknown: 7321 llvm_unreachable("Unexpected map type!"); 7322 } 7323 if (AddPtrFlag) 7324 Bits |= OMP_MAP_PTR_AND_OBJ; 7325 if (AddIsTargetParamFlag) 7326 Bits |= OMP_MAP_TARGET_PARAM; 7327 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7328 != MapModifiers.end()) 7329 Bits |= OMP_MAP_ALWAYS; 7330 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7331 != MapModifiers.end()) 7332 Bits |= OMP_MAP_CLOSE; 7333 return Bits; 7334 } 7335 7336 /// Return true if the provided expression is a final array section. A 7337 /// final array section, is one whose length can't be proved to be one. 7338 bool isFinalArraySectionExpression(const Expr *E) const { 7339 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7340 7341 // It is not an array section and therefore not a unity-size one. 7342 if (!OASE) 7343 return false; 7344 7345 // An array section with no colon always refer to a single element. 7346 if (OASE->getColonLoc().isInvalid()) 7347 return false; 7348 7349 const Expr *Length = OASE->getLength(); 7350 7351 // If we don't have a length we have to check if the array has size 1 7352 // for this dimension. Also, we should always expect a length if the 7353 // base type is pointer. 7354 if (!Length) { 7355 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7356 OASE->getBase()->IgnoreParenImpCasts()) 7357 .getCanonicalType(); 7358 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7359 return ATy->getSize().getSExtValue() != 1; 7360 // If we don't have a constant dimension length, we have to consider 7361 // the current section as having any size, so it is not necessarily 7362 // unitary. If it happen to be unity size, that's user fault. 7363 return true; 7364 } 7365 7366 // Check if the length evaluates to 1. 7367 Expr::EvalResult Result; 7368 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7369 return true; // Can have more that size 1. 7370 7371 llvm::APSInt ConstLength = Result.Val.getInt(); 7372 return ConstLength.getSExtValue() != 1; 7373 } 7374 7375 /// Generate the base pointers, section pointers, sizes and map type 7376 /// bits for the provided map type, map modifier, and expression components. 7377 /// \a IsFirstComponent should be set to true if the provided set of 7378 /// components is the first associated with a capture. 7379 void generateInfoForComponentList( 7380 OpenMPMapClauseKind MapType, 7381 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7382 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7383 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7384 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7385 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7386 bool IsImplicit, 7387 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7388 OverlappedElements = llvm::None) const { 7389 // The following summarizes what has to be generated for each map and the 7390 // types below. The generated information is expressed in this order: 7391 // base pointer, section pointer, size, flags 7392 // (to add to the ones that come from the map type and modifier). 7393 // 7394 // double d; 7395 // int i[100]; 7396 // float *p; 7397 // 7398 // struct S1 { 7399 // int i; 7400 // float f[50]; 7401 // } 7402 // struct S2 { 7403 // int i; 7404 // float f[50]; 7405 // S1 s; 7406 // double *p; 7407 // struct S2 *ps; 7408 // } 7409 // S2 s; 7410 // S2 *ps; 7411 // 7412 // map(d) 7413 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7414 // 7415 // map(i) 7416 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7417 // 7418 // map(i[1:23]) 7419 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7420 // 7421 // map(p) 7422 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7423 // 7424 // map(p[1:24]) 7425 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7426 // 7427 // map(s) 7428 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7429 // 7430 // map(s.i) 7431 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7432 // 7433 // map(s.s.f) 7434 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7435 // 7436 // map(s.p) 7437 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7438 // 7439 // map(to: s.p[:22]) 7440 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7441 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7442 // &(s.p), &(s.p[0]), 22*sizeof(double), 7443 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7444 // (*) alloc space for struct members, only this is a target parameter 7445 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7446 // optimizes this entry out, same in the examples below) 7447 // (***) map the pointee (map: to) 7448 // 7449 // map(s.ps) 7450 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7451 // 7452 // map(from: s.ps->s.i) 7453 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7454 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7455 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7456 // 7457 // map(to: s.ps->ps) 7458 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7459 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7460 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7461 // 7462 // map(s.ps->ps->ps) 7463 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7464 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7465 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7466 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7467 // 7468 // map(to: s.ps->ps->s.f[:22]) 7469 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7470 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7471 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7472 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7473 // 7474 // map(ps) 7475 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7476 // 7477 // map(ps->i) 7478 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7479 // 7480 // map(ps->s.f) 7481 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7482 // 7483 // map(from: ps->p) 7484 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7485 // 7486 // map(to: ps->p[:22]) 7487 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7488 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7489 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7490 // 7491 // map(ps->ps) 7492 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7493 // 7494 // map(from: ps->ps->s.i) 7495 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7496 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7497 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7498 // 7499 // map(from: ps->ps->ps) 7500 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7501 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7502 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7503 // 7504 // map(ps->ps->ps->ps) 7505 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7506 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7507 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7508 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7509 // 7510 // map(to: ps->ps->ps->s.f[:22]) 7511 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7512 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7513 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7514 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7515 // 7516 // map(to: s.f[:22]) map(from: s.p[:33]) 7517 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7518 // sizeof(double*) (**), TARGET_PARAM 7519 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7520 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7521 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7522 // (*) allocate contiguous space needed to fit all mapped members even if 7523 // we allocate space for members not mapped (in this example, 7524 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7525 // them as well because they fall between &s.f[0] and &s.p) 7526 // 7527 // map(from: s.f[:22]) map(to: ps->p[:33]) 7528 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7529 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7530 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7531 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7532 // (*) the struct this entry pertains to is the 2nd element in the list of 7533 // arguments, hence MEMBER_OF(2) 7534 // 7535 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7536 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7537 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7538 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7539 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7540 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7541 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7542 // (*) the struct this entry pertains to is the 4th element in the list 7543 // of arguments, hence MEMBER_OF(4) 7544 7545 // Track if the map information being generated is the first for a capture. 7546 bool IsCaptureFirstInfo = IsFirstComponentList; 7547 // When the variable is on a declare target link or in a to clause with 7548 // unified memory, a reference is needed to hold the host/device address 7549 // of the variable. 7550 bool RequiresReference = false; 7551 7552 // Scan the components from the base to the complete expression. 7553 auto CI = Components.rbegin(); 7554 auto CE = Components.rend(); 7555 auto I = CI; 7556 7557 // Track if the map information being generated is the first for a list of 7558 // components. 7559 bool IsExpressionFirstInfo = true; 7560 Address BP = Address::invalid(); 7561 const Expr *AssocExpr = I->getAssociatedExpression(); 7562 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7563 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7564 7565 if (isa<MemberExpr>(AssocExpr)) { 7566 // The base is the 'this' pointer. The content of the pointer is going 7567 // to be the base of the field being mapped. 7568 BP = CGF.LoadCXXThisAddress(); 7569 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7570 (OASE && 7571 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7572 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7573 } else { 7574 // The base is the reference to the variable. 7575 // BP = &Var. 7576 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7577 if (const auto *VD = 7578 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7579 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7580 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7581 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7582 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7583 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7584 RequiresReference = true; 7585 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7586 } 7587 } 7588 } 7589 7590 // If the variable is a pointer and is being dereferenced (i.e. is not 7591 // the last component), the base has to be the pointer itself, not its 7592 // reference. References are ignored for mapping purposes. 7593 QualType Ty = 7594 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7595 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7596 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7597 7598 // We do not need to generate individual map information for the 7599 // pointer, it can be associated with the combined storage. 7600 ++I; 7601 } 7602 } 7603 7604 // Track whether a component of the list should be marked as MEMBER_OF some 7605 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7606 // in a component list should be marked as MEMBER_OF, all subsequent entries 7607 // do not belong to the base struct. E.g. 7608 // struct S2 s; 7609 // s.ps->ps->ps->f[:] 7610 // (1) (2) (3) (4) 7611 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7612 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7613 // is the pointee of ps(2) which is not member of struct s, so it should not 7614 // be marked as such (it is still PTR_AND_OBJ). 7615 // The variable is initialized to false so that PTR_AND_OBJ entries which 7616 // are not struct members are not considered (e.g. array of pointers to 7617 // data). 7618 bool ShouldBeMemberOf = false; 7619 7620 // Variable keeping track of whether or not we have encountered a component 7621 // in the component list which is a member expression. Useful when we have a 7622 // pointer or a final array section, in which case it is the previous 7623 // component in the list which tells us whether we have a member expression. 7624 // E.g. X.f[:] 7625 // While processing the final array section "[:]" it is "f" which tells us 7626 // whether we are dealing with a member of a declared struct. 7627 const MemberExpr *EncounteredME = nullptr; 7628 7629 for (; I != CE; ++I) { 7630 // If the current component is member of a struct (parent struct) mark it. 7631 if (!EncounteredME) { 7632 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7633 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7634 // as MEMBER_OF the parent struct. 7635 if (EncounteredME) 7636 ShouldBeMemberOf = true; 7637 } 7638 7639 auto Next = std::next(I); 7640 7641 // We need to generate the addresses and sizes if this is the last 7642 // component, if the component is a pointer or if it is an array section 7643 // whose length can't be proved to be one. If this is a pointer, it 7644 // becomes the base address for the following components. 7645 7646 // A final array section, is one whose length can't be proved to be one. 7647 bool IsFinalArraySection = 7648 isFinalArraySectionExpression(I->getAssociatedExpression()); 7649 7650 // Get information on whether the element is a pointer. Have to do a 7651 // special treatment for array sections given that they are built-in 7652 // types. 7653 const auto *OASE = 7654 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7655 bool IsPointer = 7656 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7657 .getCanonicalType() 7658 ->isAnyPointerType()) || 7659 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7660 7661 if (Next == CE || IsPointer || IsFinalArraySection) { 7662 // If this is not the last component, we expect the pointer to be 7663 // associated with an array expression or member expression. 7664 assert((Next == CE || 7665 isa<MemberExpr>(Next->getAssociatedExpression()) || 7666 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7667 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7668 "Unexpected expression"); 7669 7670 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7671 .getAddress(CGF); 7672 7673 // If this component is a pointer inside the base struct then we don't 7674 // need to create any entry for it - it will be combined with the object 7675 // it is pointing to into a single PTR_AND_OBJ entry. 7676 bool IsMemberPointer = 7677 IsPointer && EncounteredME && 7678 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7679 EncounteredME); 7680 if (!OverlappedElements.empty()) { 7681 // Handle base element with the info for overlapped elements. 7682 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7683 assert(Next == CE && 7684 "Expected last element for the overlapped elements."); 7685 assert(!IsPointer && 7686 "Unexpected base element with the pointer type."); 7687 // Mark the whole struct as the struct that requires allocation on the 7688 // device. 7689 PartialStruct.LowestElem = {0, LB}; 7690 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7691 I->getAssociatedExpression()->getType()); 7692 Address HB = CGF.Builder.CreateConstGEP( 7693 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7694 CGF.VoidPtrTy), 7695 TypeSize.getQuantity() - 1); 7696 PartialStruct.HighestElem = { 7697 std::numeric_limits<decltype( 7698 PartialStruct.HighestElem.first)>::max(), 7699 HB}; 7700 PartialStruct.Base = BP; 7701 // Emit data for non-overlapped data. 7702 OpenMPOffloadMappingFlags Flags = 7703 OMP_MAP_MEMBER_OF | 7704 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7705 /*AddPtrFlag=*/false, 7706 /*AddIsTargetParamFlag=*/false); 7707 LB = BP; 7708 llvm::Value *Size = nullptr; 7709 // Do bitcopy of all non-overlapped structure elements. 7710 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7711 Component : OverlappedElements) { 7712 Address ComponentLB = Address::invalid(); 7713 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7714 Component) { 7715 if (MC.getAssociatedDeclaration()) { 7716 ComponentLB = 7717 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7718 .getAddress(CGF); 7719 Size = CGF.Builder.CreatePtrDiff( 7720 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7721 CGF.EmitCastToVoidPtr(LB.getPointer())); 7722 break; 7723 } 7724 } 7725 BasePointers.push_back(BP.getPointer()); 7726 Pointers.push_back(LB.getPointer()); 7727 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7728 /*isSigned=*/true)); 7729 Types.push_back(Flags); 7730 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7731 } 7732 BasePointers.push_back(BP.getPointer()); 7733 Pointers.push_back(LB.getPointer()); 7734 Size = CGF.Builder.CreatePtrDiff( 7735 CGF.EmitCastToVoidPtr( 7736 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7737 CGF.EmitCastToVoidPtr(LB.getPointer())); 7738 Sizes.push_back( 7739 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7740 Types.push_back(Flags); 7741 break; 7742 } 7743 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7744 if (!IsMemberPointer) { 7745 BasePointers.push_back(BP.getPointer()); 7746 Pointers.push_back(LB.getPointer()); 7747 Sizes.push_back( 7748 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7749 7750 // We need to add a pointer flag for each map that comes from the 7751 // same expression except for the first one. We also need to signal 7752 // this map is the first one that relates with the current capture 7753 // (there is a set of entries for each capture). 7754 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7755 MapType, MapModifiers, IsImplicit, 7756 !IsExpressionFirstInfo || RequiresReference, 7757 IsCaptureFirstInfo && !RequiresReference); 7758 7759 if (!IsExpressionFirstInfo) { 7760 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7761 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7762 if (IsPointer) 7763 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7764 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7765 7766 if (ShouldBeMemberOf) { 7767 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7768 // should be later updated with the correct value of MEMBER_OF. 7769 Flags |= OMP_MAP_MEMBER_OF; 7770 // From now on, all subsequent PTR_AND_OBJ entries should not be 7771 // marked as MEMBER_OF. 7772 ShouldBeMemberOf = false; 7773 } 7774 } 7775 7776 Types.push_back(Flags); 7777 } 7778 7779 // If we have encountered a member expression so far, keep track of the 7780 // mapped member. If the parent is "*this", then the value declaration 7781 // is nullptr. 7782 if (EncounteredME) { 7783 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7784 unsigned FieldIndex = FD->getFieldIndex(); 7785 7786 // Update info about the lowest and highest elements for this struct 7787 if (!PartialStruct.Base.isValid()) { 7788 PartialStruct.LowestElem = {FieldIndex, LB}; 7789 PartialStruct.HighestElem = {FieldIndex, LB}; 7790 PartialStruct.Base = BP; 7791 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7792 PartialStruct.LowestElem = {FieldIndex, LB}; 7793 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7794 PartialStruct.HighestElem = {FieldIndex, LB}; 7795 } 7796 } 7797 7798 // If we have a final array section, we are done with this expression. 7799 if (IsFinalArraySection) 7800 break; 7801 7802 // The pointer becomes the base for the next element. 7803 if (Next != CE) 7804 BP = LB; 7805 7806 IsExpressionFirstInfo = false; 7807 IsCaptureFirstInfo = false; 7808 } 7809 } 7810 } 7811 7812 /// Return the adjusted map modifiers if the declaration a capture refers to 7813 /// appears in a first-private clause. This is expected to be used only with 7814 /// directives that start with 'target'. 7815 MappableExprsHandler::OpenMPOffloadMappingFlags 7816 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7817 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7818 7819 // A first private variable captured by reference will use only the 7820 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7821 // declaration is known as first-private in this handler. 7822 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7823 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7824 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7825 return MappableExprsHandler::OMP_MAP_ALWAYS | 7826 MappableExprsHandler::OMP_MAP_TO; 7827 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7828 return MappableExprsHandler::OMP_MAP_TO | 7829 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7830 return MappableExprsHandler::OMP_MAP_PRIVATE | 7831 MappableExprsHandler::OMP_MAP_TO; 7832 } 7833 return MappableExprsHandler::OMP_MAP_TO | 7834 MappableExprsHandler::OMP_MAP_FROM; 7835 } 7836 7837 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7838 // Rotate by getFlagMemberOffset() bits. 7839 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7840 << getFlagMemberOffset()); 7841 } 7842 7843 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7844 OpenMPOffloadMappingFlags MemberOfFlag) { 7845 // If the entry is PTR_AND_OBJ but has not been marked with the special 7846 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7847 // marked as MEMBER_OF. 7848 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7849 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7850 return; 7851 7852 // Reset the placeholder value to prepare the flag for the assignment of the 7853 // proper MEMBER_OF value. 7854 Flags &= ~OMP_MAP_MEMBER_OF; 7855 Flags |= MemberOfFlag; 7856 } 7857 7858 void getPlainLayout(const CXXRecordDecl *RD, 7859 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7860 bool AsBase) const { 7861 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7862 7863 llvm::StructType *St = 7864 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7865 7866 unsigned NumElements = St->getNumElements(); 7867 llvm::SmallVector< 7868 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7869 RecordLayout(NumElements); 7870 7871 // Fill bases. 7872 for (const auto &I : RD->bases()) { 7873 if (I.isVirtual()) 7874 continue; 7875 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7876 // Ignore empty bases. 7877 if (Base->isEmpty() || CGF.getContext() 7878 .getASTRecordLayout(Base) 7879 .getNonVirtualSize() 7880 .isZero()) 7881 continue; 7882 7883 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7884 RecordLayout[FieldIndex] = Base; 7885 } 7886 // Fill in virtual bases. 7887 for (const auto &I : RD->vbases()) { 7888 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7889 // Ignore empty bases. 7890 if (Base->isEmpty()) 7891 continue; 7892 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7893 if (RecordLayout[FieldIndex]) 7894 continue; 7895 RecordLayout[FieldIndex] = Base; 7896 } 7897 // Fill in all the fields. 7898 assert(!RD->isUnion() && "Unexpected union."); 7899 for (const auto *Field : RD->fields()) { 7900 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7901 // will fill in later.) 7902 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7903 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7904 RecordLayout[FieldIndex] = Field; 7905 } 7906 } 7907 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7908 &Data : RecordLayout) { 7909 if (Data.isNull()) 7910 continue; 7911 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7912 getPlainLayout(Base, Layout, /*AsBase=*/true); 7913 else 7914 Layout.push_back(Data.get<const FieldDecl *>()); 7915 } 7916 } 7917 7918 public: 7919 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7920 : CurDir(&Dir), CGF(CGF) { 7921 // Extract firstprivate clause information. 7922 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7923 for (const auto *D : C->varlists()) 7924 FirstPrivateDecls.try_emplace( 7925 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7926 // Extract device pointer clause information. 7927 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7928 for (auto L : C->component_lists()) 7929 DevPointersMap[L.first].push_back(L.second); 7930 } 7931 7932 /// Constructor for the declare mapper directive. 7933 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7934 : CurDir(&Dir), CGF(CGF) {} 7935 7936 /// Generate code for the combined entry if we have a partially mapped struct 7937 /// and take care of the mapping flags of the arguments corresponding to 7938 /// individual struct members. 7939 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7940 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7941 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7942 const StructRangeInfoTy &PartialStruct) const { 7943 // Base is the base of the struct 7944 BasePointers.push_back(PartialStruct.Base.getPointer()); 7945 // Pointer is the address of the lowest element 7946 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7947 Pointers.push_back(LB); 7948 // Size is (addr of {highest+1} element) - (addr of lowest element) 7949 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7950 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7951 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7952 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7953 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7954 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7955 /*isSigned=*/false); 7956 Sizes.push_back(Size); 7957 // Map type is always TARGET_PARAM 7958 Types.push_back(OMP_MAP_TARGET_PARAM); 7959 // Remove TARGET_PARAM flag from the first element 7960 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7961 7962 // All other current entries will be MEMBER_OF the combined entry 7963 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7964 // 0xFFFF in the MEMBER_OF field). 7965 OpenMPOffloadMappingFlags MemberOfFlag = 7966 getMemberOfFlag(BasePointers.size() - 1); 7967 for (auto &M : CurTypes) 7968 setCorrectMemberOfFlag(M, MemberOfFlag); 7969 } 7970 7971 /// Generate all the base pointers, section pointers, sizes and map 7972 /// types for the extracted mappable expressions. Also, for each item that 7973 /// relates with a device pointer, a pair of the relevant declaration and 7974 /// index where it occurs is appended to the device pointers info array. 7975 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7976 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7977 MapFlagsArrayTy &Types) const { 7978 // We have to process the component lists that relate with the same 7979 // declaration in a single chunk so that we can generate the map flags 7980 // correctly. Therefore, we organize all lists in a map. 7981 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7982 7983 // Helper function to fill the information map for the different supported 7984 // clauses. 7985 auto &&InfoGen = [&Info]( 7986 const ValueDecl *D, 7987 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7988 OpenMPMapClauseKind MapType, 7989 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7990 bool ReturnDevicePointer, bool IsImplicit) { 7991 const ValueDecl *VD = 7992 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7993 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7994 IsImplicit); 7995 }; 7996 7997 assert(CurDir.is<const OMPExecutableDirective *>() && 7998 "Expect a executable directive"); 7999 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8000 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 8001 for (const auto L : C->component_lists()) { 8002 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 8003 /*ReturnDevicePointer=*/false, C->isImplicit()); 8004 } 8005 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 8006 for (const auto L : C->component_lists()) { 8007 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 8008 /*ReturnDevicePointer=*/false, C->isImplicit()); 8009 } 8010 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 8011 for (const auto L : C->component_lists()) { 8012 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 8013 /*ReturnDevicePointer=*/false, C->isImplicit()); 8014 } 8015 8016 // Look at the use_device_ptr clause information and mark the existing map 8017 // entries as such. If there is no map information for an entry in the 8018 // use_device_ptr list, we create one with map type 'alloc' and zero size 8019 // section. It is the user fault if that was not mapped before. If there is 8020 // no map information and the pointer is a struct member, then we defer the 8021 // emission of that entry until the whole struct has been processed. 8022 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8023 DeferredInfo; 8024 8025 for (const auto *C : 8026 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8027 for (const auto L : C->component_lists()) { 8028 assert(!L.second.empty() && "Not expecting empty list of components!"); 8029 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 8030 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8031 const Expr *IE = L.second.back().getAssociatedExpression(); 8032 // If the first component is a member expression, we have to look into 8033 // 'this', which maps to null in the map of map information. Otherwise 8034 // look directly for the information. 8035 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8036 8037 // We potentially have map information for this declaration already. 8038 // Look for the first set of components that refer to it. 8039 if (It != Info.end()) { 8040 auto CI = std::find_if( 8041 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 8042 return MI.Components.back().getAssociatedDeclaration() == VD; 8043 }); 8044 // If we found a map entry, signal that the pointer has to be returned 8045 // and move on to the next declaration. 8046 if (CI != It->second.end()) { 8047 CI->ReturnDevicePointer = true; 8048 continue; 8049 } 8050 } 8051 8052 // We didn't find any match in our map information - generate a zero 8053 // size array section - if the pointer is a struct member we defer this 8054 // action until the whole struct has been processed. 8055 if (isa<MemberExpr>(IE)) { 8056 // Insert the pointer into Info to be processed by 8057 // generateInfoForComponentList. Because it is a member pointer 8058 // without a pointee, no entry will be generated for it, therefore 8059 // we need to generate one after the whole struct has been processed. 8060 // Nonetheless, generateInfoForComponentList must be called to take 8061 // the pointer into account for the calculation of the range of the 8062 // partial struct. 8063 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8064 /*ReturnDevicePointer=*/false, C->isImplicit()); 8065 DeferredInfo[nullptr].emplace_back(IE, VD); 8066 } else { 8067 llvm::Value *Ptr = 8068 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8069 BasePointers.emplace_back(Ptr, VD); 8070 Pointers.push_back(Ptr); 8071 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8072 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8073 } 8074 } 8075 } 8076 8077 for (const auto &M : Info) { 8078 // We need to know when we generate information for the first component 8079 // associated with a capture, because the mapping flags depend on it. 8080 bool IsFirstComponentList = true; 8081 8082 // Temporary versions of arrays 8083 MapBaseValuesArrayTy CurBasePointers; 8084 MapValuesArrayTy CurPointers; 8085 MapValuesArrayTy CurSizes; 8086 MapFlagsArrayTy CurTypes; 8087 StructRangeInfoTy PartialStruct; 8088 8089 for (const MapInfo &L : M.second) { 8090 assert(!L.Components.empty() && 8091 "Not expecting declaration with no component lists."); 8092 8093 // Remember the current base pointer index. 8094 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8095 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8096 CurBasePointers, CurPointers, CurSizes, 8097 CurTypes, PartialStruct, 8098 IsFirstComponentList, L.IsImplicit); 8099 8100 // If this entry relates with a device pointer, set the relevant 8101 // declaration and add the 'return pointer' flag. 8102 if (L.ReturnDevicePointer) { 8103 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8104 "Unexpected number of mapped base pointers."); 8105 8106 const ValueDecl *RelevantVD = 8107 L.Components.back().getAssociatedDeclaration(); 8108 assert(RelevantVD && 8109 "No relevant declaration related with device pointer??"); 8110 8111 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8112 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8113 } 8114 IsFirstComponentList = false; 8115 } 8116 8117 // Append any pending zero-length pointers which are struct members and 8118 // used with use_device_ptr. 8119 auto CI = DeferredInfo.find(M.first); 8120 if (CI != DeferredInfo.end()) { 8121 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8122 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8123 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8124 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8125 CurBasePointers.emplace_back(BasePtr, L.VD); 8126 CurPointers.push_back(Ptr); 8127 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8128 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8129 // value MEMBER_OF=FFFF so that the entry is later updated with the 8130 // correct value of MEMBER_OF. 8131 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8132 OMP_MAP_MEMBER_OF); 8133 } 8134 } 8135 8136 // If there is an entry in PartialStruct it means we have a struct with 8137 // individual members mapped. Emit an extra combined entry. 8138 if (PartialStruct.Base.isValid()) 8139 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8140 PartialStruct); 8141 8142 // We need to append the results of this capture to what we already have. 8143 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8144 Pointers.append(CurPointers.begin(), CurPointers.end()); 8145 Sizes.append(CurSizes.begin(), CurSizes.end()); 8146 Types.append(CurTypes.begin(), CurTypes.end()); 8147 } 8148 } 8149 8150 /// Generate all the base pointers, section pointers, sizes and map types for 8151 /// the extracted map clauses of user-defined mapper. 8152 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8153 MapValuesArrayTy &Pointers, 8154 MapValuesArrayTy &Sizes, 8155 MapFlagsArrayTy &Types) const { 8156 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8157 "Expect a declare mapper directive"); 8158 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8159 // We have to process the component lists that relate with the same 8160 // declaration in a single chunk so that we can generate the map flags 8161 // correctly. Therefore, we organize all lists in a map. 8162 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8163 8164 // Helper function to fill the information map for the different supported 8165 // clauses. 8166 auto &&InfoGen = [&Info]( 8167 const ValueDecl *D, 8168 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8169 OpenMPMapClauseKind MapType, 8170 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8171 bool ReturnDevicePointer, bool IsImplicit) { 8172 const ValueDecl *VD = 8173 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8174 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8175 IsImplicit); 8176 }; 8177 8178 for (const auto *C : CurMapperDir->clauselists()) { 8179 const auto *MC = cast<OMPMapClause>(C); 8180 for (const auto L : MC->component_lists()) { 8181 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8182 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8183 } 8184 } 8185 8186 for (const auto &M : Info) { 8187 // We need to know when we generate information for the first component 8188 // associated with a capture, because the mapping flags depend on it. 8189 bool IsFirstComponentList = true; 8190 8191 // Temporary versions of arrays 8192 MapBaseValuesArrayTy CurBasePointers; 8193 MapValuesArrayTy CurPointers; 8194 MapValuesArrayTy CurSizes; 8195 MapFlagsArrayTy CurTypes; 8196 StructRangeInfoTy PartialStruct; 8197 8198 for (const MapInfo &L : M.second) { 8199 assert(!L.Components.empty() && 8200 "Not expecting declaration with no component lists."); 8201 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8202 CurBasePointers, CurPointers, CurSizes, 8203 CurTypes, PartialStruct, 8204 IsFirstComponentList, L.IsImplicit); 8205 IsFirstComponentList = false; 8206 } 8207 8208 // If there is an entry in PartialStruct it means we have a struct with 8209 // individual members mapped. Emit an extra combined entry. 8210 if (PartialStruct.Base.isValid()) 8211 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8212 PartialStruct); 8213 8214 // We need to append the results of this capture to what we already have. 8215 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8216 Pointers.append(CurPointers.begin(), CurPointers.end()); 8217 Sizes.append(CurSizes.begin(), CurSizes.end()); 8218 Types.append(CurTypes.begin(), CurTypes.end()); 8219 } 8220 } 8221 8222 /// Emit capture info for lambdas for variables captured by reference. 8223 void generateInfoForLambdaCaptures( 8224 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8225 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8226 MapFlagsArrayTy &Types, 8227 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8228 const auto *RD = VD->getType() 8229 .getCanonicalType() 8230 .getNonReferenceType() 8231 ->getAsCXXRecordDecl(); 8232 if (!RD || !RD->isLambda()) 8233 return; 8234 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8235 LValue VDLVal = CGF.MakeAddrLValue( 8236 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8237 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8238 FieldDecl *ThisCapture = nullptr; 8239 RD->getCaptureFields(Captures, ThisCapture); 8240 if (ThisCapture) { 8241 LValue ThisLVal = 8242 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8243 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8244 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8245 VDLVal.getPointer(CGF)); 8246 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8247 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8248 Sizes.push_back( 8249 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8250 CGF.Int64Ty, /*isSigned=*/true)); 8251 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8252 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8253 } 8254 for (const LambdaCapture &LC : RD->captures()) { 8255 if (!LC.capturesVariable()) 8256 continue; 8257 const VarDecl *VD = LC.getCapturedVar(); 8258 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8259 continue; 8260 auto It = Captures.find(VD); 8261 assert(It != Captures.end() && "Found lambda capture without field."); 8262 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8263 if (LC.getCaptureKind() == LCK_ByRef) { 8264 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8265 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8266 VDLVal.getPointer(CGF)); 8267 BasePointers.push_back(VarLVal.getPointer(CGF)); 8268 Pointers.push_back(VarLValVal.getPointer(CGF)); 8269 Sizes.push_back(CGF.Builder.CreateIntCast( 8270 CGF.getTypeSize( 8271 VD->getType().getCanonicalType().getNonReferenceType()), 8272 CGF.Int64Ty, /*isSigned=*/true)); 8273 } else { 8274 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8275 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8276 VDLVal.getPointer(CGF)); 8277 BasePointers.push_back(VarLVal.getPointer(CGF)); 8278 Pointers.push_back(VarRVal.getScalarVal()); 8279 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8280 } 8281 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8282 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8283 } 8284 } 8285 8286 /// Set correct indices for lambdas captures. 8287 void adjustMemberOfForLambdaCaptures( 8288 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8289 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8290 MapFlagsArrayTy &Types) const { 8291 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8292 // Set correct member_of idx for all implicit lambda captures. 8293 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8294 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8295 continue; 8296 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8297 assert(BasePtr && "Unable to find base lambda address."); 8298 int TgtIdx = -1; 8299 for (unsigned J = I; J > 0; --J) { 8300 unsigned Idx = J - 1; 8301 if (Pointers[Idx] != BasePtr) 8302 continue; 8303 TgtIdx = Idx; 8304 break; 8305 } 8306 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8307 // All other current entries will be MEMBER_OF the combined entry 8308 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8309 // 0xFFFF in the MEMBER_OF field). 8310 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8311 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8312 } 8313 } 8314 8315 /// Generate the base pointers, section pointers, sizes and map types 8316 /// associated to a given capture. 8317 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8318 llvm::Value *Arg, 8319 MapBaseValuesArrayTy &BasePointers, 8320 MapValuesArrayTy &Pointers, 8321 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8322 StructRangeInfoTy &PartialStruct) const { 8323 assert(!Cap->capturesVariableArrayType() && 8324 "Not expecting to generate map info for a variable array type!"); 8325 8326 // We need to know when we generating information for the first component 8327 const ValueDecl *VD = Cap->capturesThis() 8328 ? nullptr 8329 : Cap->getCapturedVar()->getCanonicalDecl(); 8330 8331 // If this declaration appears in a is_device_ptr clause we just have to 8332 // pass the pointer by value. If it is a reference to a declaration, we just 8333 // pass its value. 8334 if (DevPointersMap.count(VD)) { 8335 BasePointers.emplace_back(Arg, VD); 8336 Pointers.push_back(Arg); 8337 Sizes.push_back( 8338 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8339 CGF.Int64Ty, /*isSigned=*/true)); 8340 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8341 return; 8342 } 8343 8344 using MapData = 8345 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8346 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8347 SmallVector<MapData, 4> DeclComponentLists; 8348 assert(CurDir.is<const OMPExecutableDirective *>() && 8349 "Expect a executable directive"); 8350 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8351 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8352 for (const auto L : C->decl_component_lists(VD)) { 8353 assert(L.first == VD && 8354 "We got information for the wrong declaration??"); 8355 assert(!L.second.empty() && 8356 "Not expecting declaration with no component lists."); 8357 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8358 C->getMapTypeModifiers(), 8359 C->isImplicit()); 8360 } 8361 } 8362 8363 // Find overlapping elements (including the offset from the base element). 8364 llvm::SmallDenseMap< 8365 const MapData *, 8366 llvm::SmallVector< 8367 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8368 4> 8369 OverlappedData; 8370 size_t Count = 0; 8371 for (const MapData &L : DeclComponentLists) { 8372 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8373 OpenMPMapClauseKind MapType; 8374 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8375 bool IsImplicit; 8376 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8377 ++Count; 8378 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8379 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8380 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8381 auto CI = Components.rbegin(); 8382 auto CE = Components.rend(); 8383 auto SI = Components1.rbegin(); 8384 auto SE = Components1.rend(); 8385 for (; CI != CE && SI != SE; ++CI, ++SI) { 8386 if (CI->getAssociatedExpression()->getStmtClass() != 8387 SI->getAssociatedExpression()->getStmtClass()) 8388 break; 8389 // Are we dealing with different variables/fields? 8390 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8391 break; 8392 } 8393 // Found overlapping if, at least for one component, reached the head of 8394 // the components list. 8395 if (CI == CE || SI == SE) { 8396 assert((CI != CE || SI != SE) && 8397 "Unexpected full match of the mapping components."); 8398 const MapData &BaseData = CI == CE ? L : L1; 8399 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8400 SI == SE ? Components : Components1; 8401 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8402 OverlappedElements.getSecond().push_back(SubData); 8403 } 8404 } 8405 } 8406 // Sort the overlapped elements for each item. 8407 llvm::SmallVector<const FieldDecl *, 4> Layout; 8408 if (!OverlappedData.empty()) { 8409 if (const auto *CRD = 8410 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8411 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8412 else { 8413 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8414 Layout.append(RD->field_begin(), RD->field_end()); 8415 } 8416 } 8417 for (auto &Pair : OverlappedData) { 8418 llvm::sort( 8419 Pair.getSecond(), 8420 [&Layout]( 8421 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8422 OMPClauseMappableExprCommon::MappableExprComponentListRef 8423 Second) { 8424 auto CI = First.rbegin(); 8425 auto CE = First.rend(); 8426 auto SI = Second.rbegin(); 8427 auto SE = Second.rend(); 8428 for (; CI != CE && SI != SE; ++CI, ++SI) { 8429 if (CI->getAssociatedExpression()->getStmtClass() != 8430 SI->getAssociatedExpression()->getStmtClass()) 8431 break; 8432 // Are we dealing with different variables/fields? 8433 if (CI->getAssociatedDeclaration() != 8434 SI->getAssociatedDeclaration()) 8435 break; 8436 } 8437 8438 // Lists contain the same elements. 8439 if (CI == CE && SI == SE) 8440 return false; 8441 8442 // List with less elements is less than list with more elements. 8443 if (CI == CE || SI == SE) 8444 return CI == CE; 8445 8446 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8447 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8448 if (FD1->getParent() == FD2->getParent()) 8449 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8450 const auto It = 8451 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8452 return FD == FD1 || FD == FD2; 8453 }); 8454 return *It == FD1; 8455 }); 8456 } 8457 8458 // Associated with a capture, because the mapping flags depend on it. 8459 // Go through all of the elements with the overlapped elements. 8460 for (const auto &Pair : OverlappedData) { 8461 const MapData &L = *Pair.getFirst(); 8462 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8463 OpenMPMapClauseKind MapType; 8464 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8465 bool IsImplicit; 8466 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8467 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8468 OverlappedComponents = Pair.getSecond(); 8469 bool IsFirstComponentList = true; 8470 generateInfoForComponentList(MapType, MapModifiers, Components, 8471 BasePointers, Pointers, Sizes, Types, 8472 PartialStruct, IsFirstComponentList, 8473 IsImplicit, OverlappedComponents); 8474 } 8475 // Go through other elements without overlapped elements. 8476 bool IsFirstComponentList = OverlappedData.empty(); 8477 for (const MapData &L : DeclComponentLists) { 8478 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8479 OpenMPMapClauseKind MapType; 8480 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8481 bool IsImplicit; 8482 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8483 auto It = OverlappedData.find(&L); 8484 if (It == OverlappedData.end()) 8485 generateInfoForComponentList(MapType, MapModifiers, Components, 8486 BasePointers, Pointers, Sizes, Types, 8487 PartialStruct, IsFirstComponentList, 8488 IsImplicit); 8489 IsFirstComponentList = false; 8490 } 8491 } 8492 8493 /// Generate the base pointers, section pointers, sizes and map types 8494 /// associated with the declare target link variables. 8495 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8496 MapValuesArrayTy &Pointers, 8497 MapValuesArrayTy &Sizes, 8498 MapFlagsArrayTy &Types) const { 8499 assert(CurDir.is<const OMPExecutableDirective *>() && 8500 "Expect a executable directive"); 8501 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8502 // Map other list items in the map clause which are not captured variables 8503 // but "declare target link" global variables. 8504 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8505 for (const auto L : C->component_lists()) { 8506 if (!L.first) 8507 continue; 8508 const auto *VD = dyn_cast<VarDecl>(L.first); 8509 if (!VD) 8510 continue; 8511 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8512 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8513 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8514 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8515 continue; 8516 StructRangeInfoTy PartialStruct; 8517 generateInfoForComponentList( 8518 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8519 Pointers, Sizes, Types, PartialStruct, 8520 /*IsFirstComponentList=*/true, C->isImplicit()); 8521 assert(!PartialStruct.Base.isValid() && 8522 "No partial structs for declare target link expected."); 8523 } 8524 } 8525 } 8526 8527 /// Generate the default map information for a given capture \a CI, 8528 /// record field declaration \a RI and captured value \a CV. 8529 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8530 const FieldDecl &RI, llvm::Value *CV, 8531 MapBaseValuesArrayTy &CurBasePointers, 8532 MapValuesArrayTy &CurPointers, 8533 MapValuesArrayTy &CurSizes, 8534 MapFlagsArrayTy &CurMapTypes) const { 8535 bool IsImplicit = true; 8536 // Do the default mapping. 8537 if (CI.capturesThis()) { 8538 CurBasePointers.push_back(CV); 8539 CurPointers.push_back(CV); 8540 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8541 CurSizes.push_back( 8542 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8543 CGF.Int64Ty, /*isSigned=*/true)); 8544 // Default map type. 8545 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8546 } else if (CI.capturesVariableByCopy()) { 8547 CurBasePointers.push_back(CV); 8548 CurPointers.push_back(CV); 8549 if (!RI.getType()->isAnyPointerType()) { 8550 // We have to signal to the runtime captures passed by value that are 8551 // not pointers. 8552 CurMapTypes.push_back(OMP_MAP_LITERAL); 8553 CurSizes.push_back(CGF.Builder.CreateIntCast( 8554 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8555 } else { 8556 // Pointers are implicitly mapped with a zero size and no flags 8557 // (other than first map that is added for all implicit maps). 8558 CurMapTypes.push_back(OMP_MAP_NONE); 8559 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8560 } 8561 const VarDecl *VD = CI.getCapturedVar(); 8562 auto I = FirstPrivateDecls.find(VD); 8563 if (I != FirstPrivateDecls.end()) 8564 IsImplicit = I->getSecond(); 8565 } else { 8566 assert(CI.capturesVariable() && "Expected captured reference."); 8567 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8568 QualType ElementType = PtrTy->getPointeeType(); 8569 CurSizes.push_back(CGF.Builder.CreateIntCast( 8570 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8571 // The default map type for a scalar/complex type is 'to' because by 8572 // default the value doesn't have to be retrieved. For an aggregate 8573 // type, the default is 'tofrom'. 8574 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8575 const VarDecl *VD = CI.getCapturedVar(); 8576 auto I = FirstPrivateDecls.find(VD); 8577 if (I != FirstPrivateDecls.end() && 8578 VD->getType().isConstant(CGF.getContext())) { 8579 llvm::Constant *Addr = 8580 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8581 // Copy the value of the original variable to the new global copy. 8582 CGF.Builder.CreateMemCpy( 8583 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8584 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8585 CurSizes.back(), /*IsVolatile=*/false); 8586 // Use new global variable as the base pointers. 8587 CurBasePointers.push_back(Addr); 8588 CurPointers.push_back(Addr); 8589 } else { 8590 CurBasePointers.push_back(CV); 8591 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8592 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8593 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8594 AlignmentSource::Decl)); 8595 CurPointers.push_back(PtrAddr.getPointer()); 8596 } else { 8597 CurPointers.push_back(CV); 8598 } 8599 } 8600 if (I != FirstPrivateDecls.end()) 8601 IsImplicit = I->getSecond(); 8602 } 8603 // Every default map produces a single argument which is a target parameter. 8604 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8605 8606 // Add flag stating this is an implicit map. 8607 if (IsImplicit) 8608 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8609 } 8610 }; 8611 } // anonymous namespace 8612 8613 /// Emit the arrays used to pass the captures and map information to the 8614 /// offloading runtime library. If there is no map or capture information, 8615 /// return nullptr by reference. 8616 static void 8617 emitOffloadingArrays(CodeGenFunction &CGF, 8618 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8619 MappableExprsHandler::MapValuesArrayTy &Pointers, 8620 MappableExprsHandler::MapValuesArrayTy &Sizes, 8621 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8622 CGOpenMPRuntime::TargetDataInfo &Info) { 8623 CodeGenModule &CGM = CGF.CGM; 8624 ASTContext &Ctx = CGF.getContext(); 8625 8626 // Reset the array information. 8627 Info.clearArrayInfo(); 8628 Info.NumberOfPtrs = BasePointers.size(); 8629 8630 if (Info.NumberOfPtrs) { 8631 // Detect if we have any capture size requiring runtime evaluation of the 8632 // size so that a constant array could be eventually used. 8633 bool hasRuntimeEvaluationCaptureSize = false; 8634 for (llvm::Value *S : Sizes) 8635 if (!isa<llvm::Constant>(S)) { 8636 hasRuntimeEvaluationCaptureSize = true; 8637 break; 8638 } 8639 8640 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8641 QualType PointerArrayType = Ctx.getConstantArrayType( 8642 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8643 /*IndexTypeQuals=*/0); 8644 8645 Info.BasePointersArray = 8646 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8647 Info.PointersArray = 8648 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8649 8650 // If we don't have any VLA types or other types that require runtime 8651 // evaluation, we can use a constant array for the map sizes, otherwise we 8652 // need to fill up the arrays as we do for the pointers. 8653 QualType Int64Ty = 8654 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8655 if (hasRuntimeEvaluationCaptureSize) { 8656 QualType SizeArrayType = Ctx.getConstantArrayType( 8657 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8658 /*IndexTypeQuals=*/0); 8659 Info.SizesArray = 8660 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8661 } else { 8662 // We expect all the sizes to be constant, so we collect them to create 8663 // a constant array. 8664 SmallVector<llvm::Constant *, 16> ConstSizes; 8665 for (llvm::Value *S : Sizes) 8666 ConstSizes.push_back(cast<llvm::Constant>(S)); 8667 8668 auto *SizesArrayInit = llvm::ConstantArray::get( 8669 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8670 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8671 auto *SizesArrayGbl = new llvm::GlobalVariable( 8672 CGM.getModule(), SizesArrayInit->getType(), 8673 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8674 SizesArrayInit, Name); 8675 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8676 Info.SizesArray = SizesArrayGbl; 8677 } 8678 8679 // The map types are always constant so we don't need to generate code to 8680 // fill arrays. Instead, we create an array constant. 8681 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8682 llvm::copy(MapTypes, Mapping.begin()); 8683 llvm::Constant *MapTypesArrayInit = 8684 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8685 std::string MaptypesName = 8686 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8687 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8688 CGM.getModule(), MapTypesArrayInit->getType(), 8689 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8690 MapTypesArrayInit, MaptypesName); 8691 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8692 Info.MapTypesArray = MapTypesArrayGbl; 8693 8694 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8695 llvm::Value *BPVal = *BasePointers[I]; 8696 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8697 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8698 Info.BasePointersArray, 0, I); 8699 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8700 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8701 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8702 CGF.Builder.CreateStore(BPVal, BPAddr); 8703 8704 if (Info.requiresDevicePointerInfo()) 8705 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8706 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8707 8708 llvm::Value *PVal = Pointers[I]; 8709 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8710 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8711 Info.PointersArray, 0, I); 8712 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8713 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8714 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8715 CGF.Builder.CreateStore(PVal, PAddr); 8716 8717 if (hasRuntimeEvaluationCaptureSize) { 8718 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8719 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8720 Info.SizesArray, 8721 /*Idx0=*/0, 8722 /*Idx1=*/I); 8723 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8724 CGF.Builder.CreateStore( 8725 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8726 SAddr); 8727 } 8728 } 8729 } 8730 } 8731 8732 /// Emit the arguments to be passed to the runtime library based on the 8733 /// arrays of pointers, sizes and map types. 8734 static void emitOffloadingArraysArgument( 8735 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8736 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8737 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8738 CodeGenModule &CGM = CGF.CGM; 8739 if (Info.NumberOfPtrs) { 8740 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8741 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8742 Info.BasePointersArray, 8743 /*Idx0=*/0, /*Idx1=*/0); 8744 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8745 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8746 Info.PointersArray, 8747 /*Idx0=*/0, 8748 /*Idx1=*/0); 8749 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8750 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8751 /*Idx0=*/0, /*Idx1=*/0); 8752 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8753 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8754 Info.MapTypesArray, 8755 /*Idx0=*/0, 8756 /*Idx1=*/0); 8757 } else { 8758 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8759 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8760 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8761 MapTypesArrayArg = 8762 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8763 } 8764 } 8765 8766 /// Check for inner distribute directive. 8767 static const OMPExecutableDirective * 8768 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8769 const auto *CS = D.getInnermostCapturedStmt(); 8770 const auto *Body = 8771 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8772 const Stmt *ChildStmt = 8773 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8774 8775 if (const auto *NestedDir = 8776 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8777 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8778 switch (D.getDirectiveKind()) { 8779 case OMPD_target: 8780 if (isOpenMPDistributeDirective(DKind)) 8781 return NestedDir; 8782 if (DKind == OMPD_teams) { 8783 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8784 /*IgnoreCaptured=*/true); 8785 if (!Body) 8786 return nullptr; 8787 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8788 if (const auto *NND = 8789 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8790 DKind = NND->getDirectiveKind(); 8791 if (isOpenMPDistributeDirective(DKind)) 8792 return NND; 8793 } 8794 } 8795 return nullptr; 8796 case OMPD_target_teams: 8797 if (isOpenMPDistributeDirective(DKind)) 8798 return NestedDir; 8799 return nullptr; 8800 case OMPD_target_parallel: 8801 case OMPD_target_simd: 8802 case OMPD_target_parallel_for: 8803 case OMPD_target_parallel_for_simd: 8804 return nullptr; 8805 case OMPD_target_teams_distribute: 8806 case OMPD_target_teams_distribute_simd: 8807 case OMPD_target_teams_distribute_parallel_for: 8808 case OMPD_target_teams_distribute_parallel_for_simd: 8809 case OMPD_parallel: 8810 case OMPD_for: 8811 case OMPD_parallel_for: 8812 case OMPD_parallel_master: 8813 case OMPD_parallel_sections: 8814 case OMPD_for_simd: 8815 case OMPD_parallel_for_simd: 8816 case OMPD_cancel: 8817 case OMPD_cancellation_point: 8818 case OMPD_ordered: 8819 case OMPD_threadprivate: 8820 case OMPD_allocate: 8821 case OMPD_task: 8822 case OMPD_simd: 8823 case OMPD_sections: 8824 case OMPD_section: 8825 case OMPD_single: 8826 case OMPD_master: 8827 case OMPD_critical: 8828 case OMPD_taskyield: 8829 case OMPD_barrier: 8830 case OMPD_taskwait: 8831 case OMPD_taskgroup: 8832 case OMPD_atomic: 8833 case OMPD_flush: 8834 case OMPD_teams: 8835 case OMPD_target_data: 8836 case OMPD_target_exit_data: 8837 case OMPD_target_enter_data: 8838 case OMPD_distribute: 8839 case OMPD_distribute_simd: 8840 case OMPD_distribute_parallel_for: 8841 case OMPD_distribute_parallel_for_simd: 8842 case OMPD_teams_distribute: 8843 case OMPD_teams_distribute_simd: 8844 case OMPD_teams_distribute_parallel_for: 8845 case OMPD_teams_distribute_parallel_for_simd: 8846 case OMPD_target_update: 8847 case OMPD_declare_simd: 8848 case OMPD_declare_variant: 8849 case OMPD_declare_target: 8850 case OMPD_end_declare_target: 8851 case OMPD_declare_reduction: 8852 case OMPD_declare_mapper: 8853 case OMPD_taskloop: 8854 case OMPD_taskloop_simd: 8855 case OMPD_master_taskloop: 8856 case OMPD_master_taskloop_simd: 8857 case OMPD_parallel_master_taskloop: 8858 case OMPD_parallel_master_taskloop_simd: 8859 case OMPD_requires: 8860 case OMPD_unknown: 8861 llvm_unreachable("Unexpected directive."); 8862 } 8863 } 8864 8865 return nullptr; 8866 } 8867 8868 /// Emit the user-defined mapper function. The code generation follows the 8869 /// pattern in the example below. 8870 /// \code 8871 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8872 /// void *base, void *begin, 8873 /// int64_t size, int64_t type) { 8874 /// // Allocate space for an array section first. 8875 /// if (size > 1 && !maptype.IsDelete) 8876 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8877 /// size*sizeof(Ty), clearToFrom(type)); 8878 /// // Map members. 8879 /// for (unsigned i = 0; i < size; i++) { 8880 /// // For each component specified by this mapper: 8881 /// for (auto c : all_components) { 8882 /// if (c.hasMapper()) 8883 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8884 /// c.arg_type); 8885 /// else 8886 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8887 /// c.arg_begin, c.arg_size, c.arg_type); 8888 /// } 8889 /// } 8890 /// // Delete the array section. 8891 /// if (size > 1 && maptype.IsDelete) 8892 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8893 /// size*sizeof(Ty), clearToFrom(type)); 8894 /// } 8895 /// \endcode 8896 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8897 CodeGenFunction *CGF) { 8898 if (UDMMap.count(D) > 0) 8899 return; 8900 ASTContext &C = CGM.getContext(); 8901 QualType Ty = D->getType(); 8902 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8903 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8904 auto *MapperVarDecl = 8905 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8906 SourceLocation Loc = D->getLocation(); 8907 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8908 8909 // Prepare mapper function arguments and attributes. 8910 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8911 C.VoidPtrTy, ImplicitParamDecl::Other); 8912 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8913 ImplicitParamDecl::Other); 8914 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8915 C.VoidPtrTy, ImplicitParamDecl::Other); 8916 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8917 ImplicitParamDecl::Other); 8918 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8919 ImplicitParamDecl::Other); 8920 FunctionArgList Args; 8921 Args.push_back(&HandleArg); 8922 Args.push_back(&BaseArg); 8923 Args.push_back(&BeginArg); 8924 Args.push_back(&SizeArg); 8925 Args.push_back(&TypeArg); 8926 const CGFunctionInfo &FnInfo = 8927 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8928 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8929 SmallString<64> TyStr; 8930 llvm::raw_svector_ostream Out(TyStr); 8931 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8932 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8933 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8934 Name, &CGM.getModule()); 8935 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8936 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8937 // Start the mapper function code generation. 8938 CodeGenFunction MapperCGF(CGM); 8939 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8940 // Compute the starting and end addreses of array elements. 8941 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8942 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8943 C.getPointerType(Int64Ty), Loc); 8944 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8945 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8946 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8947 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8948 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8949 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8950 C.getPointerType(Int64Ty), Loc); 8951 // Prepare common arguments for array initiation and deletion. 8952 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8953 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8954 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8955 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8956 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8957 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8958 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8959 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8960 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8961 8962 // Emit array initiation if this is an array section and \p MapType indicates 8963 // that memory allocation is required. 8964 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8965 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8966 ElementSize, HeadBB, /*IsInit=*/true); 8967 8968 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8969 8970 // Emit the loop header block. 8971 MapperCGF.EmitBlock(HeadBB); 8972 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8973 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8974 // Evaluate whether the initial condition is satisfied. 8975 llvm::Value *IsEmpty = 8976 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8977 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8978 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8979 8980 // Emit the loop body block. 8981 MapperCGF.EmitBlock(BodyBB); 8982 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8983 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8984 PtrPHI->addIncoming(PtrBegin, EntryBB); 8985 Address PtrCurrent = 8986 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8987 .getAlignment() 8988 .alignmentOfArrayElement(ElementSize)); 8989 // Privatize the declared variable of mapper to be the current array element. 8990 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8991 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8992 return MapperCGF 8993 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8994 .getAddress(MapperCGF); 8995 }); 8996 (void)Scope.Privatize(); 8997 8998 // Get map clause information. Fill up the arrays with all mapped variables. 8999 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9000 MappableExprsHandler::MapValuesArrayTy Pointers; 9001 MappableExprsHandler::MapValuesArrayTy Sizes; 9002 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9003 MappableExprsHandler MEHandler(*D, MapperCGF); 9004 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 9005 9006 // Call the runtime API __tgt_mapper_num_components to get the number of 9007 // pre-existing components. 9008 llvm::Value *OffloadingArgs[] = {Handle}; 9009 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9010 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 9011 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9012 PreviousSize, 9013 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9014 9015 // Fill up the runtime mapper handle for all components. 9016 for (unsigned I = 0; I < BasePointers.size(); ++I) { 9017 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9018 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9019 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9020 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9021 llvm::Value *CurSizeArg = Sizes[I]; 9022 9023 // Extract the MEMBER_OF field from the map type. 9024 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9025 MapperCGF.EmitBlock(MemberBB); 9026 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 9027 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9028 OriMapType, 9029 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9030 llvm::BasicBlock *MemberCombineBB = 9031 MapperCGF.createBasicBlock("omp.member.combine"); 9032 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9033 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9034 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9035 // Add the number of pre-existing components to the MEMBER_OF field if it 9036 // is valid. 9037 MapperCGF.EmitBlock(MemberCombineBB); 9038 llvm::Value *CombinedMember = 9039 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9040 // Do nothing if it is not a member of previous components. 9041 MapperCGF.EmitBlock(TypeBB); 9042 llvm::PHINode *MemberMapType = 9043 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9044 MemberMapType->addIncoming(OriMapType, MemberBB); 9045 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9046 9047 // Combine the map type inherited from user-defined mapper with that 9048 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9049 // bits of the \a MapType, which is the input argument of the mapper 9050 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9051 // bits of MemberMapType. 9052 // [OpenMP 5.0], 1.2.6. map-type decay. 9053 // | alloc | to | from | tofrom | release | delete 9054 // ---------------------------------------------------------- 9055 // alloc | alloc | alloc | alloc | alloc | release | delete 9056 // to | alloc | to | alloc | to | release | delete 9057 // from | alloc | alloc | from | from | release | delete 9058 // tofrom | alloc | to | from | tofrom | release | delete 9059 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9060 MapType, 9061 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9062 MappableExprsHandler::OMP_MAP_FROM)); 9063 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9064 llvm::BasicBlock *AllocElseBB = 9065 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9066 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9067 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9068 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9069 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9070 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9071 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9072 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9073 MapperCGF.EmitBlock(AllocBB); 9074 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9075 MemberMapType, 9076 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9077 MappableExprsHandler::OMP_MAP_FROM))); 9078 MapperCGF.Builder.CreateBr(EndBB); 9079 MapperCGF.EmitBlock(AllocElseBB); 9080 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9081 LeftToFrom, 9082 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9083 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9084 // In case of to, clear OMP_MAP_FROM. 9085 MapperCGF.EmitBlock(ToBB); 9086 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9087 MemberMapType, 9088 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9089 MapperCGF.Builder.CreateBr(EndBB); 9090 MapperCGF.EmitBlock(ToElseBB); 9091 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9092 LeftToFrom, 9093 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9094 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9095 // In case of from, clear OMP_MAP_TO. 9096 MapperCGF.EmitBlock(FromBB); 9097 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9098 MemberMapType, 9099 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9100 // In case of tofrom, do nothing. 9101 MapperCGF.EmitBlock(EndBB); 9102 llvm::PHINode *CurMapType = 9103 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9104 CurMapType->addIncoming(AllocMapType, AllocBB); 9105 CurMapType->addIncoming(ToMapType, ToBB); 9106 CurMapType->addIncoming(FromMapType, FromBB); 9107 CurMapType->addIncoming(MemberMapType, ToElseBB); 9108 9109 // TODO: call the corresponding mapper function if a user-defined mapper is 9110 // associated with this map clause. 9111 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9112 // data structure. 9113 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9114 CurSizeArg, CurMapType}; 9115 MapperCGF.EmitRuntimeCall( 9116 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9117 OffloadingArgs); 9118 } 9119 9120 // Update the pointer to point to the next element that needs to be mapped, 9121 // and check whether we have mapped all elements. 9122 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9123 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9124 PtrPHI->addIncoming(PtrNext, BodyBB); 9125 llvm::Value *IsDone = 9126 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9127 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9128 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9129 9130 MapperCGF.EmitBlock(ExitBB); 9131 // Emit array deletion if this is an array section and \p MapType indicates 9132 // that deletion is required. 9133 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9134 ElementSize, DoneBB, /*IsInit=*/false); 9135 9136 // Emit the function exit block. 9137 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9138 MapperCGF.FinishFunction(); 9139 UDMMap.try_emplace(D, Fn); 9140 if (CGF) { 9141 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9142 Decls.second.push_back(D); 9143 } 9144 } 9145 9146 /// Emit the array initialization or deletion portion for user-defined mapper 9147 /// code generation. First, it evaluates whether an array section is mapped and 9148 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9149 /// true, and \a MapType indicates to not delete this array, array 9150 /// initialization code is generated. If \a IsInit is false, and \a MapType 9151 /// indicates to not this array, array deletion code is generated. 9152 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9153 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9154 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9155 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9156 StringRef Prefix = IsInit ? ".init" : ".del"; 9157 9158 // Evaluate if this is an array section. 9159 llvm::BasicBlock *IsDeleteBB = 9160 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete"); 9161 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix); 9162 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9163 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9164 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9165 9166 // Evaluate if we are going to delete this section. 9167 MapperCGF.EmitBlock(IsDeleteBB); 9168 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9169 MapType, 9170 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9171 llvm::Value *DeleteCond; 9172 if (IsInit) { 9173 DeleteCond = MapperCGF.Builder.CreateIsNull( 9174 DeleteBit, "omp.array" + Prefix + ".delete"); 9175 } else { 9176 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9177 DeleteBit, "omp.array" + Prefix + ".delete"); 9178 } 9179 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9180 9181 MapperCGF.EmitBlock(BodyBB); 9182 // Get the array size by multiplying element size and element number (i.e., \p 9183 // Size). 9184 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9185 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9186 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9187 // memory allocation/deletion purpose only. 9188 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9189 MapType, 9190 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9191 MappableExprsHandler::OMP_MAP_FROM))); 9192 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9193 // data structure. 9194 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9195 MapperCGF.EmitRuntimeCall( 9196 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9197 } 9198 9199 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9200 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9201 llvm::Value *DeviceID, 9202 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9203 const OMPLoopDirective &D)> 9204 SizeEmitter) { 9205 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9206 const OMPExecutableDirective *TD = &D; 9207 // Get nested teams distribute kind directive, if any. 9208 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9209 TD = getNestedDistributeDirective(CGM.getContext(), D); 9210 if (!TD) 9211 return; 9212 const auto *LD = cast<OMPLoopDirective>(TD); 9213 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9214 PrePostActionTy &) { 9215 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9216 llvm::Value *Args[] = {DeviceID, NumIterations}; 9217 CGF.EmitRuntimeCall( 9218 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9219 } 9220 }; 9221 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9222 } 9223 9224 void CGOpenMPRuntime::emitTargetCall( 9225 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9226 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9227 const Expr *Device, 9228 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9229 const OMPLoopDirective &D)> 9230 SizeEmitter) { 9231 if (!CGF.HaveInsertPoint()) 9232 return; 9233 9234 assert(OutlinedFn && "Invalid outlined function!"); 9235 9236 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9237 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9238 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9239 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9240 PrePostActionTy &) { 9241 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9242 }; 9243 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9244 9245 CodeGenFunction::OMPTargetDataInfo InputInfo; 9246 llvm::Value *MapTypesArray = nullptr; 9247 // Fill up the pointer arrays and transfer execution to the device. 9248 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9249 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9250 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9251 // On top of the arrays that were filled up, the target offloading call 9252 // takes as arguments the device id as well as the host pointer. The host 9253 // pointer is used by the runtime library to identify the current target 9254 // region, so it only has to be unique and not necessarily point to 9255 // anything. It could be the pointer to the outlined function that 9256 // implements the target region, but we aren't using that so that the 9257 // compiler doesn't need to keep that, and could therefore inline the host 9258 // function if proven worthwhile during optimization. 9259 9260 // From this point on, we need to have an ID of the target region defined. 9261 assert(OutlinedFnID && "Invalid outlined function ID!"); 9262 9263 // Emit device ID if any. 9264 llvm::Value *DeviceID; 9265 if (Device) { 9266 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9267 CGF.Int64Ty, /*isSigned=*/true); 9268 } else { 9269 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9270 } 9271 9272 // Emit the number of elements in the offloading arrays. 9273 llvm::Value *PointerNum = 9274 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9275 9276 // Return value of the runtime offloading call. 9277 llvm::Value *Return; 9278 9279 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9280 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9281 9282 // Emit tripcount for the target loop-based directive. 9283 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9284 9285 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9286 // The target region is an outlined function launched by the runtime 9287 // via calls __tgt_target() or __tgt_target_teams(). 9288 // 9289 // __tgt_target() launches a target region with one team and one thread, 9290 // executing a serial region. This master thread may in turn launch 9291 // more threads within its team upon encountering a parallel region, 9292 // however, no additional teams can be launched on the device. 9293 // 9294 // __tgt_target_teams() launches a target region with one or more teams, 9295 // each with one or more threads. This call is required for target 9296 // constructs such as: 9297 // 'target teams' 9298 // 'target' / 'teams' 9299 // 'target teams distribute parallel for' 9300 // 'target parallel' 9301 // and so on. 9302 // 9303 // Note that on the host and CPU targets, the runtime implementation of 9304 // these calls simply call the outlined function without forking threads. 9305 // The outlined functions themselves have runtime calls to 9306 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9307 // the compiler in emitTeamsCall() and emitParallelCall(). 9308 // 9309 // In contrast, on the NVPTX target, the implementation of 9310 // __tgt_target_teams() launches a GPU kernel with the requested number 9311 // of teams and threads so no additional calls to the runtime are required. 9312 if (NumTeams) { 9313 // If we have NumTeams defined this means that we have an enclosed teams 9314 // region. Therefore we also expect to have NumThreads defined. These two 9315 // values should be defined in the presence of a teams directive, 9316 // regardless of having any clauses associated. If the user is using teams 9317 // but no clauses, these two values will be the default that should be 9318 // passed to the runtime library - a 32-bit integer with the value zero. 9319 assert(NumThreads && "Thread limit expression should be available along " 9320 "with number of teams."); 9321 llvm::Value *OffloadingArgs[] = {DeviceID, 9322 OutlinedFnID, 9323 PointerNum, 9324 InputInfo.BasePointersArray.getPointer(), 9325 InputInfo.PointersArray.getPointer(), 9326 InputInfo.SizesArray.getPointer(), 9327 MapTypesArray, 9328 NumTeams, 9329 NumThreads}; 9330 Return = CGF.EmitRuntimeCall( 9331 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9332 : OMPRTL__tgt_target_teams), 9333 OffloadingArgs); 9334 } else { 9335 llvm::Value *OffloadingArgs[] = {DeviceID, 9336 OutlinedFnID, 9337 PointerNum, 9338 InputInfo.BasePointersArray.getPointer(), 9339 InputInfo.PointersArray.getPointer(), 9340 InputInfo.SizesArray.getPointer(), 9341 MapTypesArray}; 9342 Return = CGF.EmitRuntimeCall( 9343 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9344 : OMPRTL__tgt_target), 9345 OffloadingArgs); 9346 } 9347 9348 // Check the error code and execute the host version if required. 9349 llvm::BasicBlock *OffloadFailedBlock = 9350 CGF.createBasicBlock("omp_offload.failed"); 9351 llvm::BasicBlock *OffloadContBlock = 9352 CGF.createBasicBlock("omp_offload.cont"); 9353 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9354 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9355 9356 CGF.EmitBlock(OffloadFailedBlock); 9357 if (RequiresOuterTask) { 9358 CapturedVars.clear(); 9359 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9360 } 9361 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9362 CGF.EmitBranch(OffloadContBlock); 9363 9364 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9365 }; 9366 9367 // Notify that the host version must be executed. 9368 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9369 RequiresOuterTask](CodeGenFunction &CGF, 9370 PrePostActionTy &) { 9371 if (RequiresOuterTask) { 9372 CapturedVars.clear(); 9373 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9374 } 9375 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9376 }; 9377 9378 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9379 &CapturedVars, RequiresOuterTask, 9380 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9381 // Fill up the arrays with all the captured variables. 9382 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9383 MappableExprsHandler::MapValuesArrayTy Pointers; 9384 MappableExprsHandler::MapValuesArrayTy Sizes; 9385 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9386 9387 // Get mappable expression information. 9388 MappableExprsHandler MEHandler(D, CGF); 9389 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9390 9391 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9392 auto CV = CapturedVars.begin(); 9393 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9394 CE = CS.capture_end(); 9395 CI != CE; ++CI, ++RI, ++CV) { 9396 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9397 MappableExprsHandler::MapValuesArrayTy CurPointers; 9398 MappableExprsHandler::MapValuesArrayTy CurSizes; 9399 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9400 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9401 9402 // VLA sizes are passed to the outlined region by copy and do not have map 9403 // information associated. 9404 if (CI->capturesVariableArrayType()) { 9405 CurBasePointers.push_back(*CV); 9406 CurPointers.push_back(*CV); 9407 CurSizes.push_back(CGF.Builder.CreateIntCast( 9408 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9409 // Copy to the device as an argument. No need to retrieve it. 9410 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9411 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9412 MappableExprsHandler::OMP_MAP_IMPLICIT); 9413 } else { 9414 // If we have any information in the map clause, we use it, otherwise we 9415 // just do a default mapping. 9416 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9417 CurSizes, CurMapTypes, PartialStruct); 9418 if (CurBasePointers.empty()) 9419 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9420 CurPointers, CurSizes, CurMapTypes); 9421 // Generate correct mapping for variables captured by reference in 9422 // lambdas. 9423 if (CI->capturesVariable()) 9424 MEHandler.generateInfoForLambdaCaptures( 9425 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9426 CurMapTypes, LambdaPointers); 9427 } 9428 // We expect to have at least an element of information for this capture. 9429 assert(!CurBasePointers.empty() && 9430 "Non-existing map pointer for capture!"); 9431 assert(CurBasePointers.size() == CurPointers.size() && 9432 CurBasePointers.size() == CurSizes.size() && 9433 CurBasePointers.size() == CurMapTypes.size() && 9434 "Inconsistent map information sizes!"); 9435 9436 // If there is an entry in PartialStruct it means we have a struct with 9437 // individual members mapped. Emit an extra combined entry. 9438 if (PartialStruct.Base.isValid()) 9439 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9440 CurMapTypes, PartialStruct); 9441 9442 // We need to append the results of this capture to what we already have. 9443 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9444 Pointers.append(CurPointers.begin(), CurPointers.end()); 9445 Sizes.append(CurSizes.begin(), CurSizes.end()); 9446 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9447 } 9448 // Adjust MEMBER_OF flags for the lambdas captures. 9449 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9450 Pointers, MapTypes); 9451 // Map other list items in the map clause which are not captured variables 9452 // but "declare target link" global variables. 9453 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9454 MapTypes); 9455 9456 TargetDataInfo Info; 9457 // Fill up the arrays and create the arguments. 9458 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9459 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9460 Info.PointersArray, Info.SizesArray, 9461 Info.MapTypesArray, Info); 9462 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9463 InputInfo.BasePointersArray = 9464 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9465 InputInfo.PointersArray = 9466 Address(Info.PointersArray, CGM.getPointerAlign()); 9467 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9468 MapTypesArray = Info.MapTypesArray; 9469 if (RequiresOuterTask) 9470 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9471 else 9472 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9473 }; 9474 9475 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9476 CodeGenFunction &CGF, PrePostActionTy &) { 9477 if (RequiresOuterTask) { 9478 CodeGenFunction::OMPTargetDataInfo InputInfo; 9479 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9480 } else { 9481 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9482 } 9483 }; 9484 9485 // If we have a target function ID it means that we need to support 9486 // offloading, otherwise, just execute on the host. We need to execute on host 9487 // regardless of the conditional in the if clause if, e.g., the user do not 9488 // specify target triples. 9489 if (OutlinedFnID) { 9490 if (IfCond) { 9491 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9492 } else { 9493 RegionCodeGenTy ThenRCG(TargetThenGen); 9494 ThenRCG(CGF); 9495 } 9496 } else { 9497 RegionCodeGenTy ElseRCG(TargetElseGen); 9498 ElseRCG(CGF); 9499 } 9500 } 9501 9502 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9503 StringRef ParentName) { 9504 if (!S) 9505 return; 9506 9507 // Codegen OMP target directives that offload compute to the device. 9508 bool RequiresDeviceCodegen = 9509 isa<OMPExecutableDirective>(S) && 9510 isOpenMPTargetExecutionDirective( 9511 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9512 9513 if (RequiresDeviceCodegen) { 9514 const auto &E = *cast<OMPExecutableDirective>(S); 9515 unsigned DeviceID; 9516 unsigned FileID; 9517 unsigned Line; 9518 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9519 FileID, Line); 9520 9521 // Is this a target region that should not be emitted as an entry point? If 9522 // so just signal we are done with this target region. 9523 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9524 ParentName, Line)) 9525 return; 9526 9527 switch (E.getDirectiveKind()) { 9528 case OMPD_target: 9529 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9530 cast<OMPTargetDirective>(E)); 9531 break; 9532 case OMPD_target_parallel: 9533 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9534 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9535 break; 9536 case OMPD_target_teams: 9537 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9538 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9539 break; 9540 case OMPD_target_teams_distribute: 9541 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9542 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9543 break; 9544 case OMPD_target_teams_distribute_simd: 9545 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9546 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9547 break; 9548 case OMPD_target_parallel_for: 9549 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9550 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9551 break; 9552 case OMPD_target_parallel_for_simd: 9553 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9554 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9555 break; 9556 case OMPD_target_simd: 9557 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9558 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9559 break; 9560 case OMPD_target_teams_distribute_parallel_for: 9561 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9562 CGM, ParentName, 9563 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9564 break; 9565 case OMPD_target_teams_distribute_parallel_for_simd: 9566 CodeGenFunction:: 9567 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9568 CGM, ParentName, 9569 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9570 break; 9571 case OMPD_parallel: 9572 case OMPD_for: 9573 case OMPD_parallel_for: 9574 case OMPD_parallel_master: 9575 case OMPD_parallel_sections: 9576 case OMPD_for_simd: 9577 case OMPD_parallel_for_simd: 9578 case OMPD_cancel: 9579 case OMPD_cancellation_point: 9580 case OMPD_ordered: 9581 case OMPD_threadprivate: 9582 case OMPD_allocate: 9583 case OMPD_task: 9584 case OMPD_simd: 9585 case OMPD_sections: 9586 case OMPD_section: 9587 case OMPD_single: 9588 case OMPD_master: 9589 case OMPD_critical: 9590 case OMPD_taskyield: 9591 case OMPD_barrier: 9592 case OMPD_taskwait: 9593 case OMPD_taskgroup: 9594 case OMPD_atomic: 9595 case OMPD_flush: 9596 case OMPD_teams: 9597 case OMPD_target_data: 9598 case OMPD_target_exit_data: 9599 case OMPD_target_enter_data: 9600 case OMPD_distribute: 9601 case OMPD_distribute_simd: 9602 case OMPD_distribute_parallel_for: 9603 case OMPD_distribute_parallel_for_simd: 9604 case OMPD_teams_distribute: 9605 case OMPD_teams_distribute_simd: 9606 case OMPD_teams_distribute_parallel_for: 9607 case OMPD_teams_distribute_parallel_for_simd: 9608 case OMPD_target_update: 9609 case OMPD_declare_simd: 9610 case OMPD_declare_variant: 9611 case OMPD_declare_target: 9612 case OMPD_end_declare_target: 9613 case OMPD_declare_reduction: 9614 case OMPD_declare_mapper: 9615 case OMPD_taskloop: 9616 case OMPD_taskloop_simd: 9617 case OMPD_master_taskloop: 9618 case OMPD_master_taskloop_simd: 9619 case OMPD_parallel_master_taskloop: 9620 case OMPD_parallel_master_taskloop_simd: 9621 case OMPD_requires: 9622 case OMPD_unknown: 9623 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9624 } 9625 return; 9626 } 9627 9628 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9629 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9630 return; 9631 9632 scanForTargetRegionsFunctions( 9633 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9634 return; 9635 } 9636 9637 // If this is a lambda function, look into its body. 9638 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9639 S = L->getBody(); 9640 9641 // Keep looking for target regions recursively. 9642 for (const Stmt *II : S->children()) 9643 scanForTargetRegionsFunctions(II, ParentName); 9644 } 9645 9646 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9647 // If emitting code for the host, we do not process FD here. Instead we do 9648 // the normal code generation. 9649 if (!CGM.getLangOpts().OpenMPIsDevice) { 9650 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9651 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9652 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9653 // Do not emit device_type(nohost) functions for the host. 9654 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9655 return true; 9656 } 9657 return false; 9658 } 9659 9660 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9661 StringRef Name = CGM.getMangledName(GD); 9662 // Try to detect target regions in the function. 9663 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9664 scanForTargetRegionsFunctions(FD->getBody(), Name); 9665 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9666 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9667 // Do not emit device_type(nohost) functions for the host. 9668 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9669 return true; 9670 } 9671 9672 // Do not to emit function if it is not marked as declare target. 9673 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9674 AlreadyEmittedTargetFunctions.count(Name) == 0; 9675 } 9676 9677 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9678 if (!CGM.getLangOpts().OpenMPIsDevice) 9679 return false; 9680 9681 // Check if there are Ctors/Dtors in this declaration and look for target 9682 // regions in it. We use the complete variant to produce the kernel name 9683 // mangling. 9684 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9685 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9686 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9687 StringRef ParentName = 9688 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9689 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9690 } 9691 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9692 StringRef ParentName = 9693 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9694 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9695 } 9696 } 9697 9698 // Do not to emit variable if it is not marked as declare target. 9699 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9700 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9701 cast<VarDecl>(GD.getDecl())); 9702 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9703 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9704 HasRequiresUnifiedSharedMemory)) { 9705 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9706 return true; 9707 } 9708 return false; 9709 } 9710 9711 llvm::Constant * 9712 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9713 const VarDecl *VD) { 9714 assert(VD->getType().isConstant(CGM.getContext()) && 9715 "Expected constant variable."); 9716 StringRef VarName; 9717 llvm::Constant *Addr; 9718 llvm::GlobalValue::LinkageTypes Linkage; 9719 QualType Ty = VD->getType(); 9720 SmallString<128> Buffer; 9721 { 9722 unsigned DeviceID; 9723 unsigned FileID; 9724 unsigned Line; 9725 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9726 FileID, Line); 9727 llvm::raw_svector_ostream OS(Buffer); 9728 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9729 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9730 VarName = OS.str(); 9731 } 9732 Linkage = llvm::GlobalValue::InternalLinkage; 9733 Addr = 9734 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9735 getDefaultFirstprivateAddressSpace()); 9736 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9737 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9738 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9739 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9740 VarName, Addr, VarSize, 9741 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9742 return Addr; 9743 } 9744 9745 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9746 llvm::Constant *Addr) { 9747 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9748 !CGM.getLangOpts().OpenMPIsDevice) 9749 return; 9750 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9751 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9752 if (!Res) { 9753 if (CGM.getLangOpts().OpenMPIsDevice) { 9754 // Register non-target variables being emitted in device code (debug info 9755 // may cause this). 9756 StringRef VarName = CGM.getMangledName(VD); 9757 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9758 } 9759 return; 9760 } 9761 // Register declare target variables. 9762 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9763 StringRef VarName; 9764 CharUnits VarSize; 9765 llvm::GlobalValue::LinkageTypes Linkage; 9766 9767 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9768 !HasRequiresUnifiedSharedMemory) { 9769 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9770 VarName = CGM.getMangledName(VD); 9771 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9772 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9773 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9774 } else { 9775 VarSize = CharUnits::Zero(); 9776 } 9777 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9778 // Temp solution to prevent optimizations of the internal variables. 9779 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9780 std::string RefName = getName({VarName, "ref"}); 9781 if (!CGM.GetGlobalValue(RefName)) { 9782 llvm::Constant *AddrRef = 9783 getOrCreateInternalVariable(Addr->getType(), RefName); 9784 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9785 GVAddrRef->setConstant(/*Val=*/true); 9786 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9787 GVAddrRef->setInitializer(Addr); 9788 CGM.addCompilerUsedGlobal(GVAddrRef); 9789 } 9790 } 9791 } else { 9792 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9793 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9794 HasRequiresUnifiedSharedMemory)) && 9795 "Declare target attribute must link or to with unified memory."); 9796 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9797 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9798 else 9799 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9800 9801 if (CGM.getLangOpts().OpenMPIsDevice) { 9802 VarName = Addr->getName(); 9803 Addr = nullptr; 9804 } else { 9805 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9806 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9807 } 9808 VarSize = CGM.getPointerSize(); 9809 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9810 } 9811 9812 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9813 VarName, Addr, VarSize, Flags, Linkage); 9814 } 9815 9816 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9817 if (isa<FunctionDecl>(GD.getDecl()) || 9818 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9819 return emitTargetFunctions(GD); 9820 9821 return emitTargetGlobalVariable(GD); 9822 } 9823 9824 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9825 for (const VarDecl *VD : DeferredGlobalVariables) { 9826 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9827 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9828 if (!Res) 9829 continue; 9830 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9831 !HasRequiresUnifiedSharedMemory) { 9832 CGM.EmitGlobal(VD); 9833 } else { 9834 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9835 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9836 HasRequiresUnifiedSharedMemory)) && 9837 "Expected link clause or to clause with unified memory."); 9838 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9839 } 9840 } 9841 } 9842 9843 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9844 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9845 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9846 " Expected target-based directive."); 9847 } 9848 9849 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9850 const OMPRequiresDecl *D) { 9851 for (const OMPClause *Clause : D->clauselists()) { 9852 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9853 HasRequiresUnifiedSharedMemory = true; 9854 break; 9855 } 9856 } 9857 } 9858 9859 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9860 LangAS &AS) { 9861 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9862 return false; 9863 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9864 switch(A->getAllocatorType()) { 9865 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9866 // Not supported, fallback to the default mem space. 9867 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9868 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9869 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9870 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9871 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9872 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9873 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9874 AS = LangAS::Default; 9875 return true; 9876 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9877 llvm_unreachable("Expected predefined allocator for the variables with the " 9878 "static storage."); 9879 } 9880 return false; 9881 } 9882 9883 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9884 return HasRequiresUnifiedSharedMemory; 9885 } 9886 9887 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9888 CodeGenModule &CGM) 9889 : CGM(CGM) { 9890 if (CGM.getLangOpts().OpenMPIsDevice) { 9891 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9892 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9893 } 9894 } 9895 9896 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9897 if (CGM.getLangOpts().OpenMPIsDevice) 9898 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9899 } 9900 9901 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9902 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9903 return true; 9904 9905 StringRef Name = CGM.getMangledName(GD); 9906 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9907 // Do not to emit function if it is marked as declare target as it was already 9908 // emitted. 9909 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9910 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { 9911 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) 9912 return !F->isDeclaration(); 9913 return false; 9914 } 9915 return true; 9916 } 9917 9918 return !AlreadyEmittedTargetFunctions.insert(Name).second; 9919 } 9920 9921 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9922 // If we don't have entries or if we are emitting code for the device, we 9923 // don't need to do anything. 9924 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9925 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9926 (OffloadEntriesInfoManager.empty() && 9927 !HasEmittedDeclareTargetRegion && 9928 !HasEmittedTargetRegion)) 9929 return nullptr; 9930 9931 // Create and register the function that handles the requires directives. 9932 ASTContext &C = CGM.getContext(); 9933 9934 llvm::Function *RequiresRegFn; 9935 { 9936 CodeGenFunction CGF(CGM); 9937 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9938 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9939 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9940 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9941 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9942 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9943 // TODO: check for other requires clauses. 9944 // The requires directive takes effect only when a target region is 9945 // present in the compilation unit. Otherwise it is ignored and not 9946 // passed to the runtime. This avoids the runtime from throwing an error 9947 // for mismatching requires clauses across compilation units that don't 9948 // contain at least 1 target region. 9949 assert((HasEmittedTargetRegion || 9950 HasEmittedDeclareTargetRegion || 9951 !OffloadEntriesInfoManager.empty()) && 9952 "Target or declare target region expected."); 9953 if (HasRequiresUnifiedSharedMemory) 9954 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9955 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9956 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9957 CGF.FinishFunction(); 9958 } 9959 return RequiresRegFn; 9960 } 9961 9962 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9963 const OMPExecutableDirective &D, 9964 SourceLocation Loc, 9965 llvm::Function *OutlinedFn, 9966 ArrayRef<llvm::Value *> CapturedVars) { 9967 if (!CGF.HaveInsertPoint()) 9968 return; 9969 9970 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9971 CodeGenFunction::RunCleanupsScope Scope(CGF); 9972 9973 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9974 llvm::Value *Args[] = { 9975 RTLoc, 9976 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9977 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9978 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9979 RealArgs.append(std::begin(Args), std::end(Args)); 9980 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9981 9982 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9983 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9984 } 9985 9986 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9987 const Expr *NumTeams, 9988 const Expr *ThreadLimit, 9989 SourceLocation Loc) { 9990 if (!CGF.HaveInsertPoint()) 9991 return; 9992 9993 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9994 9995 llvm::Value *NumTeamsVal = 9996 NumTeams 9997 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9998 CGF.CGM.Int32Ty, /* isSigned = */ true) 9999 : CGF.Builder.getInt32(0); 10000 10001 llvm::Value *ThreadLimitVal = 10002 ThreadLimit 10003 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 10004 CGF.CGM.Int32Ty, /* isSigned = */ true) 10005 : CGF.Builder.getInt32(0); 10006 10007 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 10008 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 10009 ThreadLimitVal}; 10010 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 10011 PushNumTeamsArgs); 10012 } 10013 10014 void CGOpenMPRuntime::emitTargetDataCalls( 10015 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10016 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10017 if (!CGF.HaveInsertPoint()) 10018 return; 10019 10020 // Action used to replace the default codegen action and turn privatization 10021 // off. 10022 PrePostActionTy NoPrivAction; 10023 10024 // Generate the code for the opening of the data environment. Capture all the 10025 // arguments of the runtime call by reference because they are used in the 10026 // closing of the region. 10027 auto &&BeginThenGen = [this, &D, Device, &Info, 10028 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10029 // Fill up the arrays with all the mapped variables. 10030 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10031 MappableExprsHandler::MapValuesArrayTy Pointers; 10032 MappableExprsHandler::MapValuesArrayTy Sizes; 10033 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10034 10035 // Get map clause information. 10036 MappableExprsHandler MCHandler(D, CGF); 10037 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10038 10039 // Fill up the arrays and create the arguments. 10040 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10041 10042 llvm::Value *BasePointersArrayArg = nullptr; 10043 llvm::Value *PointersArrayArg = nullptr; 10044 llvm::Value *SizesArrayArg = nullptr; 10045 llvm::Value *MapTypesArrayArg = nullptr; 10046 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10047 SizesArrayArg, MapTypesArrayArg, Info); 10048 10049 // Emit device ID if any. 10050 llvm::Value *DeviceID = nullptr; 10051 if (Device) { 10052 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10053 CGF.Int64Ty, /*isSigned=*/true); 10054 } else { 10055 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10056 } 10057 10058 // Emit the number of elements in the offloading arrays. 10059 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10060 10061 llvm::Value *OffloadingArgs[] = { 10062 DeviceID, PointerNum, BasePointersArrayArg, 10063 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10064 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10065 OffloadingArgs); 10066 10067 // If device pointer privatization is required, emit the body of the region 10068 // here. It will have to be duplicated: with and without privatization. 10069 if (!Info.CaptureDeviceAddrMap.empty()) 10070 CodeGen(CGF); 10071 }; 10072 10073 // Generate code for the closing of the data region. 10074 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10075 PrePostActionTy &) { 10076 assert(Info.isValid() && "Invalid data environment closing arguments."); 10077 10078 llvm::Value *BasePointersArrayArg = nullptr; 10079 llvm::Value *PointersArrayArg = nullptr; 10080 llvm::Value *SizesArrayArg = nullptr; 10081 llvm::Value *MapTypesArrayArg = nullptr; 10082 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10083 SizesArrayArg, MapTypesArrayArg, Info); 10084 10085 // Emit device ID if any. 10086 llvm::Value *DeviceID = nullptr; 10087 if (Device) { 10088 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10089 CGF.Int64Ty, /*isSigned=*/true); 10090 } else { 10091 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10092 } 10093 10094 // Emit the number of elements in the offloading arrays. 10095 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10096 10097 llvm::Value *OffloadingArgs[] = { 10098 DeviceID, PointerNum, BasePointersArrayArg, 10099 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10100 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10101 OffloadingArgs); 10102 }; 10103 10104 // If we need device pointer privatization, we need to emit the body of the 10105 // region with no privatization in the 'else' branch of the conditional. 10106 // Otherwise, we don't have to do anything. 10107 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10108 PrePostActionTy &) { 10109 if (!Info.CaptureDeviceAddrMap.empty()) { 10110 CodeGen.setAction(NoPrivAction); 10111 CodeGen(CGF); 10112 } 10113 }; 10114 10115 // We don't have to do anything to close the region if the if clause evaluates 10116 // to false. 10117 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10118 10119 if (IfCond) { 10120 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10121 } else { 10122 RegionCodeGenTy RCG(BeginThenGen); 10123 RCG(CGF); 10124 } 10125 10126 // If we don't require privatization of device pointers, we emit the body in 10127 // between the runtime calls. This avoids duplicating the body code. 10128 if (Info.CaptureDeviceAddrMap.empty()) { 10129 CodeGen.setAction(NoPrivAction); 10130 CodeGen(CGF); 10131 } 10132 10133 if (IfCond) { 10134 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10135 } else { 10136 RegionCodeGenTy RCG(EndThenGen); 10137 RCG(CGF); 10138 } 10139 } 10140 10141 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10142 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10143 const Expr *Device) { 10144 if (!CGF.HaveInsertPoint()) 10145 return; 10146 10147 assert((isa<OMPTargetEnterDataDirective>(D) || 10148 isa<OMPTargetExitDataDirective>(D) || 10149 isa<OMPTargetUpdateDirective>(D)) && 10150 "Expecting either target enter, exit data, or update directives."); 10151 10152 CodeGenFunction::OMPTargetDataInfo InputInfo; 10153 llvm::Value *MapTypesArray = nullptr; 10154 // Generate the code for the opening of the data environment. 10155 auto &&ThenGen = [this, &D, Device, &InputInfo, 10156 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10157 // Emit device ID if any. 10158 llvm::Value *DeviceID = nullptr; 10159 if (Device) { 10160 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10161 CGF.Int64Ty, /*isSigned=*/true); 10162 } else { 10163 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10164 } 10165 10166 // Emit the number of elements in the offloading arrays. 10167 llvm::Constant *PointerNum = 10168 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10169 10170 llvm::Value *OffloadingArgs[] = {DeviceID, 10171 PointerNum, 10172 InputInfo.BasePointersArray.getPointer(), 10173 InputInfo.PointersArray.getPointer(), 10174 InputInfo.SizesArray.getPointer(), 10175 MapTypesArray}; 10176 10177 // Select the right runtime function call for each expected standalone 10178 // directive. 10179 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10180 OpenMPRTLFunction RTLFn; 10181 switch (D.getDirectiveKind()) { 10182 case OMPD_target_enter_data: 10183 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10184 : OMPRTL__tgt_target_data_begin; 10185 break; 10186 case OMPD_target_exit_data: 10187 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10188 : OMPRTL__tgt_target_data_end; 10189 break; 10190 case OMPD_target_update: 10191 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10192 : OMPRTL__tgt_target_data_update; 10193 break; 10194 case OMPD_parallel: 10195 case OMPD_for: 10196 case OMPD_parallel_for: 10197 case OMPD_parallel_master: 10198 case OMPD_parallel_sections: 10199 case OMPD_for_simd: 10200 case OMPD_parallel_for_simd: 10201 case OMPD_cancel: 10202 case OMPD_cancellation_point: 10203 case OMPD_ordered: 10204 case OMPD_threadprivate: 10205 case OMPD_allocate: 10206 case OMPD_task: 10207 case OMPD_simd: 10208 case OMPD_sections: 10209 case OMPD_section: 10210 case OMPD_single: 10211 case OMPD_master: 10212 case OMPD_critical: 10213 case OMPD_taskyield: 10214 case OMPD_barrier: 10215 case OMPD_taskwait: 10216 case OMPD_taskgroup: 10217 case OMPD_atomic: 10218 case OMPD_flush: 10219 case OMPD_teams: 10220 case OMPD_target_data: 10221 case OMPD_distribute: 10222 case OMPD_distribute_simd: 10223 case OMPD_distribute_parallel_for: 10224 case OMPD_distribute_parallel_for_simd: 10225 case OMPD_teams_distribute: 10226 case OMPD_teams_distribute_simd: 10227 case OMPD_teams_distribute_parallel_for: 10228 case OMPD_teams_distribute_parallel_for_simd: 10229 case OMPD_declare_simd: 10230 case OMPD_declare_variant: 10231 case OMPD_declare_target: 10232 case OMPD_end_declare_target: 10233 case OMPD_declare_reduction: 10234 case OMPD_declare_mapper: 10235 case OMPD_taskloop: 10236 case OMPD_taskloop_simd: 10237 case OMPD_master_taskloop: 10238 case OMPD_master_taskloop_simd: 10239 case OMPD_parallel_master_taskloop: 10240 case OMPD_parallel_master_taskloop_simd: 10241 case OMPD_target: 10242 case OMPD_target_simd: 10243 case OMPD_target_teams_distribute: 10244 case OMPD_target_teams_distribute_simd: 10245 case OMPD_target_teams_distribute_parallel_for: 10246 case OMPD_target_teams_distribute_parallel_for_simd: 10247 case OMPD_target_teams: 10248 case OMPD_target_parallel: 10249 case OMPD_target_parallel_for: 10250 case OMPD_target_parallel_for_simd: 10251 case OMPD_requires: 10252 case OMPD_unknown: 10253 llvm_unreachable("Unexpected standalone target data directive."); 10254 break; 10255 } 10256 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10257 }; 10258 10259 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10260 CodeGenFunction &CGF, PrePostActionTy &) { 10261 // Fill up the arrays with all the mapped variables. 10262 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10263 MappableExprsHandler::MapValuesArrayTy Pointers; 10264 MappableExprsHandler::MapValuesArrayTy Sizes; 10265 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10266 10267 // Get map clause information. 10268 MappableExprsHandler MEHandler(D, CGF); 10269 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10270 10271 TargetDataInfo Info; 10272 // Fill up the arrays and create the arguments. 10273 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10274 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10275 Info.PointersArray, Info.SizesArray, 10276 Info.MapTypesArray, Info); 10277 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10278 InputInfo.BasePointersArray = 10279 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10280 InputInfo.PointersArray = 10281 Address(Info.PointersArray, CGM.getPointerAlign()); 10282 InputInfo.SizesArray = 10283 Address(Info.SizesArray, CGM.getPointerAlign()); 10284 MapTypesArray = Info.MapTypesArray; 10285 if (D.hasClausesOfKind<OMPDependClause>()) 10286 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10287 else 10288 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10289 }; 10290 10291 if (IfCond) { 10292 emitIfClause(CGF, IfCond, TargetThenGen, 10293 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10294 } else { 10295 RegionCodeGenTy ThenRCG(TargetThenGen); 10296 ThenRCG(CGF); 10297 } 10298 } 10299 10300 namespace { 10301 /// Kind of parameter in a function with 'declare simd' directive. 10302 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10303 /// Attribute set of the parameter. 10304 struct ParamAttrTy { 10305 ParamKindTy Kind = Vector; 10306 llvm::APSInt StrideOrArg; 10307 llvm::APSInt Alignment; 10308 }; 10309 } // namespace 10310 10311 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10312 ArrayRef<ParamAttrTy> ParamAttrs) { 10313 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10314 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10315 // of that clause. The VLEN value must be power of 2. 10316 // In other case the notion of the function`s "characteristic data type" (CDT) 10317 // is used to compute the vector length. 10318 // CDT is defined in the following order: 10319 // a) For non-void function, the CDT is the return type. 10320 // b) If the function has any non-uniform, non-linear parameters, then the 10321 // CDT is the type of the first such parameter. 10322 // c) If the CDT determined by a) or b) above is struct, union, or class 10323 // type which is pass-by-value (except for the type that maps to the 10324 // built-in complex data type), the characteristic data type is int. 10325 // d) If none of the above three cases is applicable, the CDT is int. 10326 // The VLEN is then determined based on the CDT and the size of vector 10327 // register of that ISA for which current vector version is generated. The 10328 // VLEN is computed using the formula below: 10329 // VLEN = sizeof(vector_register) / sizeof(CDT), 10330 // where vector register size specified in section 3.2.1 Registers and the 10331 // Stack Frame of original AMD64 ABI document. 10332 QualType RetType = FD->getReturnType(); 10333 if (RetType.isNull()) 10334 return 0; 10335 ASTContext &C = FD->getASTContext(); 10336 QualType CDT; 10337 if (!RetType.isNull() && !RetType->isVoidType()) { 10338 CDT = RetType; 10339 } else { 10340 unsigned Offset = 0; 10341 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10342 if (ParamAttrs[Offset].Kind == Vector) 10343 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10344 ++Offset; 10345 } 10346 if (CDT.isNull()) { 10347 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10348 if (ParamAttrs[I + Offset].Kind == Vector) { 10349 CDT = FD->getParamDecl(I)->getType(); 10350 break; 10351 } 10352 } 10353 } 10354 } 10355 if (CDT.isNull()) 10356 CDT = C.IntTy; 10357 CDT = CDT->getCanonicalTypeUnqualified(); 10358 if (CDT->isRecordType() || CDT->isUnionType()) 10359 CDT = C.IntTy; 10360 return C.getTypeSize(CDT); 10361 } 10362 10363 static void 10364 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10365 const llvm::APSInt &VLENVal, 10366 ArrayRef<ParamAttrTy> ParamAttrs, 10367 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10368 struct ISADataTy { 10369 char ISA; 10370 unsigned VecRegSize; 10371 }; 10372 ISADataTy ISAData[] = { 10373 { 10374 'b', 128 10375 }, // SSE 10376 { 10377 'c', 256 10378 }, // AVX 10379 { 10380 'd', 256 10381 }, // AVX2 10382 { 10383 'e', 512 10384 }, // AVX512 10385 }; 10386 llvm::SmallVector<char, 2> Masked; 10387 switch (State) { 10388 case OMPDeclareSimdDeclAttr::BS_Undefined: 10389 Masked.push_back('N'); 10390 Masked.push_back('M'); 10391 break; 10392 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10393 Masked.push_back('N'); 10394 break; 10395 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10396 Masked.push_back('M'); 10397 break; 10398 } 10399 for (char Mask : Masked) { 10400 for (const ISADataTy &Data : ISAData) { 10401 SmallString<256> Buffer; 10402 llvm::raw_svector_ostream Out(Buffer); 10403 Out << "_ZGV" << Data.ISA << Mask; 10404 if (!VLENVal) { 10405 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10406 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10407 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10408 } else { 10409 Out << VLENVal; 10410 } 10411 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10412 switch (ParamAttr.Kind){ 10413 case LinearWithVarStride: 10414 Out << 's' << ParamAttr.StrideOrArg; 10415 break; 10416 case Linear: 10417 Out << 'l'; 10418 if (!!ParamAttr.StrideOrArg) 10419 Out << ParamAttr.StrideOrArg; 10420 break; 10421 case Uniform: 10422 Out << 'u'; 10423 break; 10424 case Vector: 10425 Out << 'v'; 10426 break; 10427 } 10428 if (!!ParamAttr.Alignment) 10429 Out << 'a' << ParamAttr.Alignment; 10430 } 10431 Out << '_' << Fn->getName(); 10432 Fn->addFnAttr(Out.str()); 10433 } 10434 } 10435 } 10436 10437 // This are the Functions that are needed to mangle the name of the 10438 // vector functions generated by the compiler, according to the rules 10439 // defined in the "Vector Function ABI specifications for AArch64", 10440 // available at 10441 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10442 10443 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10444 /// 10445 /// TODO: Need to implement the behavior for reference marked with a 10446 /// var or no linear modifiers (1.b in the section). For this, we 10447 /// need to extend ParamKindTy to support the linear modifiers. 10448 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10449 QT = QT.getCanonicalType(); 10450 10451 if (QT->isVoidType()) 10452 return false; 10453 10454 if (Kind == ParamKindTy::Uniform) 10455 return false; 10456 10457 if (Kind == ParamKindTy::Linear) 10458 return false; 10459 10460 // TODO: Handle linear references with modifiers 10461 10462 if (Kind == ParamKindTy::LinearWithVarStride) 10463 return false; 10464 10465 return true; 10466 } 10467 10468 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10469 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10470 QT = QT.getCanonicalType(); 10471 unsigned Size = C.getTypeSize(QT); 10472 10473 // Only scalars and complex within 16 bytes wide set PVB to true. 10474 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10475 return false; 10476 10477 if (QT->isFloatingType()) 10478 return true; 10479 10480 if (QT->isIntegerType()) 10481 return true; 10482 10483 if (QT->isPointerType()) 10484 return true; 10485 10486 // TODO: Add support for complex types (section 3.1.2, item 2). 10487 10488 return false; 10489 } 10490 10491 /// Computes the lane size (LS) of a return type or of an input parameter, 10492 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10493 /// TODO: Add support for references, section 3.2.1, item 1. 10494 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10495 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10496 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10497 if (getAArch64PBV(PTy, C)) 10498 return C.getTypeSize(PTy); 10499 } 10500 if (getAArch64PBV(QT, C)) 10501 return C.getTypeSize(QT); 10502 10503 return C.getTypeSize(C.getUIntPtrType()); 10504 } 10505 10506 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10507 // signature of the scalar function, as defined in 3.2.2 of the 10508 // AAVFABI. 10509 static std::tuple<unsigned, unsigned, bool> 10510 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10511 QualType RetType = FD->getReturnType().getCanonicalType(); 10512 10513 ASTContext &C = FD->getASTContext(); 10514 10515 bool OutputBecomesInput = false; 10516 10517 llvm::SmallVector<unsigned, 8> Sizes; 10518 if (!RetType->isVoidType()) { 10519 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10520 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10521 OutputBecomesInput = true; 10522 } 10523 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10524 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10525 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10526 } 10527 10528 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10529 // The LS of a function parameter / return value can only be a power 10530 // of 2, starting from 8 bits, up to 128. 10531 assert(std::all_of(Sizes.begin(), Sizes.end(), 10532 [](unsigned Size) { 10533 return Size == 8 || Size == 16 || Size == 32 || 10534 Size == 64 || Size == 128; 10535 }) && 10536 "Invalid size"); 10537 10538 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10539 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10540 OutputBecomesInput); 10541 } 10542 10543 /// Mangle the parameter part of the vector function name according to 10544 /// their OpenMP classification. The mangling function is defined in 10545 /// section 3.5 of the AAVFABI. 10546 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10547 SmallString<256> Buffer; 10548 llvm::raw_svector_ostream Out(Buffer); 10549 for (const auto &ParamAttr : ParamAttrs) { 10550 switch (ParamAttr.Kind) { 10551 case LinearWithVarStride: 10552 Out << "ls" << ParamAttr.StrideOrArg; 10553 break; 10554 case Linear: 10555 Out << 'l'; 10556 // Don't print the step value if it is not present or if it is 10557 // equal to 1. 10558 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10559 Out << ParamAttr.StrideOrArg; 10560 break; 10561 case Uniform: 10562 Out << 'u'; 10563 break; 10564 case Vector: 10565 Out << 'v'; 10566 break; 10567 } 10568 10569 if (!!ParamAttr.Alignment) 10570 Out << 'a' << ParamAttr.Alignment; 10571 } 10572 10573 return Out.str(); 10574 } 10575 10576 // Function used to add the attribute. The parameter `VLEN` is 10577 // templated to allow the use of "x" when targeting scalable functions 10578 // for SVE. 10579 template <typename T> 10580 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10581 char ISA, StringRef ParSeq, 10582 StringRef MangledName, bool OutputBecomesInput, 10583 llvm::Function *Fn) { 10584 SmallString<256> Buffer; 10585 llvm::raw_svector_ostream Out(Buffer); 10586 Out << Prefix << ISA << LMask << VLEN; 10587 if (OutputBecomesInput) 10588 Out << "v"; 10589 Out << ParSeq << "_" << MangledName; 10590 Fn->addFnAttr(Out.str()); 10591 } 10592 10593 // Helper function to generate the Advanced SIMD names depending on 10594 // the value of the NDS when simdlen is not present. 10595 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10596 StringRef Prefix, char ISA, 10597 StringRef ParSeq, StringRef MangledName, 10598 bool OutputBecomesInput, 10599 llvm::Function *Fn) { 10600 switch (NDS) { 10601 case 8: 10602 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10603 OutputBecomesInput, Fn); 10604 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10605 OutputBecomesInput, Fn); 10606 break; 10607 case 16: 10608 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10609 OutputBecomesInput, Fn); 10610 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10611 OutputBecomesInput, Fn); 10612 break; 10613 case 32: 10614 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10615 OutputBecomesInput, Fn); 10616 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10617 OutputBecomesInput, Fn); 10618 break; 10619 case 64: 10620 case 128: 10621 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10622 OutputBecomesInput, Fn); 10623 break; 10624 default: 10625 llvm_unreachable("Scalar type is too wide."); 10626 } 10627 } 10628 10629 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10630 static void emitAArch64DeclareSimdFunction( 10631 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10632 ArrayRef<ParamAttrTy> ParamAttrs, 10633 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10634 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10635 10636 // Get basic data for building the vector signature. 10637 const auto Data = getNDSWDS(FD, ParamAttrs); 10638 const unsigned NDS = std::get<0>(Data); 10639 const unsigned WDS = std::get<1>(Data); 10640 const bool OutputBecomesInput = std::get<2>(Data); 10641 10642 // Check the values provided via `simdlen` by the user. 10643 // 1. A `simdlen(1)` doesn't produce vector signatures, 10644 if (UserVLEN == 1) { 10645 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10646 DiagnosticsEngine::Warning, 10647 "The clause simdlen(1) has no effect when targeting aarch64."); 10648 CGM.getDiags().Report(SLoc, DiagID); 10649 return; 10650 } 10651 10652 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10653 // Advanced SIMD output. 10654 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10655 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10656 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10657 "power of 2 when targeting Advanced SIMD."); 10658 CGM.getDiags().Report(SLoc, DiagID); 10659 return; 10660 } 10661 10662 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10663 // limits. 10664 if (ISA == 's' && UserVLEN != 0) { 10665 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10666 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10667 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10668 "lanes in the architectural constraints " 10669 "for SVE (min is 128-bit, max is " 10670 "2048-bit, by steps of 128-bit)"); 10671 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10672 return; 10673 } 10674 } 10675 10676 // Sort out parameter sequence. 10677 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10678 StringRef Prefix = "_ZGV"; 10679 // Generate simdlen from user input (if any). 10680 if (UserVLEN) { 10681 if (ISA == 's') { 10682 // SVE generates only a masked function. 10683 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10684 OutputBecomesInput, Fn); 10685 } else { 10686 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10687 // Advanced SIMD generates one or two functions, depending on 10688 // the `[not]inbranch` clause. 10689 switch (State) { 10690 case OMPDeclareSimdDeclAttr::BS_Undefined: 10691 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10692 OutputBecomesInput, Fn); 10693 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10694 OutputBecomesInput, Fn); 10695 break; 10696 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10697 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10698 OutputBecomesInput, Fn); 10699 break; 10700 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10701 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10702 OutputBecomesInput, Fn); 10703 break; 10704 } 10705 } 10706 } else { 10707 // If no user simdlen is provided, follow the AAVFABI rules for 10708 // generating the vector length. 10709 if (ISA == 's') { 10710 // SVE, section 3.4.1, item 1. 10711 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10712 OutputBecomesInput, Fn); 10713 } else { 10714 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10715 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10716 // two vector names depending on the use of the clause 10717 // `[not]inbranch`. 10718 switch (State) { 10719 case OMPDeclareSimdDeclAttr::BS_Undefined: 10720 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10721 OutputBecomesInput, Fn); 10722 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10723 OutputBecomesInput, Fn); 10724 break; 10725 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10726 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10727 OutputBecomesInput, Fn); 10728 break; 10729 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10730 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10731 OutputBecomesInput, Fn); 10732 break; 10733 } 10734 } 10735 } 10736 } 10737 10738 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10739 llvm::Function *Fn) { 10740 ASTContext &C = CGM.getContext(); 10741 FD = FD->getMostRecentDecl(); 10742 // Map params to their positions in function decl. 10743 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10744 if (isa<CXXMethodDecl>(FD)) 10745 ParamPositions.try_emplace(FD, 0); 10746 unsigned ParamPos = ParamPositions.size(); 10747 for (const ParmVarDecl *P : FD->parameters()) { 10748 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10749 ++ParamPos; 10750 } 10751 while (FD) { 10752 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10753 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10754 // Mark uniform parameters. 10755 for (const Expr *E : Attr->uniforms()) { 10756 E = E->IgnoreParenImpCasts(); 10757 unsigned Pos; 10758 if (isa<CXXThisExpr>(E)) { 10759 Pos = ParamPositions[FD]; 10760 } else { 10761 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10762 ->getCanonicalDecl(); 10763 Pos = ParamPositions[PVD]; 10764 } 10765 ParamAttrs[Pos].Kind = Uniform; 10766 } 10767 // Get alignment info. 10768 auto NI = Attr->alignments_begin(); 10769 for (const Expr *E : Attr->aligneds()) { 10770 E = E->IgnoreParenImpCasts(); 10771 unsigned Pos; 10772 QualType ParmTy; 10773 if (isa<CXXThisExpr>(E)) { 10774 Pos = ParamPositions[FD]; 10775 ParmTy = E->getType(); 10776 } else { 10777 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10778 ->getCanonicalDecl(); 10779 Pos = ParamPositions[PVD]; 10780 ParmTy = PVD->getType(); 10781 } 10782 ParamAttrs[Pos].Alignment = 10783 (*NI) 10784 ? (*NI)->EvaluateKnownConstInt(C) 10785 : llvm::APSInt::getUnsigned( 10786 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10787 .getQuantity()); 10788 ++NI; 10789 } 10790 // Mark linear parameters. 10791 auto SI = Attr->steps_begin(); 10792 auto MI = Attr->modifiers_begin(); 10793 for (const Expr *E : Attr->linears()) { 10794 E = E->IgnoreParenImpCasts(); 10795 unsigned Pos; 10796 if (isa<CXXThisExpr>(E)) { 10797 Pos = ParamPositions[FD]; 10798 } else { 10799 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10800 ->getCanonicalDecl(); 10801 Pos = ParamPositions[PVD]; 10802 } 10803 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10804 ParamAttr.Kind = Linear; 10805 if (*SI) { 10806 Expr::EvalResult Result; 10807 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10808 if (const auto *DRE = 10809 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10810 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10811 ParamAttr.Kind = LinearWithVarStride; 10812 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10813 ParamPositions[StridePVD->getCanonicalDecl()]); 10814 } 10815 } 10816 } else { 10817 ParamAttr.StrideOrArg = Result.Val.getInt(); 10818 } 10819 } 10820 ++SI; 10821 ++MI; 10822 } 10823 llvm::APSInt VLENVal; 10824 SourceLocation ExprLoc; 10825 const Expr *VLENExpr = Attr->getSimdlen(); 10826 if (VLENExpr) { 10827 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10828 ExprLoc = VLENExpr->getExprLoc(); 10829 } 10830 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10831 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 10832 CGM.getTriple().getArch() == llvm::Triple::x86_64) { 10833 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10834 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10835 unsigned VLEN = VLENVal.getExtValue(); 10836 StringRef MangledName = Fn->getName(); 10837 if (CGM.getTarget().hasFeature("sve")) 10838 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10839 MangledName, 's', 128, Fn, ExprLoc); 10840 if (CGM.getTarget().hasFeature("neon")) 10841 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10842 MangledName, 'n', 128, Fn, ExprLoc); 10843 } 10844 } 10845 FD = FD->getPreviousDecl(); 10846 } 10847 } 10848 10849 namespace { 10850 /// Cleanup action for doacross support. 10851 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10852 public: 10853 static const int DoacrossFinArgs = 2; 10854 10855 private: 10856 llvm::FunctionCallee RTLFn; 10857 llvm::Value *Args[DoacrossFinArgs]; 10858 10859 public: 10860 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10861 ArrayRef<llvm::Value *> CallArgs) 10862 : RTLFn(RTLFn) { 10863 assert(CallArgs.size() == DoacrossFinArgs); 10864 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10865 } 10866 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10867 if (!CGF.HaveInsertPoint()) 10868 return; 10869 CGF.EmitRuntimeCall(RTLFn, Args); 10870 } 10871 }; 10872 } // namespace 10873 10874 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10875 const OMPLoopDirective &D, 10876 ArrayRef<Expr *> NumIterations) { 10877 if (!CGF.HaveInsertPoint()) 10878 return; 10879 10880 ASTContext &C = CGM.getContext(); 10881 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10882 RecordDecl *RD; 10883 if (KmpDimTy.isNull()) { 10884 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10885 // kmp_int64 lo; // lower 10886 // kmp_int64 up; // upper 10887 // kmp_int64 st; // stride 10888 // }; 10889 RD = C.buildImplicitRecord("kmp_dim"); 10890 RD->startDefinition(); 10891 addFieldToRecordDecl(C, RD, Int64Ty); 10892 addFieldToRecordDecl(C, RD, Int64Ty); 10893 addFieldToRecordDecl(C, RD, Int64Ty); 10894 RD->completeDefinition(); 10895 KmpDimTy = C.getRecordType(RD); 10896 } else { 10897 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10898 } 10899 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10900 QualType ArrayTy = 10901 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10902 10903 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10904 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10905 enum { LowerFD = 0, UpperFD, StrideFD }; 10906 // Fill dims with data. 10907 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10908 LValue DimsLVal = CGF.MakeAddrLValue( 10909 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10910 // dims.upper = num_iterations; 10911 LValue UpperLVal = CGF.EmitLValueForField( 10912 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10913 llvm::Value *NumIterVal = 10914 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10915 D.getNumIterations()->getType(), Int64Ty, 10916 D.getNumIterations()->getExprLoc()); 10917 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10918 // dims.stride = 1; 10919 LValue StrideLVal = CGF.EmitLValueForField( 10920 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10921 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10922 StrideLVal); 10923 } 10924 10925 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10926 // kmp_int32 num_dims, struct kmp_dim * dims); 10927 llvm::Value *Args[] = { 10928 emitUpdateLocation(CGF, D.getBeginLoc()), 10929 getThreadID(CGF, D.getBeginLoc()), 10930 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10931 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10932 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10933 CGM.VoidPtrTy)}; 10934 10935 llvm::FunctionCallee RTLFn = 10936 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10937 CGF.EmitRuntimeCall(RTLFn, Args); 10938 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10939 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10940 llvm::FunctionCallee FiniRTLFn = 10941 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10942 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10943 llvm::makeArrayRef(FiniArgs)); 10944 } 10945 10946 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10947 const OMPDependClause *C) { 10948 QualType Int64Ty = 10949 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10950 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10951 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10952 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10953 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10954 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10955 const Expr *CounterVal = C->getLoopData(I); 10956 assert(CounterVal); 10957 llvm::Value *CntVal = CGF.EmitScalarConversion( 10958 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10959 CounterVal->getExprLoc()); 10960 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10961 /*Volatile=*/false, Int64Ty); 10962 } 10963 llvm::Value *Args[] = { 10964 emitUpdateLocation(CGF, C->getBeginLoc()), 10965 getThreadID(CGF, C->getBeginLoc()), 10966 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10967 llvm::FunctionCallee RTLFn; 10968 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10969 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10970 } else { 10971 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10972 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10973 } 10974 CGF.EmitRuntimeCall(RTLFn, Args); 10975 } 10976 10977 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10978 llvm::FunctionCallee Callee, 10979 ArrayRef<llvm::Value *> Args) const { 10980 assert(Loc.isValid() && "Outlined function call location must be valid."); 10981 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10982 10983 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10984 if (Fn->doesNotThrow()) { 10985 CGF.EmitNounwindRuntimeCall(Fn, Args); 10986 return; 10987 } 10988 } 10989 CGF.EmitRuntimeCall(Callee, Args); 10990 } 10991 10992 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10993 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10994 ArrayRef<llvm::Value *> Args) const { 10995 emitCall(CGF, Loc, OutlinedFn, Args); 10996 } 10997 10998 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10999 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 11000 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 11001 HasEmittedDeclareTargetRegion = true; 11002 } 11003 11004 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 11005 const VarDecl *NativeParam, 11006 const VarDecl *TargetParam) const { 11007 return CGF.GetAddrOfLocalVar(NativeParam); 11008 } 11009 11010 namespace { 11011 /// Cleanup action for allocate support. 11012 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 11013 public: 11014 static const int CleanupArgs = 3; 11015 11016 private: 11017 llvm::FunctionCallee RTLFn; 11018 llvm::Value *Args[CleanupArgs]; 11019 11020 public: 11021 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 11022 ArrayRef<llvm::Value *> CallArgs) 11023 : RTLFn(RTLFn) { 11024 assert(CallArgs.size() == CleanupArgs && 11025 "Size of arguments does not match."); 11026 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11027 } 11028 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11029 if (!CGF.HaveInsertPoint()) 11030 return; 11031 CGF.EmitRuntimeCall(RTLFn, Args); 11032 } 11033 }; 11034 } // namespace 11035 11036 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11037 const VarDecl *VD) { 11038 if (!VD) 11039 return Address::invalid(); 11040 const VarDecl *CVD = VD->getCanonicalDecl(); 11041 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 11042 return Address::invalid(); 11043 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11044 // Use the default allocation. 11045 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 11046 !AA->getAllocator()) 11047 return Address::invalid(); 11048 llvm::Value *Size; 11049 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11050 if (CVD->getType()->isVariablyModifiedType()) { 11051 Size = CGF.getTypeSize(CVD->getType()); 11052 // Align the size: ((size + align - 1) / align) * align 11053 Size = CGF.Builder.CreateNUWAdd( 11054 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11055 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11056 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11057 } else { 11058 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11059 Size = CGM.getSize(Sz.alignTo(Align)); 11060 } 11061 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11062 assert(AA->getAllocator() && 11063 "Expected allocator expression for non-default allocator."); 11064 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11065 // According to the standard, the original allocator type is a enum (integer). 11066 // Convert to pointer type, if required. 11067 if (Allocator->getType()->isIntegerTy()) 11068 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11069 else if (Allocator->getType()->isPointerTy()) 11070 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11071 CGM.VoidPtrTy); 11072 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11073 11074 llvm::Value *Addr = 11075 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11076 CVD->getName() + ".void.addr"); 11077 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11078 Allocator}; 11079 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11080 11081 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11082 llvm::makeArrayRef(FiniArgs)); 11083 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11084 Addr, 11085 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11086 CVD->getName() + ".addr"); 11087 return Address(Addr, Align); 11088 } 11089 11090 namespace { 11091 using OMPContextSelectorData = 11092 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>; 11093 using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>; 11094 } // anonymous namespace 11095 11096 /// Checks current context and returns true if it matches the context selector. 11097 template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx, 11098 typename... Arguments> 11099 static bool checkContext(const OMPContextSelectorData &Data, 11100 Arguments... Params) { 11101 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown && 11102 "Unknown context selector or context selector set."); 11103 return false; 11104 } 11105 11106 /// Checks for implementation={vendor(<vendor>)} context selector. 11107 /// \returns true iff <vendor>="llvm", false otherwise. 11108 template <> 11109 bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>( 11110 const OMPContextSelectorData &Data) { 11111 return llvm::all_of(Data.Names, 11112 [](StringRef S) { return !S.compare_lower("llvm"); }); 11113 } 11114 11115 /// Checks for device={kind(<kind>)} context selector. 11116 /// \returns true if <kind>="host" and compilation is for host. 11117 /// true if <kind>="nohost" and compilation is for device. 11118 /// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU. 11119 /// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN. 11120 /// false otherwise. 11121 template <> 11122 bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>( 11123 const OMPContextSelectorData &Data, CodeGenModule &CGM) { 11124 for (StringRef Name : Data.Names) { 11125 if (!Name.compare_lower("host")) { 11126 if (CGM.getLangOpts().OpenMPIsDevice) 11127 return false; 11128 continue; 11129 } 11130 if (!Name.compare_lower("nohost")) { 11131 if (!CGM.getLangOpts().OpenMPIsDevice) 11132 return false; 11133 continue; 11134 } 11135 switch (CGM.getTriple().getArch()) { 11136 case llvm::Triple::arm: 11137 case llvm::Triple::armeb: 11138 case llvm::Triple::aarch64: 11139 case llvm::Triple::aarch64_be: 11140 case llvm::Triple::aarch64_32: 11141 case llvm::Triple::ppc: 11142 case llvm::Triple::ppc64: 11143 case llvm::Triple::ppc64le: 11144 case llvm::Triple::x86: 11145 case llvm::Triple::x86_64: 11146 if (Name.compare_lower("cpu")) 11147 return false; 11148 break; 11149 case llvm::Triple::amdgcn: 11150 case llvm::Triple::nvptx: 11151 case llvm::Triple::nvptx64: 11152 if (Name.compare_lower("gpu")) 11153 return false; 11154 break; 11155 case llvm::Triple::UnknownArch: 11156 case llvm::Triple::arc: 11157 case llvm::Triple::avr: 11158 case llvm::Triple::bpfel: 11159 case llvm::Triple::bpfeb: 11160 case llvm::Triple::hexagon: 11161 case llvm::Triple::mips: 11162 case llvm::Triple::mipsel: 11163 case llvm::Triple::mips64: 11164 case llvm::Triple::mips64el: 11165 case llvm::Triple::msp430: 11166 case llvm::Triple::r600: 11167 case llvm::Triple::riscv32: 11168 case llvm::Triple::riscv64: 11169 case llvm::Triple::sparc: 11170 case llvm::Triple::sparcv9: 11171 case llvm::Triple::sparcel: 11172 case llvm::Triple::systemz: 11173 case llvm::Triple::tce: 11174 case llvm::Triple::tcele: 11175 case llvm::Triple::thumb: 11176 case llvm::Triple::thumbeb: 11177 case llvm::Triple::xcore: 11178 case llvm::Triple::le32: 11179 case llvm::Triple::le64: 11180 case llvm::Triple::amdil: 11181 case llvm::Triple::amdil64: 11182 case llvm::Triple::hsail: 11183 case llvm::Triple::hsail64: 11184 case llvm::Triple::spir: 11185 case llvm::Triple::spir64: 11186 case llvm::Triple::kalimba: 11187 case llvm::Triple::shave: 11188 case llvm::Triple::lanai: 11189 case llvm::Triple::wasm32: 11190 case llvm::Triple::wasm64: 11191 case llvm::Triple::renderscript32: 11192 case llvm::Triple::renderscript64: 11193 return false; 11194 } 11195 } 11196 return true; 11197 } 11198 11199 bool matchesContext(CodeGenModule &CGM, 11200 const CompleteOMPContextSelectorData &ContextData) { 11201 for (const OMPContextSelectorData &Data : ContextData) { 11202 switch (Data.Ctx) { 11203 case OMP_CTX_vendor: 11204 assert(Data.CtxSet == OMP_CTX_SET_implementation && 11205 "Expected implementation context selector set."); 11206 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data)) 11207 return false; 11208 break; 11209 case OMP_CTX_kind: 11210 assert(Data.CtxSet == OMP_CTX_SET_device && 11211 "Expected device context selector set."); 11212 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data, 11213 CGM)) 11214 return false; 11215 break; 11216 case OMP_CTX_unknown: 11217 llvm_unreachable("Unknown context selector kind."); 11218 } 11219 } 11220 return true; 11221 } 11222 11223 static CompleteOMPContextSelectorData 11224 translateAttrToContextSelectorData(ASTContext &C, 11225 const OMPDeclareVariantAttr *A) { 11226 CompleteOMPContextSelectorData Data; 11227 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) { 11228 Data.emplace_back(); 11229 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( 11230 *std::next(A->ctxSelectorSets_begin(), I)); 11231 auto Ctx = static_cast<OpenMPContextSelectorKind>( 11232 *std::next(A->ctxSelectors_begin(), I)); 11233 Data.back().CtxSet = CtxSet; 11234 Data.back().Ctx = Ctx; 11235 const Expr *Score = *std::next(A->scores_begin(), I); 11236 Data.back().Score = Score->EvaluateKnownConstInt(C); 11237 switch (Ctx) { 11238 case OMP_CTX_vendor: 11239 assert(CtxSet == OMP_CTX_SET_implementation && 11240 "Expected implementation context selector set."); 11241 Data.back().Names = 11242 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end()); 11243 break; 11244 case OMP_CTX_kind: 11245 assert(CtxSet == OMP_CTX_SET_device && 11246 "Expected device context selector set."); 11247 Data.back().Names = 11248 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end()); 11249 break; 11250 case OMP_CTX_unknown: 11251 llvm_unreachable("Unknown context selector kind."); 11252 } 11253 } 11254 return Data; 11255 } 11256 11257 static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS, 11258 const CompleteOMPContextSelectorData &RHS) { 11259 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData; 11260 for (const OMPContextSelectorData &D : RHS) { 11261 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx)); 11262 Pair.getSecond().insert(D.Names.begin(), D.Names.end()); 11263 } 11264 bool AllSetsAreEqual = true; 11265 for (const OMPContextSelectorData &D : LHS) { 11266 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx)); 11267 if (It == RHSData.end()) 11268 return false; 11269 if (D.Names.size() > It->getSecond().size()) 11270 return false; 11271 if (llvm::set_union(It->getSecond(), D.Names)) 11272 return false; 11273 AllSetsAreEqual = 11274 AllSetsAreEqual && (D.Names.size() == It->getSecond().size()); 11275 } 11276 11277 return LHS.size() != RHS.size() || !AllSetsAreEqual; 11278 } 11279 11280 static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS, 11281 const CompleteOMPContextSelectorData &RHS) { 11282 // Score is calculated as sum of all scores + 1. 11283 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11284 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS); 11285 if (RHSIsSubsetOfLHS) { 11286 LHSScore = llvm::APSInt::get(0); 11287 } else { 11288 for (const OMPContextSelectorData &Data : LHS) { 11289 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) { 11290 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11291 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) { 11292 LHSScore += Data.Score.extend(LHSScore.getBitWidth()); 11293 } else { 11294 LHSScore += Data.Score; 11295 } 11296 } 11297 } 11298 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11299 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) { 11300 RHSScore = llvm::APSInt::get(0); 11301 } else { 11302 for (const OMPContextSelectorData &Data : RHS) { 11303 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) { 11304 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11305 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) { 11306 RHSScore += Data.Score.extend(RHSScore.getBitWidth()); 11307 } else { 11308 RHSScore += Data.Score; 11309 } 11310 } 11311 } 11312 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0; 11313 } 11314 11315 /// Finds the variant function that matches current context with its context 11316 /// selector. 11317 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11318 const FunctionDecl *FD) { 11319 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11320 return FD; 11321 // Iterate through all DeclareVariant attributes and check context selectors. 11322 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11323 CompleteOMPContextSelectorData TopMostData; 11324 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11325 CompleteOMPContextSelectorData Data = 11326 translateAttrToContextSelectorData(CGM.getContext(), A); 11327 if (!matchesContext(CGM, Data)) 11328 continue; 11329 // If the attribute matches the context, find the attribute with the highest 11330 // score. 11331 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { 11332 TopMostAttr = A; 11333 TopMostData.swap(Data); 11334 } 11335 } 11336 if (!TopMostAttr) 11337 return FD; 11338 return cast<FunctionDecl>( 11339 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11340 ->getDecl()); 11341 } 11342 11343 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11344 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11345 // If the original function is defined already, use its definition. 11346 StringRef MangledName = CGM.getMangledName(GD); 11347 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11348 if (Orig && !Orig->isDeclaration()) 11349 return false; 11350 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11351 // Emit original function if it does not have declare variant attribute or the 11352 // context does not match. 11353 if (NewFD == D) 11354 return false; 11355 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11356 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11357 DeferredVariantFunction.erase(D); 11358 return true; 11359 } 11360 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11361 return true; 11362 } 11363 11364 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11365 CodeGenModule &CGM, const OMPLoopDirective &S) 11366 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11367 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11368 if (!NeedToPush) 11369 return; 11370 NontemporalDeclsSet &DS = 11371 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11372 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11373 for (const Stmt *Ref : C->private_refs()) { 11374 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11375 const ValueDecl *VD; 11376 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11377 VD = DRE->getDecl(); 11378 } else { 11379 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11380 assert((ME->isImplicitCXXThis() || 11381 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11382 "Expected member of current class."); 11383 VD = ME->getMemberDecl(); 11384 } 11385 DS.insert(VD); 11386 } 11387 } 11388 } 11389 11390 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11391 if (!NeedToPush) 11392 return; 11393 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11394 } 11395 11396 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11397 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11398 11399 return llvm::any_of( 11400 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11401 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11402 } 11403 11404 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11405 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11406 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11407 llvm_unreachable("Not supported in SIMD-only mode"); 11408 } 11409 11410 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11411 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11412 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11413 llvm_unreachable("Not supported in SIMD-only mode"); 11414 } 11415 11416 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11417 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11418 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11419 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11420 bool Tied, unsigned &NumberOfParts) { 11421 llvm_unreachable("Not supported in SIMD-only mode"); 11422 } 11423 11424 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11425 SourceLocation Loc, 11426 llvm::Function *OutlinedFn, 11427 ArrayRef<llvm::Value *> CapturedVars, 11428 const Expr *IfCond) { 11429 llvm_unreachable("Not supported in SIMD-only mode"); 11430 } 11431 11432 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11433 CodeGenFunction &CGF, StringRef CriticalName, 11434 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11435 const Expr *Hint) { 11436 llvm_unreachable("Not supported in SIMD-only mode"); 11437 } 11438 11439 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11440 const RegionCodeGenTy &MasterOpGen, 11441 SourceLocation Loc) { 11442 llvm_unreachable("Not supported in SIMD-only mode"); 11443 } 11444 11445 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11446 SourceLocation Loc) { 11447 llvm_unreachable("Not supported in SIMD-only mode"); 11448 } 11449 11450 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11451 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11452 SourceLocation Loc) { 11453 llvm_unreachable("Not supported in SIMD-only mode"); 11454 } 11455 11456 void CGOpenMPSIMDRuntime::emitSingleRegion( 11457 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11458 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11459 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11460 ArrayRef<const Expr *> AssignmentOps) { 11461 llvm_unreachable("Not supported in SIMD-only mode"); 11462 } 11463 11464 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11465 const RegionCodeGenTy &OrderedOpGen, 11466 SourceLocation Loc, 11467 bool IsThreads) { 11468 llvm_unreachable("Not supported in SIMD-only mode"); 11469 } 11470 11471 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11472 SourceLocation Loc, 11473 OpenMPDirectiveKind Kind, 11474 bool EmitChecks, 11475 bool ForceSimpleCall) { 11476 llvm_unreachable("Not supported in SIMD-only mode"); 11477 } 11478 11479 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11480 CodeGenFunction &CGF, SourceLocation Loc, 11481 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11482 bool Ordered, const DispatchRTInput &DispatchValues) { 11483 llvm_unreachable("Not supported in SIMD-only mode"); 11484 } 11485 11486 void CGOpenMPSIMDRuntime::emitForStaticInit( 11487 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11488 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11489 llvm_unreachable("Not supported in SIMD-only mode"); 11490 } 11491 11492 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11493 CodeGenFunction &CGF, SourceLocation Loc, 11494 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11495 llvm_unreachable("Not supported in SIMD-only mode"); 11496 } 11497 11498 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11499 SourceLocation Loc, 11500 unsigned IVSize, 11501 bool IVSigned) { 11502 llvm_unreachable("Not supported in SIMD-only mode"); 11503 } 11504 11505 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11506 SourceLocation Loc, 11507 OpenMPDirectiveKind DKind) { 11508 llvm_unreachable("Not supported in SIMD-only mode"); 11509 } 11510 11511 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11512 SourceLocation Loc, 11513 unsigned IVSize, bool IVSigned, 11514 Address IL, Address LB, 11515 Address UB, Address ST) { 11516 llvm_unreachable("Not supported in SIMD-only mode"); 11517 } 11518 11519 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11520 llvm::Value *NumThreads, 11521 SourceLocation Loc) { 11522 llvm_unreachable("Not supported in SIMD-only mode"); 11523 } 11524 11525 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11526 ProcBindKind ProcBind, 11527 SourceLocation Loc) { 11528 llvm_unreachable("Not supported in SIMD-only mode"); 11529 } 11530 11531 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11532 const VarDecl *VD, 11533 Address VDAddr, 11534 SourceLocation Loc) { 11535 llvm_unreachable("Not supported in SIMD-only mode"); 11536 } 11537 11538 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11539 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11540 CodeGenFunction *CGF) { 11541 llvm_unreachable("Not supported in SIMD-only mode"); 11542 } 11543 11544 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11545 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11546 llvm_unreachable("Not supported in SIMD-only mode"); 11547 } 11548 11549 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11550 ArrayRef<const Expr *> Vars, 11551 SourceLocation Loc) { 11552 llvm_unreachable("Not supported in SIMD-only mode"); 11553 } 11554 11555 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11556 const OMPExecutableDirective &D, 11557 llvm::Function *TaskFunction, 11558 QualType SharedsTy, Address Shareds, 11559 const Expr *IfCond, 11560 const OMPTaskDataTy &Data) { 11561 llvm_unreachable("Not supported in SIMD-only mode"); 11562 } 11563 11564 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11565 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11566 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11567 const Expr *IfCond, const OMPTaskDataTy &Data) { 11568 llvm_unreachable("Not supported in SIMD-only mode"); 11569 } 11570 11571 void CGOpenMPSIMDRuntime::emitReduction( 11572 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11573 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11574 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11575 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11576 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11577 ReductionOps, Options); 11578 } 11579 11580 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11581 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11582 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11583 llvm_unreachable("Not supported in SIMD-only mode"); 11584 } 11585 11586 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11587 SourceLocation Loc, 11588 ReductionCodeGen &RCG, 11589 unsigned N) { 11590 llvm_unreachable("Not supported in SIMD-only mode"); 11591 } 11592 11593 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11594 SourceLocation Loc, 11595 llvm::Value *ReductionsPtr, 11596 LValue SharedLVal) { 11597 llvm_unreachable("Not supported in SIMD-only mode"); 11598 } 11599 11600 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11601 SourceLocation Loc) { 11602 llvm_unreachable("Not supported in SIMD-only mode"); 11603 } 11604 11605 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11606 CodeGenFunction &CGF, SourceLocation Loc, 11607 OpenMPDirectiveKind CancelRegion) { 11608 llvm_unreachable("Not supported in SIMD-only mode"); 11609 } 11610 11611 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11612 SourceLocation Loc, const Expr *IfCond, 11613 OpenMPDirectiveKind CancelRegion) { 11614 llvm_unreachable("Not supported in SIMD-only mode"); 11615 } 11616 11617 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11618 const OMPExecutableDirective &D, StringRef ParentName, 11619 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11620 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11621 llvm_unreachable("Not supported in SIMD-only mode"); 11622 } 11623 11624 void CGOpenMPSIMDRuntime::emitTargetCall( 11625 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11626 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11627 const Expr *Device, 11628 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11629 const OMPLoopDirective &D)> 11630 SizeEmitter) { 11631 llvm_unreachable("Not supported in SIMD-only mode"); 11632 } 11633 11634 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11635 llvm_unreachable("Not supported in SIMD-only mode"); 11636 } 11637 11638 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11639 llvm_unreachable("Not supported in SIMD-only mode"); 11640 } 11641 11642 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11643 return false; 11644 } 11645 11646 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11647 const OMPExecutableDirective &D, 11648 SourceLocation Loc, 11649 llvm::Function *OutlinedFn, 11650 ArrayRef<llvm::Value *> CapturedVars) { 11651 llvm_unreachable("Not supported in SIMD-only mode"); 11652 } 11653 11654 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11655 const Expr *NumTeams, 11656 const Expr *ThreadLimit, 11657 SourceLocation Loc) { 11658 llvm_unreachable("Not supported in SIMD-only mode"); 11659 } 11660 11661 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11662 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11663 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11664 llvm_unreachable("Not supported in SIMD-only mode"); 11665 } 11666 11667 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11668 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11669 const Expr *Device) { 11670 llvm_unreachable("Not supported in SIMD-only mode"); 11671 } 11672 11673 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11674 const OMPLoopDirective &D, 11675 ArrayRef<Expr *> NumIterations) { 11676 llvm_unreachable("Not supported in SIMD-only mode"); 11677 } 11678 11679 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11680 const OMPDependClause *C) { 11681 llvm_unreachable("Not supported in SIMD-only mode"); 11682 } 11683 11684 const VarDecl * 11685 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11686 const VarDecl *NativeParam) const { 11687 llvm_unreachable("Not supported in SIMD-only mode"); 11688 } 11689 11690 Address 11691 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11692 const VarDecl *NativeParam, 11693 const VarDecl *TargetParam) const { 11694 llvm_unreachable("Not supported in SIMD-only mode"); 11695 } 11696