1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This provides a class for OpenMP runtime code generation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGOpenMPRuntime.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/Decl.h" 19 #include "clang/AST/StmtOpenMP.h" 20 #include "llvm/ADT/ArrayRef.h" 21 #include "llvm/Bitcode/ReaderWriter.h" 22 #include "llvm/IR/CallSite.h" 23 #include "llvm/IR/DerivedTypes.h" 24 #include "llvm/IR/GlobalValue.h" 25 #include "llvm/IR/Value.h" 26 #include "llvm/Support/Format.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include <cassert> 29 30 using namespace clang; 31 using namespace CodeGen; 32 33 namespace { 34 /// \brief Base class for handling code generation inside OpenMP regions. 35 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 36 public: 37 /// \brief Kinds of OpenMP regions used in codegen. 38 enum CGOpenMPRegionKind { 39 /// \brief Region with outlined function for standalone 'parallel' 40 /// directive. 41 ParallelOutlinedRegion, 42 /// \brief Region with outlined function for standalone 'task' directive. 43 TaskOutlinedRegion, 44 /// \brief Region for constructs that do not require function outlining, 45 /// like 'for', 'sections', 'atomic' etc. directives. 46 InlinedRegion, 47 /// \brief Region with outlined function for standalone 'target' directive. 48 TargetRegion, 49 }; 50 51 CGOpenMPRegionInfo(const CapturedStmt &CS, 52 const CGOpenMPRegionKind RegionKind, 53 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 54 bool HasCancel) 55 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 56 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 57 58 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 59 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 60 bool HasCancel) 61 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 62 Kind(Kind), HasCancel(HasCancel) {} 63 64 /// \brief Get a variable or parameter for storing global thread id 65 /// inside OpenMP construct. 66 virtual const VarDecl *getThreadIDVariable() const = 0; 67 68 /// \brief Emit the captured statement body. 69 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 70 71 /// \brief Get an LValue for the current ThreadID variable. 72 /// \return LValue for thread id variable. This LValue always has type int32*. 73 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 74 75 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 76 77 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 78 79 bool hasCancel() const { return HasCancel; } 80 81 static bool classof(const CGCapturedStmtInfo *Info) { 82 return Info->getKind() == CR_OpenMP; 83 } 84 85 protected: 86 CGOpenMPRegionKind RegionKind; 87 RegionCodeGenTy CodeGen; 88 OpenMPDirectiveKind Kind; 89 bool HasCancel; 90 }; 91 92 /// \brief API for captured statement code generation in OpenMP constructs. 93 class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo { 94 public: 95 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 96 const RegionCodeGenTy &CodeGen, 97 OpenMPDirectiveKind Kind, bool HasCancel) 98 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 99 HasCancel), 100 ThreadIDVar(ThreadIDVar) { 101 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 102 } 103 104 /// \brief Get a variable or parameter for storing global thread id 105 /// inside OpenMP construct. 106 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 107 108 /// \brief Get the name of the capture helper. 109 StringRef getHelperName() const override { return ".omp_outlined."; } 110 111 static bool classof(const CGCapturedStmtInfo *Info) { 112 return CGOpenMPRegionInfo::classof(Info) && 113 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 114 ParallelOutlinedRegion; 115 } 116 117 private: 118 /// \brief A variable or parameter storing global thread id for OpenMP 119 /// constructs. 120 const VarDecl *ThreadIDVar; 121 }; 122 123 /// \brief API for captured statement code generation in OpenMP constructs. 124 class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo { 125 public: 126 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 127 const VarDecl *ThreadIDVar, 128 const RegionCodeGenTy &CodeGen, 129 OpenMPDirectiveKind Kind, bool HasCancel) 130 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 131 ThreadIDVar(ThreadIDVar) { 132 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 133 } 134 135 /// \brief Get a variable or parameter for storing global thread id 136 /// inside OpenMP construct. 137 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 138 139 /// \brief Get an LValue for the current ThreadID variable. 140 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 141 142 /// \brief Get the name of the capture helper. 143 StringRef getHelperName() const override { return ".omp_outlined."; } 144 145 static bool classof(const CGCapturedStmtInfo *Info) { 146 return CGOpenMPRegionInfo::classof(Info) && 147 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 148 TaskOutlinedRegion; 149 } 150 151 private: 152 /// \brief A variable or parameter storing global thread id for OpenMP 153 /// constructs. 154 const VarDecl *ThreadIDVar; 155 }; 156 157 /// \brief API for inlined captured statement code generation in OpenMP 158 /// constructs. 159 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 160 public: 161 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 162 const RegionCodeGenTy &CodeGen, 163 OpenMPDirectiveKind Kind, bool HasCancel) 164 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 165 OldCSI(OldCSI), 166 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 167 168 // \brief Retrieve the value of the context parameter. 169 llvm::Value *getContextValue() const override { 170 if (OuterRegionInfo) 171 return OuterRegionInfo->getContextValue(); 172 llvm_unreachable("No context value for inlined OpenMP region"); 173 } 174 175 void setContextValue(llvm::Value *V) override { 176 if (OuterRegionInfo) { 177 OuterRegionInfo->setContextValue(V); 178 return; 179 } 180 llvm_unreachable("No context value for inlined OpenMP region"); 181 } 182 183 /// \brief Lookup the captured field decl for a variable. 184 const FieldDecl *lookup(const VarDecl *VD) const override { 185 if (OuterRegionInfo) 186 return OuterRegionInfo->lookup(VD); 187 // If there is no outer outlined region,no need to lookup in a list of 188 // captured variables, we can use the original one. 189 return nullptr; 190 } 191 192 FieldDecl *getThisFieldDecl() const override { 193 if (OuterRegionInfo) 194 return OuterRegionInfo->getThisFieldDecl(); 195 return nullptr; 196 } 197 198 /// \brief Get a variable or parameter for storing global thread id 199 /// inside OpenMP construct. 200 const VarDecl *getThreadIDVariable() const override { 201 if (OuterRegionInfo) 202 return OuterRegionInfo->getThreadIDVariable(); 203 return nullptr; 204 } 205 206 /// \brief Get the name of the capture helper. 207 StringRef getHelperName() const override { 208 if (auto *OuterRegionInfo = getOldCSI()) 209 return OuterRegionInfo->getHelperName(); 210 llvm_unreachable("No helper name for inlined OpenMP construct"); 211 } 212 213 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 214 215 static bool classof(const CGCapturedStmtInfo *Info) { 216 return CGOpenMPRegionInfo::classof(Info) && 217 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 218 } 219 220 private: 221 /// \brief CodeGen info about outer OpenMP region. 222 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 223 CGOpenMPRegionInfo *OuterRegionInfo; 224 }; 225 226 /// \brief API for captured statement code generation in OpenMP target 227 /// constructs. For this captures, implicit parameters are used instead of the 228 /// captured fields. The name of the target region has to be unique in a given 229 /// application so it is provided by the client, because only the client has 230 /// the information to generate that. 231 class CGOpenMPTargetRegionInfo : public CGOpenMPRegionInfo { 232 public: 233 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 234 const RegionCodeGenTy &CodeGen, StringRef HelperName) 235 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 236 /*HasCancel=*/false), 237 HelperName(HelperName) {} 238 239 /// \brief This is unused for target regions because each starts executing 240 /// with a single thread. 241 const VarDecl *getThreadIDVariable() const override { return nullptr; } 242 243 /// \brief Get the name of the capture helper. 244 StringRef getHelperName() const override { return HelperName; } 245 246 static bool classof(const CGCapturedStmtInfo *Info) { 247 return CGOpenMPRegionInfo::classof(Info) && 248 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 249 } 250 251 private: 252 StringRef HelperName; 253 }; 254 255 /// \brief RAII for emitting code of OpenMP constructs. 256 class InlinedOpenMPRegionRAII { 257 CodeGenFunction &CGF; 258 259 public: 260 /// \brief Constructs region for combined constructs. 261 /// \param CodeGen Code generation sequence for combined directives. Includes 262 /// a list of functions used for code generation of implicitly inlined 263 /// regions. 264 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 265 OpenMPDirectiveKind Kind, bool HasCancel) 266 : CGF(CGF) { 267 // Start emission for the construct. 268 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 269 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 270 } 271 272 ~InlinedOpenMPRegionRAII() { 273 // Restore original CapturedStmtInfo only if we're done with code emission. 274 auto *OldCSI = 275 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 276 delete CGF.CapturedStmtInfo; 277 CGF.CapturedStmtInfo = OldCSI; 278 } 279 }; 280 281 /// \brief Values for bit flags used in the ident_t to describe the fields. 282 /// All enumeric elements are named and described in accordance with the code 283 /// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h 284 enum OpenMPLocationFlags { 285 /// \brief Use trampoline for internal microtask. 286 OMP_IDENT_IMD = 0x01, 287 /// \brief Use c-style ident structure. 288 OMP_IDENT_KMPC = 0x02, 289 /// \brief Atomic reduction option for kmpc_reduce. 290 OMP_ATOMIC_REDUCE = 0x10, 291 /// \brief Explicit 'barrier' directive. 292 OMP_IDENT_BARRIER_EXPL = 0x20, 293 /// \brief Implicit barrier in code. 294 OMP_IDENT_BARRIER_IMPL = 0x40, 295 /// \brief Implicit barrier in 'for' directive. 296 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 297 /// \brief Implicit barrier in 'sections' directive. 298 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 299 /// \brief Implicit barrier in 'single' directive. 300 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140 301 }; 302 303 /// \brief Describes ident structure that describes a source location. 304 /// All descriptions are taken from 305 /// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h 306 /// Original structure: 307 /// typedef struct ident { 308 /// kmp_int32 reserved_1; /**< might be used in Fortran; 309 /// see above */ 310 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 311 /// KMP_IDENT_KMPC identifies this union 312 /// member */ 313 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 314 /// see above */ 315 ///#if USE_ITT_BUILD 316 /// /* but currently used for storing 317 /// region-specific ITT */ 318 /// /* contextual information. */ 319 ///#endif /* USE_ITT_BUILD */ 320 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 321 /// C++ */ 322 /// char const *psource; /**< String describing the source location. 323 /// The string is composed of semi-colon separated 324 // fields which describe the source file, 325 /// the function and a pair of line numbers that 326 /// delimit the construct. 327 /// */ 328 /// } ident_t; 329 enum IdentFieldIndex { 330 /// \brief might be used in Fortran 331 IdentField_Reserved_1, 332 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 333 IdentField_Flags, 334 /// \brief Not really used in Fortran any more 335 IdentField_Reserved_2, 336 /// \brief Source[4] in Fortran, do not use for C++ 337 IdentField_Reserved_3, 338 /// \brief String describing the source location. The string is composed of 339 /// semi-colon separated fields which describe the source file, the function 340 /// and a pair of line numbers that delimit the construct. 341 IdentField_PSource 342 }; 343 344 /// \brief Schedule types for 'omp for' loops (these enumerators are taken from 345 /// the enum sched_type in kmp.h). 346 enum OpenMPSchedType { 347 /// \brief Lower bound for default (unordered) versions. 348 OMP_sch_lower = 32, 349 OMP_sch_static_chunked = 33, 350 OMP_sch_static = 34, 351 OMP_sch_dynamic_chunked = 35, 352 OMP_sch_guided_chunked = 36, 353 OMP_sch_runtime = 37, 354 OMP_sch_auto = 38, 355 /// \brief Lower bound for 'ordered' versions. 356 OMP_ord_lower = 64, 357 OMP_ord_static_chunked = 65, 358 OMP_ord_static = 66, 359 OMP_ord_dynamic_chunked = 67, 360 OMP_ord_guided_chunked = 68, 361 OMP_ord_runtime = 69, 362 OMP_ord_auto = 70, 363 OMP_sch_default = OMP_sch_static, 364 }; 365 366 enum OpenMPRTLFunction { 367 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 368 /// kmpc_micro microtask, ...); 369 OMPRTL__kmpc_fork_call, 370 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc, 371 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 372 OMPRTL__kmpc_threadprivate_cached, 373 /// \brief Call to void __kmpc_threadprivate_register( ident_t *, 374 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 375 OMPRTL__kmpc_threadprivate_register, 376 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 377 OMPRTL__kmpc_global_thread_num, 378 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 379 // kmp_critical_name *crit); 380 OMPRTL__kmpc_critical, 381 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 382 // global_tid, kmp_critical_name *crit, uintptr_t hint); 383 OMPRTL__kmpc_critical_with_hint, 384 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 385 // kmp_critical_name *crit); 386 OMPRTL__kmpc_end_critical, 387 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 388 // global_tid); 389 OMPRTL__kmpc_cancel_barrier, 390 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 391 OMPRTL__kmpc_barrier, 392 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 393 OMPRTL__kmpc_for_static_fini, 394 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 395 // global_tid); 396 OMPRTL__kmpc_serialized_parallel, 397 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 398 // global_tid); 399 OMPRTL__kmpc_end_serialized_parallel, 400 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 401 // kmp_int32 num_threads); 402 OMPRTL__kmpc_push_num_threads, 403 // Call to void __kmpc_flush(ident_t *loc); 404 OMPRTL__kmpc_flush, 405 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 406 OMPRTL__kmpc_master, 407 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 408 OMPRTL__kmpc_end_master, 409 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 410 // int end_part); 411 OMPRTL__kmpc_omp_taskyield, 412 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 413 OMPRTL__kmpc_single, 414 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 415 OMPRTL__kmpc_end_single, 416 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 417 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 418 // kmp_routine_entry_t *task_entry); 419 OMPRTL__kmpc_omp_task_alloc, 420 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 421 // new_task); 422 OMPRTL__kmpc_omp_task, 423 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 424 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 425 // kmp_int32 didit); 426 OMPRTL__kmpc_copyprivate, 427 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 428 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 429 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 430 OMPRTL__kmpc_reduce, 431 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 432 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 433 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 434 // *lck); 435 OMPRTL__kmpc_reduce_nowait, 436 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 437 // kmp_critical_name *lck); 438 OMPRTL__kmpc_end_reduce, 439 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 440 // kmp_critical_name *lck); 441 OMPRTL__kmpc_end_reduce_nowait, 442 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 443 // kmp_task_t * new_task); 444 OMPRTL__kmpc_omp_task_begin_if0, 445 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 446 // kmp_task_t * new_task); 447 OMPRTL__kmpc_omp_task_complete_if0, 448 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 449 OMPRTL__kmpc_ordered, 450 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 451 OMPRTL__kmpc_end_ordered, 452 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 453 // global_tid); 454 OMPRTL__kmpc_omp_taskwait, 455 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 456 OMPRTL__kmpc_taskgroup, 457 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 458 OMPRTL__kmpc_end_taskgroup, 459 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 460 // int proc_bind); 461 OMPRTL__kmpc_push_proc_bind, 462 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 463 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 464 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 465 OMPRTL__kmpc_omp_task_with_deps, 466 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 467 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 468 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 469 OMPRTL__kmpc_omp_wait_deps, 470 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 471 // global_tid, kmp_int32 cncl_kind); 472 OMPRTL__kmpc_cancellationpoint, 473 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 474 // kmp_int32 cncl_kind); 475 OMPRTL__kmpc_cancel, 476 477 // 478 // Offloading related calls 479 // 480 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t 481 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t 482 // *arg_types); 483 OMPRTL__tgt_target, 484 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 485 OMPRTL__tgt_register_lib, 486 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 487 OMPRTL__tgt_unregister_lib, 488 }; 489 490 } // anonymous namespace 491 492 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 493 return CGF.EmitLoadOfPointerLValue( 494 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 495 getThreadIDVariable()->getType()->castAs<PointerType>()); 496 } 497 498 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 499 if (!CGF.HaveInsertPoint()) 500 return; 501 // 1.2.2 OpenMP Language Terminology 502 // Structured block - An executable statement with a single entry at the 503 // top and a single exit at the bottom. 504 // The point of exit cannot be a branch out of the structured block. 505 // longjmp() and throw() must not violate the entry/exit criteria. 506 CGF.EHStack.pushTerminate(); 507 { 508 CodeGenFunction::RunCleanupsScope Scope(CGF); 509 CodeGen(CGF); 510 } 511 CGF.EHStack.popTerminate(); 512 } 513 514 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 515 CodeGenFunction &CGF) { 516 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 517 getThreadIDVariable()->getType(), 518 AlignmentSource::Decl); 519 } 520 521 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) 522 : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr), 523 OffloadEntriesInfoManager(CGM) { 524 IdentTy = llvm::StructType::create( 525 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, 526 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, 527 CGM.Int8PtrTy /* psource */, nullptr); 528 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 529 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 530 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 531 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 532 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 533 534 loadOffloadInfoMetadata(); 535 } 536 537 void CGOpenMPRuntime::clear() { 538 InternalVars.clear(); 539 } 540 541 // Layout information for ident_t. 542 static CharUnits getIdentAlign(CodeGenModule &CGM) { 543 return CGM.getPointerAlign(); 544 } 545 static CharUnits getIdentSize(CodeGenModule &CGM) { 546 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign())); 547 return CharUnits::fromQuantity(16) + CGM.getPointerSize(); 548 } 549 static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) { 550 // All the fields except the last are i32, so this works beautifully. 551 return unsigned(Field) * CharUnits::fromQuantity(4); 552 } 553 static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr, 554 IdentFieldIndex Field, 555 const llvm::Twine &Name = "") { 556 auto Offset = getOffsetOfIdentField(Field); 557 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name); 558 } 559 560 llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction( 561 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 562 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 563 assert(ThreadIDVar->getType()->isPointerType() && 564 "thread id variable must be of type kmp_int32 *"); 565 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 566 CodeGenFunction CGF(CGM, true); 567 bool HasCancel = false; 568 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 569 HasCancel = OPD->hasCancel(); 570 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 571 HasCancel = OPSD->hasCancel(); 572 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 573 HasCancel = OPFD->hasCancel(); 574 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 575 HasCancel); 576 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 577 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 578 } 579 580 llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction( 581 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 582 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 583 assert(!ThreadIDVar->getType()->isPointerType() && 584 "thread id variable must be of type kmp_int32 for tasks"); 585 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 586 CodeGenFunction CGF(CGM, true); 587 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 588 InnermostKind, 589 cast<OMPTaskDirective>(D).hasCancel()); 590 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 591 return CGF.GenerateCapturedStmtFunction(*CS); 592 } 593 594 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 595 CharUnits Align = getIdentAlign(CGM); 596 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags); 597 if (!Entry) { 598 if (!DefaultOpenMPPSource) { 599 // Initialize default location for psource field of ident_t structure of 600 // all ident_t objects. Format is ";file;function;line;column;;". 601 // Taken from 602 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c 603 DefaultOpenMPPSource = 604 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 605 DefaultOpenMPPSource = 606 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 607 } 608 auto DefaultOpenMPLocation = new llvm::GlobalVariable( 609 CGM.getModule(), IdentTy, /*isConstant*/ true, 610 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr); 611 DefaultOpenMPLocation->setUnnamedAddr(true); 612 DefaultOpenMPLocation->setAlignment(Align.getQuantity()); 613 614 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true); 615 llvm::Constant *Values[] = {Zero, 616 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 617 Zero, Zero, DefaultOpenMPPSource}; 618 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values); 619 DefaultOpenMPLocation->setInitializer(Init); 620 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation; 621 } 622 return Address(Entry, Align); 623 } 624 625 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 626 SourceLocation Loc, 627 unsigned Flags) { 628 Flags |= OMP_IDENT_KMPC; 629 // If no debug info is generated - return global default location. 630 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 631 Loc.isInvalid()) 632 return getOrCreateDefaultLocation(Flags).getPointer(); 633 634 assert(CGF.CurFn && "No function in current CodeGenFunction."); 635 636 Address LocValue = Address::invalid(); 637 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 638 if (I != OpenMPLocThreadIDMap.end()) 639 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM)); 640 641 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 642 // GetOpenMPThreadID was called before this routine. 643 if (!LocValue.isValid()) { 644 // Generate "ident_t .kmpc_loc.addr;" 645 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM), 646 ".kmpc_loc.addr"); 647 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 648 Elem.second.DebugLoc = AI.getPointer(); 649 LocValue = AI; 650 651 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 652 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 653 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 654 CGM.getSize(getIdentSize(CGF.CGM))); 655 } 656 657 // char **psource = &.kmpc_loc_<flags>.addr.psource; 658 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource); 659 660 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 661 if (OMPDebugLoc == nullptr) { 662 SmallString<128> Buffer2; 663 llvm::raw_svector_ostream OS2(Buffer2); 664 // Build debug location 665 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 666 OS2 << ";" << PLoc.getFilename() << ";"; 667 if (const FunctionDecl *FD = 668 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) { 669 OS2 << FD->getQualifiedNameAsString(); 670 } 671 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 672 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 673 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 674 } 675 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 676 CGF.Builder.CreateStore(OMPDebugLoc, PSource); 677 678 // Our callers always pass this to a runtime function, so for 679 // convenience, go ahead and return a naked pointer. 680 return LocValue.getPointer(); 681 } 682 683 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 684 SourceLocation Loc) { 685 assert(CGF.CurFn && "No function in current CodeGenFunction."); 686 687 llvm::Value *ThreadID = nullptr; 688 // Check whether we've already cached a load of the thread id in this 689 // function. 690 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 691 if (I != OpenMPLocThreadIDMap.end()) { 692 ThreadID = I->second.ThreadID; 693 if (ThreadID != nullptr) 694 return ThreadID; 695 } 696 if (auto *OMPRegionInfo = 697 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 698 if (OMPRegionInfo->getThreadIDVariable()) { 699 // Check if this an outlined function with thread id passed as argument. 700 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 701 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal(); 702 // If value loaded in entry block, cache it and use it everywhere in 703 // function. 704 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 705 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 706 Elem.second.ThreadID = ThreadID; 707 } 708 return ThreadID; 709 } 710 } 711 712 // This is not an outlined function region - need to call __kmpc_int32 713 // kmpc_global_thread_num(ident_t *loc). 714 // Generate thread id value and cache this value for use across the 715 // function. 716 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 717 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 718 ThreadID = 719 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 720 emitUpdateLocation(CGF, Loc)); 721 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 722 Elem.second.ThreadID = ThreadID; 723 return ThreadID; 724 } 725 726 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 727 assert(CGF.CurFn && "No function in current CodeGenFunction."); 728 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) 729 OpenMPLocThreadIDMap.erase(CGF.CurFn); 730 } 731 732 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 733 return llvm::PointerType::getUnqual(IdentTy); 734 } 735 736 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 737 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 738 } 739 740 llvm::Constant * 741 CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 742 llvm::Constant *RTLFn = nullptr; 743 switch (static_cast<OpenMPRTLFunction>(Function)) { 744 case OMPRTL__kmpc_fork_call: { 745 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 746 // microtask, ...); 747 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 748 getKmpc_MicroPointerTy()}; 749 llvm::FunctionType *FnTy = 750 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 751 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 752 break; 753 } 754 case OMPRTL__kmpc_global_thread_num: { 755 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 756 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 757 llvm::FunctionType *FnTy = 758 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 759 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 760 break; 761 } 762 case OMPRTL__kmpc_threadprivate_cached: { 763 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 764 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 765 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 766 CGM.VoidPtrTy, CGM.SizeTy, 767 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 768 llvm::FunctionType *FnTy = 769 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 770 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 771 break; 772 } 773 case OMPRTL__kmpc_critical: { 774 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 775 // kmp_critical_name *crit); 776 llvm::Type *TypeParams[] = { 777 getIdentTyPointerTy(), CGM.Int32Ty, 778 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 779 llvm::FunctionType *FnTy = 780 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 781 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 782 break; 783 } 784 case OMPRTL__kmpc_critical_with_hint: { 785 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 786 // kmp_critical_name *crit, uintptr_t hint); 787 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 788 llvm::PointerType::getUnqual(KmpCriticalNameTy), 789 CGM.IntPtrTy}; 790 llvm::FunctionType *FnTy = 791 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 792 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 793 break; 794 } 795 case OMPRTL__kmpc_threadprivate_register: { 796 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 797 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 798 // typedef void *(*kmpc_ctor)(void *); 799 auto KmpcCtorTy = 800 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 801 /*isVarArg*/ false)->getPointerTo(); 802 // typedef void *(*kmpc_cctor)(void *, void *); 803 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 804 auto KmpcCopyCtorTy = 805 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 806 /*isVarArg*/ false)->getPointerTo(); 807 // typedef void (*kmpc_dtor)(void *); 808 auto KmpcDtorTy = 809 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 810 ->getPointerTo(); 811 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 812 KmpcCopyCtorTy, KmpcDtorTy}; 813 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 814 /*isVarArg*/ false); 815 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 816 break; 817 } 818 case OMPRTL__kmpc_end_critical: { 819 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 820 // kmp_critical_name *crit); 821 llvm::Type *TypeParams[] = { 822 getIdentTyPointerTy(), CGM.Int32Ty, 823 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 824 llvm::FunctionType *FnTy = 825 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 826 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 827 break; 828 } 829 case OMPRTL__kmpc_cancel_barrier: { 830 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 831 // global_tid); 832 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 833 llvm::FunctionType *FnTy = 834 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 835 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 836 break; 837 } 838 case OMPRTL__kmpc_barrier: { 839 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 840 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 841 llvm::FunctionType *FnTy = 842 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 843 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 844 break; 845 } 846 case OMPRTL__kmpc_for_static_fini: { 847 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 848 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 849 llvm::FunctionType *FnTy = 850 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 851 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 852 break; 853 } 854 case OMPRTL__kmpc_push_num_threads: { 855 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 856 // kmp_int32 num_threads) 857 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 858 CGM.Int32Ty}; 859 llvm::FunctionType *FnTy = 860 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 861 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 862 break; 863 } 864 case OMPRTL__kmpc_serialized_parallel: { 865 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 866 // global_tid); 867 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 868 llvm::FunctionType *FnTy = 869 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 870 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 871 break; 872 } 873 case OMPRTL__kmpc_end_serialized_parallel: { 874 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 875 // global_tid); 876 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 877 llvm::FunctionType *FnTy = 878 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 879 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 880 break; 881 } 882 case OMPRTL__kmpc_flush: { 883 // Build void __kmpc_flush(ident_t *loc); 884 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 885 llvm::FunctionType *FnTy = 886 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 887 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 888 break; 889 } 890 case OMPRTL__kmpc_master: { 891 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 892 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 893 llvm::FunctionType *FnTy = 894 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 895 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 896 break; 897 } 898 case OMPRTL__kmpc_end_master: { 899 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 900 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 901 llvm::FunctionType *FnTy = 902 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 903 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 904 break; 905 } 906 case OMPRTL__kmpc_omp_taskyield: { 907 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 908 // int end_part); 909 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 910 llvm::FunctionType *FnTy = 911 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 912 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 913 break; 914 } 915 case OMPRTL__kmpc_single: { 916 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 917 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 918 llvm::FunctionType *FnTy = 919 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 920 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 921 break; 922 } 923 case OMPRTL__kmpc_end_single: { 924 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 925 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 926 llvm::FunctionType *FnTy = 927 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 928 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 929 break; 930 } 931 case OMPRTL__kmpc_omp_task_alloc: { 932 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 933 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 934 // kmp_routine_entry_t *task_entry); 935 assert(KmpRoutineEntryPtrTy != nullptr && 936 "Type kmp_routine_entry_t must be created."); 937 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 938 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 939 // Return void * and then cast to particular kmp_task_t type. 940 llvm::FunctionType *FnTy = 941 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 942 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 943 break; 944 } 945 case OMPRTL__kmpc_omp_task: { 946 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 947 // *new_task); 948 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 949 CGM.VoidPtrTy}; 950 llvm::FunctionType *FnTy = 951 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 952 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 953 break; 954 } 955 case OMPRTL__kmpc_copyprivate: { 956 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 957 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 958 // kmp_int32 didit); 959 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 960 auto *CpyFnTy = 961 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 962 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 963 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 964 CGM.Int32Ty}; 965 llvm::FunctionType *FnTy = 966 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 967 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 968 break; 969 } 970 case OMPRTL__kmpc_reduce: { 971 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 972 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 973 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 974 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 975 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 976 /*isVarArg=*/false); 977 llvm::Type *TypeParams[] = { 978 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 979 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 980 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 981 llvm::FunctionType *FnTy = 982 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 983 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 984 break; 985 } 986 case OMPRTL__kmpc_reduce_nowait: { 987 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 988 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 989 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 990 // *lck); 991 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 992 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 993 /*isVarArg=*/false); 994 llvm::Type *TypeParams[] = { 995 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 996 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 997 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 998 llvm::FunctionType *FnTy = 999 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1000 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 1001 break; 1002 } 1003 case OMPRTL__kmpc_end_reduce: { 1004 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 1005 // kmp_critical_name *lck); 1006 llvm::Type *TypeParams[] = { 1007 getIdentTyPointerTy(), CGM.Int32Ty, 1008 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1009 llvm::FunctionType *FnTy = 1010 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1011 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 1012 break; 1013 } 1014 case OMPRTL__kmpc_end_reduce_nowait: { 1015 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 1016 // kmp_critical_name *lck); 1017 llvm::Type *TypeParams[] = { 1018 getIdentTyPointerTy(), CGM.Int32Ty, 1019 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1020 llvm::FunctionType *FnTy = 1021 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1022 RTLFn = 1023 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 1024 break; 1025 } 1026 case OMPRTL__kmpc_omp_task_begin_if0: { 1027 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1028 // *new_task); 1029 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1030 CGM.VoidPtrTy}; 1031 llvm::FunctionType *FnTy = 1032 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1033 RTLFn = 1034 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 1035 break; 1036 } 1037 case OMPRTL__kmpc_omp_task_complete_if0: { 1038 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1039 // *new_task); 1040 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1041 CGM.VoidPtrTy}; 1042 llvm::FunctionType *FnTy = 1043 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1044 RTLFn = CGM.CreateRuntimeFunction(FnTy, 1045 /*Name=*/"__kmpc_omp_task_complete_if0"); 1046 break; 1047 } 1048 case OMPRTL__kmpc_ordered: { 1049 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 1050 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1051 llvm::FunctionType *FnTy = 1052 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1053 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 1054 break; 1055 } 1056 case OMPRTL__kmpc_end_ordered: { 1057 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 1058 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1059 llvm::FunctionType *FnTy = 1060 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1061 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 1062 break; 1063 } 1064 case OMPRTL__kmpc_omp_taskwait: { 1065 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 1066 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1067 llvm::FunctionType *FnTy = 1068 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1069 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 1070 break; 1071 } 1072 case OMPRTL__kmpc_taskgroup: { 1073 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 1074 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1075 llvm::FunctionType *FnTy = 1076 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1077 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 1078 break; 1079 } 1080 case OMPRTL__kmpc_end_taskgroup: { 1081 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 1082 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1083 llvm::FunctionType *FnTy = 1084 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1085 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 1086 break; 1087 } 1088 case OMPRTL__kmpc_push_proc_bind: { 1089 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 1090 // int proc_bind) 1091 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1092 llvm::FunctionType *FnTy = 1093 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1094 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 1095 break; 1096 } 1097 case OMPRTL__kmpc_omp_task_with_deps: { 1098 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 1099 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 1100 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 1101 llvm::Type *TypeParams[] = { 1102 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 1103 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 1104 llvm::FunctionType *FnTy = 1105 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1106 RTLFn = 1107 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 1108 break; 1109 } 1110 case OMPRTL__kmpc_omp_wait_deps: { 1111 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 1112 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 1113 // kmp_depend_info_t *noalias_dep_list); 1114 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1115 CGM.Int32Ty, CGM.VoidPtrTy, 1116 CGM.Int32Ty, CGM.VoidPtrTy}; 1117 llvm::FunctionType *FnTy = 1118 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1119 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 1120 break; 1121 } 1122 case OMPRTL__kmpc_cancellationpoint: { 1123 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 1124 // global_tid, kmp_int32 cncl_kind) 1125 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1126 llvm::FunctionType *FnTy = 1127 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1128 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 1129 break; 1130 } 1131 case OMPRTL__kmpc_cancel: { 1132 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 1133 // kmp_int32 cncl_kind) 1134 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1135 llvm::FunctionType *FnTy = 1136 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1137 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 1138 break; 1139 } 1140 case OMPRTL__tgt_target: { 1141 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t 1142 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t 1143 // *arg_types); 1144 llvm::Type *TypeParams[] = {CGM.Int32Ty, 1145 CGM.VoidPtrTy, 1146 CGM.Int32Ty, 1147 CGM.VoidPtrPtrTy, 1148 CGM.VoidPtrPtrTy, 1149 CGM.SizeTy->getPointerTo(), 1150 CGM.Int32Ty->getPointerTo()}; 1151 llvm::FunctionType *FnTy = 1152 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1153 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 1154 break; 1155 } 1156 case OMPRTL__tgt_register_lib: { 1157 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 1158 QualType ParamTy = 1159 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 1160 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 1161 llvm::FunctionType *FnTy = 1162 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1163 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 1164 break; 1165 } 1166 case OMPRTL__tgt_unregister_lib: { 1167 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 1168 QualType ParamTy = 1169 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 1170 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 1171 llvm::FunctionType *FnTy = 1172 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1173 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 1174 break; 1175 } 1176 } 1177 assert(RTLFn && "Unable to find OpenMP runtime function"); 1178 return RTLFn; 1179 } 1180 1181 llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, 1182 bool IVSigned) { 1183 assert((IVSize == 32 || IVSize == 64) && 1184 "IV size is not compatible with the omp runtime"); 1185 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1186 : "__kmpc_for_static_init_4u") 1187 : (IVSigned ? "__kmpc_for_static_init_8" 1188 : "__kmpc_for_static_init_8u"); 1189 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1190 auto PtrTy = llvm::PointerType::getUnqual(ITy); 1191 llvm::Type *TypeParams[] = { 1192 getIdentTyPointerTy(), // loc 1193 CGM.Int32Ty, // tid 1194 CGM.Int32Ty, // schedtype 1195 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1196 PtrTy, // p_lower 1197 PtrTy, // p_upper 1198 PtrTy, // p_stride 1199 ITy, // incr 1200 ITy // chunk 1201 }; 1202 llvm::FunctionType *FnTy = 1203 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1204 return CGM.CreateRuntimeFunction(FnTy, Name); 1205 } 1206 1207 llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, 1208 bool IVSigned) { 1209 assert((IVSize == 32 || IVSize == 64) && 1210 "IV size is not compatible with the omp runtime"); 1211 auto Name = 1212 IVSize == 32 1213 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1214 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1215 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1216 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1217 CGM.Int32Ty, // tid 1218 CGM.Int32Ty, // schedtype 1219 ITy, // lower 1220 ITy, // upper 1221 ITy, // stride 1222 ITy // chunk 1223 }; 1224 llvm::FunctionType *FnTy = 1225 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1226 return CGM.CreateRuntimeFunction(FnTy, Name); 1227 } 1228 1229 llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, 1230 bool IVSigned) { 1231 assert((IVSize == 32 || IVSize == 64) && 1232 "IV size is not compatible with the omp runtime"); 1233 auto Name = 1234 IVSize == 32 1235 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1236 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1237 llvm::Type *TypeParams[] = { 1238 getIdentTyPointerTy(), // loc 1239 CGM.Int32Ty, // tid 1240 }; 1241 llvm::FunctionType *FnTy = 1242 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1243 return CGM.CreateRuntimeFunction(FnTy, Name); 1244 } 1245 1246 llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, 1247 bool IVSigned) { 1248 assert((IVSize == 32 || IVSize == 64) && 1249 "IV size is not compatible with the omp runtime"); 1250 auto Name = 1251 IVSize == 32 1252 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1253 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1254 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1255 auto PtrTy = llvm::PointerType::getUnqual(ITy); 1256 llvm::Type *TypeParams[] = { 1257 getIdentTyPointerTy(), // loc 1258 CGM.Int32Ty, // tid 1259 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1260 PtrTy, // p_lower 1261 PtrTy, // p_upper 1262 PtrTy // p_stride 1263 }; 1264 llvm::FunctionType *FnTy = 1265 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1266 return CGM.CreateRuntimeFunction(FnTy, Name); 1267 } 1268 1269 llvm::Constant * 1270 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1271 assert(!CGM.getLangOpts().OpenMPUseTLS || 1272 !CGM.getContext().getTargetInfo().isTLSSupported()); 1273 // Lookup the entry, lazily creating it if necessary. 1274 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy, 1275 Twine(CGM.getMangledName(VD)) + ".cache."); 1276 } 1277 1278 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1279 const VarDecl *VD, 1280 Address VDAddr, 1281 SourceLocation Loc) { 1282 if (CGM.getLangOpts().OpenMPUseTLS && 1283 CGM.getContext().getTargetInfo().isTLSSupported()) 1284 return VDAddr; 1285 1286 auto VarTy = VDAddr.getElementType(); 1287 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1288 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1289 CGM.Int8PtrTy), 1290 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1291 getOrCreateThreadPrivateCache(VD)}; 1292 return Address(CGF.EmitRuntimeCall( 1293 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 1294 VDAddr.getAlignment()); 1295 } 1296 1297 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1298 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1299 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1300 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1301 // library. 1302 auto OMPLoc = emitUpdateLocation(CGF, Loc); 1303 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1304 OMPLoc); 1305 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1306 // to register constructor/destructor for variable. 1307 llvm::Value *Args[] = {OMPLoc, 1308 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1309 CGM.VoidPtrTy), 1310 Ctor, CopyCtor, Dtor}; 1311 CGF.EmitRuntimeCall( 1312 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 1313 } 1314 1315 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1316 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1317 bool PerformInit, CodeGenFunction *CGF) { 1318 if (CGM.getLangOpts().OpenMPUseTLS && 1319 CGM.getContext().getTargetInfo().isTLSSupported()) 1320 return nullptr; 1321 1322 VD = VD->getDefinition(CGM.getContext()); 1323 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) { 1324 ThreadPrivateWithDefinition.insert(VD); 1325 QualType ASTTy = VD->getType(); 1326 1327 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1328 auto Init = VD->getAnyInitializer(); 1329 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1330 // Generate function that re-emits the declaration's initializer into the 1331 // threadprivate copy of the variable VD 1332 CodeGenFunction CtorCGF(CGM); 1333 FunctionArgList Args; 1334 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 1335 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 1336 Args.push_back(&Dst); 1337 1338 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 1339 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(), 1340 /*isVariadic=*/false); 1341 auto FTy = CGM.getTypes().GetFunctionType(FI); 1342 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 1343 FTy, ".__kmpc_global_ctor_.", FI, Loc); 1344 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1345 Args, SourceLocation()); 1346 auto ArgVal = CtorCGF.EmitLoadOfScalar( 1347 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1348 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1349 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1350 Arg = CtorCGF.Builder.CreateElementBitCast(Arg, 1351 CtorCGF.ConvertTypeForMem(ASTTy)); 1352 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1353 /*IsInitializer=*/true); 1354 ArgVal = CtorCGF.EmitLoadOfScalar( 1355 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1356 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1357 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1358 CtorCGF.FinishFunction(); 1359 Ctor = Fn; 1360 } 1361 if (VD->getType().isDestructedType() != QualType::DK_none) { 1362 // Generate function that emits destructor call for the threadprivate copy 1363 // of the variable VD 1364 CodeGenFunction DtorCGF(CGM); 1365 FunctionArgList Args; 1366 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 1367 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 1368 Args.push_back(&Dst); 1369 1370 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 1371 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(), 1372 /*isVariadic=*/false); 1373 auto FTy = CGM.getTypes().GetFunctionType(FI); 1374 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 1375 FTy, ".__kmpc_global_dtor_.", FI, Loc); 1376 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1377 SourceLocation()); 1378 auto ArgVal = DtorCGF.EmitLoadOfScalar( 1379 DtorCGF.GetAddrOfLocalVar(&Dst), 1380 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1381 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1382 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1383 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1384 DtorCGF.FinishFunction(); 1385 Dtor = Fn; 1386 } 1387 // Do not emit init function if it is not required. 1388 if (!Ctor && !Dtor) 1389 return nullptr; 1390 1391 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1392 auto CopyCtorTy = 1393 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1394 /*isVarArg=*/false)->getPointerTo(); 1395 // Copying constructor for the threadprivate variable. 1396 // Must be NULL - reserved by runtime, but currently it requires that this 1397 // parameter is always NULL. Otherwise it fires assertion. 1398 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1399 if (Ctor == nullptr) { 1400 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1401 /*isVarArg=*/false)->getPointerTo(); 1402 Ctor = llvm::Constant::getNullValue(CtorTy); 1403 } 1404 if (Dtor == nullptr) { 1405 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1406 /*isVarArg=*/false)->getPointerTo(); 1407 Dtor = llvm::Constant::getNullValue(DtorTy); 1408 } 1409 if (!CGF) { 1410 auto InitFunctionTy = 1411 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1412 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction( 1413 InitFunctionTy, ".__omp_threadprivate_init_.", 1414 CGM.getTypes().arrangeNullaryFunction()); 1415 CodeGenFunction InitCGF(CGM); 1416 FunctionArgList ArgList; 1417 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1418 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1419 Loc); 1420 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1421 InitCGF.FinishFunction(); 1422 return InitFunction; 1423 } 1424 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1425 } 1426 return nullptr; 1427 } 1428 1429 /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen 1430 /// function. Here is the logic: 1431 /// if (Cond) { 1432 /// ThenGen(); 1433 /// } else { 1434 /// ElseGen(); 1435 /// } 1436 static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, 1437 const RegionCodeGenTy &ThenGen, 1438 const RegionCodeGenTy &ElseGen) { 1439 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 1440 1441 // If the condition constant folds and can be elided, try to avoid emitting 1442 // the condition and the dead arm of the if/else. 1443 bool CondConstant; 1444 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 1445 CodeGenFunction::RunCleanupsScope Scope(CGF); 1446 if (CondConstant) { 1447 ThenGen(CGF); 1448 } else { 1449 ElseGen(CGF); 1450 } 1451 return; 1452 } 1453 1454 // Otherwise, the condition did not fold, or we couldn't elide it. Just 1455 // emit the conditional branch. 1456 auto ThenBlock = CGF.createBasicBlock("omp_if.then"); 1457 auto ElseBlock = CGF.createBasicBlock("omp_if.else"); 1458 auto ContBlock = CGF.createBasicBlock("omp_if.end"); 1459 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 1460 1461 // Emit the 'then' code. 1462 CGF.EmitBlock(ThenBlock); 1463 { 1464 CodeGenFunction::RunCleanupsScope ThenScope(CGF); 1465 ThenGen(CGF); 1466 } 1467 CGF.EmitBranch(ContBlock); 1468 // Emit the 'else' code if present. 1469 { 1470 // There is no need to emit line number for unconditional branch. 1471 auto NL = ApplyDebugLocation::CreateEmpty(CGF); 1472 CGF.EmitBlock(ElseBlock); 1473 } 1474 { 1475 CodeGenFunction::RunCleanupsScope ThenScope(CGF); 1476 ElseGen(CGF); 1477 } 1478 { 1479 // There is no need to emit line number for unconditional branch. 1480 auto NL = ApplyDebugLocation::CreateEmpty(CGF); 1481 CGF.EmitBranch(ContBlock); 1482 } 1483 // Emit the continuation block for code after the if. 1484 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 1485 } 1486 1487 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 1488 llvm::Value *OutlinedFn, 1489 ArrayRef<llvm::Value *> CapturedVars, 1490 const Expr *IfCond) { 1491 if (!CGF.HaveInsertPoint()) 1492 return; 1493 auto *RTLoc = emitUpdateLocation(CGF, Loc); 1494 auto &&ThenGen = [this, OutlinedFn, CapturedVars, 1495 RTLoc](CodeGenFunction &CGF) { 1496 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 1497 llvm::Value *Args[] = { 1498 RTLoc, 1499 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 1500 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 1501 llvm::SmallVector<llvm::Value *, 16> RealArgs; 1502 RealArgs.append(std::begin(Args), std::end(Args)); 1503 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 1504 1505 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call); 1506 CGF.EmitRuntimeCall(RTLFn, RealArgs); 1507 }; 1508 auto &&ElseGen = [this, OutlinedFn, CapturedVars, RTLoc, 1509 Loc](CodeGenFunction &CGF) { 1510 auto ThreadID = getThreadID(CGF, Loc); 1511 // Build calls: 1512 // __kmpc_serialized_parallel(&Loc, GTid); 1513 llvm::Value *Args[] = {RTLoc, ThreadID}; 1514 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), 1515 Args); 1516 1517 // OutlinedFn(>id, &zero, CapturedStruct); 1518 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc); 1519 Address ZeroAddr = 1520 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4), 1521 /*Name*/ ".zero.addr"); 1522 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 1523 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 1524 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 1525 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 1526 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 1527 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs); 1528 1529 // __kmpc_end_serialized_parallel(&Loc, GTid); 1530 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID}; 1531 CGF.EmitRuntimeCall( 1532 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs); 1533 }; 1534 if (IfCond) { 1535 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 1536 } else { 1537 CodeGenFunction::RunCleanupsScope Scope(CGF); 1538 ThenGen(CGF); 1539 } 1540 } 1541 1542 // If we're inside an (outlined) parallel region, use the region info's 1543 // thread-ID variable (it is passed in a first argument of the outlined function 1544 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 1545 // regular serial code region, get thread ID by calling kmp_int32 1546 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 1547 // return the address of that temp. 1548 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 1549 SourceLocation Loc) { 1550 if (auto *OMPRegionInfo = 1551 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 1552 if (OMPRegionInfo->getThreadIDVariable()) 1553 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 1554 1555 auto ThreadID = getThreadID(CGF, Loc); 1556 auto Int32Ty = 1557 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 1558 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 1559 CGF.EmitStoreOfScalar(ThreadID, 1560 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 1561 1562 return ThreadIDTemp; 1563 } 1564 1565 llvm::Constant * 1566 CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty, 1567 const llvm::Twine &Name) { 1568 SmallString<256> Buffer; 1569 llvm::raw_svector_ostream Out(Buffer); 1570 Out << Name; 1571 auto RuntimeName = Out.str(); 1572 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first; 1573 if (Elem.second) { 1574 assert(Elem.second->getType()->getPointerElementType() == Ty && 1575 "OMP internal variable has different type than requested"); 1576 return &*Elem.second; 1577 } 1578 1579 return Elem.second = new llvm::GlobalVariable( 1580 CGM.getModule(), Ty, /*IsConstant*/ false, 1581 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 1582 Elem.first()); 1583 } 1584 1585 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 1586 llvm::Twine Name(".gomp_critical_user_", CriticalName); 1587 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var")); 1588 } 1589 1590 namespace { 1591 template <size_t N> class CallEndCleanup final : public EHScopeStack::Cleanup { 1592 llvm::Value *Callee; 1593 llvm::Value *Args[N]; 1594 1595 public: 1596 CallEndCleanup(llvm::Value *Callee, ArrayRef<llvm::Value *> CleanupArgs) 1597 : Callee(Callee) { 1598 assert(CleanupArgs.size() == N); 1599 std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args)); 1600 } 1601 1602 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 1603 if (!CGF.HaveInsertPoint()) 1604 return; 1605 CGF.EmitRuntimeCall(Callee, Args); 1606 } 1607 }; 1608 } // anonymous namespace 1609 1610 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 1611 StringRef CriticalName, 1612 const RegionCodeGenTy &CriticalOpGen, 1613 SourceLocation Loc, const Expr *Hint) { 1614 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 1615 // CriticalOpGen(); 1616 // __kmpc_end_critical(ident_t *, gtid, Lock); 1617 // Prepare arguments and build a call to __kmpc_critical 1618 if (!CGF.HaveInsertPoint()) 1619 return; 1620 CodeGenFunction::RunCleanupsScope Scope(CGF); 1621 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1622 getCriticalRegionLock(CriticalName)}; 1623 if (Hint) { 1624 llvm::SmallVector<llvm::Value *, 8> ArgsWithHint(std::begin(Args), 1625 std::end(Args)); 1626 auto *HintVal = CGF.EmitScalarExpr(Hint); 1627 ArgsWithHint.push_back( 1628 CGF.Builder.CreateIntCast(HintVal, CGM.IntPtrTy, /*isSigned=*/false)); 1629 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical_with_hint), 1630 ArgsWithHint); 1631 } else 1632 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args); 1633 // Build a call to __kmpc_end_critical 1634 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( 1635 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical), 1636 llvm::makeArrayRef(Args)); 1637 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 1638 } 1639 1640 static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond, 1641 OpenMPDirectiveKind Kind, SourceLocation Loc, 1642 const RegionCodeGenTy &BodyOpGen) { 1643 llvm::Value *CallBool = CGF.EmitScalarConversion( 1644 IfCond, 1645 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true), 1646 CGF.getContext().BoolTy, Loc); 1647 1648 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 1649 auto *ContBlock = CGF.createBasicBlock("omp_if.end"); 1650 // Generate the branch (If-stmt) 1651 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 1652 CGF.EmitBlock(ThenBlock); 1653 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen); 1654 // Emit the rest of bblocks/branches 1655 CGF.EmitBranch(ContBlock); 1656 CGF.EmitBlock(ContBlock, true); 1657 } 1658 1659 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 1660 const RegionCodeGenTy &MasterOpGen, 1661 SourceLocation Loc) { 1662 if (!CGF.HaveInsertPoint()) 1663 return; 1664 // if(__kmpc_master(ident_t *, gtid)) { 1665 // MasterOpGen(); 1666 // __kmpc_end_master(ident_t *, gtid); 1667 // } 1668 // Prepare arguments and build a call to __kmpc_master 1669 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 1670 auto *IsMaster = 1671 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args); 1672 typedef CallEndCleanup<std::extent<decltype(Args)>::value> 1673 MasterCallEndCleanup; 1674 emitIfStmt( 1675 CGF, IsMaster, OMPD_master, Loc, [&](CodeGenFunction &CGF) -> void { 1676 CodeGenFunction::RunCleanupsScope Scope(CGF); 1677 CGF.EHStack.pushCleanup<MasterCallEndCleanup>( 1678 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master), 1679 llvm::makeArrayRef(Args)); 1680 MasterOpGen(CGF); 1681 }); 1682 } 1683 1684 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 1685 SourceLocation Loc) { 1686 if (!CGF.HaveInsertPoint()) 1687 return; 1688 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 1689 llvm::Value *Args[] = { 1690 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1691 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 1692 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 1693 } 1694 1695 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 1696 const RegionCodeGenTy &TaskgroupOpGen, 1697 SourceLocation Loc) { 1698 if (!CGF.HaveInsertPoint()) 1699 return; 1700 // __kmpc_taskgroup(ident_t *, gtid); 1701 // TaskgroupOpGen(); 1702 // __kmpc_end_taskgroup(ident_t *, gtid); 1703 // Prepare arguments and build a call to __kmpc_taskgroup 1704 { 1705 CodeGenFunction::RunCleanupsScope Scope(CGF); 1706 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 1707 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args); 1708 // Build a call to __kmpc_end_taskgroup 1709 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( 1710 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 1711 llvm::makeArrayRef(Args)); 1712 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 1713 } 1714 } 1715 1716 /// Given an array of pointers to variables, project the address of a 1717 /// given variable. 1718 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 1719 unsigned Index, const VarDecl *Var) { 1720 // Pull out the pointer to the variable. 1721 Address PtrAddr = 1722 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize()); 1723 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 1724 1725 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 1726 Addr = CGF.Builder.CreateElementBitCast( 1727 Addr, CGF.ConvertTypeForMem(Var->getType())); 1728 return Addr; 1729 } 1730 1731 static llvm::Value *emitCopyprivateCopyFunction( 1732 CodeGenModule &CGM, llvm::Type *ArgsType, 1733 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 1734 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) { 1735 auto &C = CGM.getContext(); 1736 // void copy_func(void *LHSArg, void *RHSArg); 1737 FunctionArgList Args; 1738 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 1739 C.VoidPtrTy); 1740 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 1741 C.VoidPtrTy); 1742 Args.push_back(&LHSArg); 1743 Args.push_back(&RHSArg); 1744 FunctionType::ExtInfo EI; 1745 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration( 1746 C.VoidTy, Args, EI, /*isVariadic=*/false); 1747 auto *Fn = llvm::Function::Create( 1748 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 1749 ".omp.copyprivate.copy_func", &CGM.getModule()); 1750 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI); 1751 CodeGenFunction CGF(CGM); 1752 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 1753 // Dest = (void*[n])(LHSArg); 1754 // Src = (void*[n])(RHSArg); 1755 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1756 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 1757 ArgsType), CGF.getPointerAlign()); 1758 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1759 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 1760 ArgsType), CGF.getPointerAlign()); 1761 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 1762 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 1763 // ... 1764 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 1765 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 1766 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 1767 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 1768 1769 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 1770 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 1771 1772 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 1773 QualType Type = VD->getType(); 1774 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 1775 } 1776 CGF.FinishFunction(); 1777 return Fn; 1778 } 1779 1780 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 1781 const RegionCodeGenTy &SingleOpGen, 1782 SourceLocation Loc, 1783 ArrayRef<const Expr *> CopyprivateVars, 1784 ArrayRef<const Expr *> SrcExprs, 1785 ArrayRef<const Expr *> DstExprs, 1786 ArrayRef<const Expr *> AssignmentOps) { 1787 if (!CGF.HaveInsertPoint()) 1788 return; 1789 assert(CopyprivateVars.size() == SrcExprs.size() && 1790 CopyprivateVars.size() == DstExprs.size() && 1791 CopyprivateVars.size() == AssignmentOps.size()); 1792 auto &C = CGM.getContext(); 1793 // int32 did_it = 0; 1794 // if(__kmpc_single(ident_t *, gtid)) { 1795 // SingleOpGen(); 1796 // __kmpc_end_single(ident_t *, gtid); 1797 // did_it = 1; 1798 // } 1799 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 1800 // <copy_func>, did_it); 1801 1802 Address DidIt = Address::invalid(); 1803 if (!CopyprivateVars.empty()) { 1804 // int32 did_it = 0; 1805 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1806 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 1807 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 1808 } 1809 // Prepare arguments and build a call to __kmpc_single 1810 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 1811 auto *IsSingle = 1812 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args); 1813 typedef CallEndCleanup<std::extent<decltype(Args)>::value> 1814 SingleCallEndCleanup; 1815 emitIfStmt( 1816 CGF, IsSingle, OMPD_single, Loc, [&](CodeGenFunction &CGF) -> void { 1817 CodeGenFunction::RunCleanupsScope Scope(CGF); 1818 CGF.EHStack.pushCleanup<SingleCallEndCleanup>( 1819 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single), 1820 llvm::makeArrayRef(Args)); 1821 SingleOpGen(CGF); 1822 if (DidIt.isValid()) { 1823 // did_it = 1; 1824 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 1825 } 1826 }); 1827 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 1828 // <copy_func>, did_it); 1829 if (DidIt.isValid()) { 1830 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 1831 auto CopyprivateArrayTy = 1832 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 1833 /*IndexTypeQuals=*/0); 1834 // Create a list of all private variables for copyprivate. 1835 Address CopyprivateList = 1836 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 1837 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 1838 Address Elem = CGF.Builder.CreateConstArrayGEP( 1839 CopyprivateList, I, CGF.getPointerSize()); 1840 CGF.Builder.CreateStore( 1841 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1842 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), 1843 Elem); 1844 } 1845 // Build function that copies private values from single region to all other 1846 // threads in the corresponding parallel region. 1847 auto *CpyFn = emitCopyprivateCopyFunction( 1848 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 1849 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps); 1850 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 1851 Address CL = 1852 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 1853 CGF.VoidPtrTy); 1854 auto *DidItVal = CGF.Builder.CreateLoad(DidIt); 1855 llvm::Value *Args[] = { 1856 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 1857 getThreadID(CGF, Loc), // i32 <gtid> 1858 BufSize, // size_t <buf_size> 1859 CL.getPointer(), // void *<copyprivate list> 1860 CpyFn, // void (*) (void *, void *) <copy_func> 1861 DidItVal // i32 did_it 1862 }; 1863 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 1864 } 1865 } 1866 1867 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 1868 const RegionCodeGenTy &OrderedOpGen, 1869 SourceLocation Loc, bool IsThreads) { 1870 if (!CGF.HaveInsertPoint()) 1871 return; 1872 // __kmpc_ordered(ident_t *, gtid); 1873 // OrderedOpGen(); 1874 // __kmpc_end_ordered(ident_t *, gtid); 1875 // Prepare arguments and build a call to __kmpc_ordered 1876 CodeGenFunction::RunCleanupsScope Scope(CGF); 1877 if (IsThreads) { 1878 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 1879 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args); 1880 // Build a call to __kmpc_end_ordered 1881 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( 1882 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered), 1883 llvm::makeArrayRef(Args)); 1884 } 1885 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 1886 } 1887 1888 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 1889 OpenMPDirectiveKind Kind, bool EmitChecks, 1890 bool ForceSimpleCall) { 1891 if (!CGF.HaveInsertPoint()) 1892 return; 1893 // Build call __kmpc_cancel_barrier(loc, thread_id); 1894 // Build call __kmpc_barrier(loc, thread_id); 1895 unsigned Flags; 1896 if (Kind == OMPD_for) 1897 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 1898 else if (Kind == OMPD_sections) 1899 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 1900 else if (Kind == OMPD_single) 1901 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 1902 else if (Kind == OMPD_barrier) 1903 Flags = OMP_IDENT_BARRIER_EXPL; 1904 else 1905 Flags = OMP_IDENT_BARRIER_IMPL; 1906 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 1907 // thread_id); 1908 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 1909 getThreadID(CGF, Loc)}; 1910 if (auto *OMPRegionInfo = 1911 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1912 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 1913 auto *Result = CGF.EmitRuntimeCall( 1914 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 1915 if (EmitChecks) { 1916 // if (__kmpc_cancel_barrier()) { 1917 // exit from construct; 1918 // } 1919 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 1920 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 1921 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 1922 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 1923 CGF.EmitBlock(ExitBB); 1924 // exit from construct; 1925 auto CancelDestination = 1926 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 1927 CGF.EmitBranchThroughCleanup(CancelDestination); 1928 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 1929 } 1930 return; 1931 } 1932 } 1933 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 1934 } 1935 1936 /// \brief Map the OpenMP loop schedule to the runtime enumeration. 1937 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 1938 bool Chunked, bool Ordered) { 1939 switch (ScheduleKind) { 1940 case OMPC_SCHEDULE_static: 1941 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 1942 : (Ordered ? OMP_ord_static : OMP_sch_static); 1943 case OMPC_SCHEDULE_dynamic: 1944 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 1945 case OMPC_SCHEDULE_guided: 1946 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 1947 case OMPC_SCHEDULE_runtime: 1948 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 1949 case OMPC_SCHEDULE_auto: 1950 return Ordered ? OMP_ord_auto : OMP_sch_auto; 1951 case OMPC_SCHEDULE_unknown: 1952 assert(!Chunked && "chunk was specified but schedule kind not known"); 1953 return Ordered ? OMP_ord_static : OMP_sch_static; 1954 } 1955 llvm_unreachable("Unexpected runtime schedule"); 1956 } 1957 1958 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 1959 bool Chunked) const { 1960 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 1961 return Schedule == OMP_sch_static; 1962 } 1963 1964 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 1965 auto Schedule = 1966 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 1967 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 1968 return Schedule != OMP_sch_static; 1969 } 1970 1971 void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF, 1972 SourceLocation Loc, 1973 OpenMPScheduleClauseKind ScheduleKind, 1974 unsigned IVSize, bool IVSigned, 1975 bool Ordered, llvm::Value *UB, 1976 llvm::Value *Chunk) { 1977 if (!CGF.HaveInsertPoint()) 1978 return; 1979 OpenMPSchedType Schedule = 1980 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered); 1981 assert(Ordered || 1982 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 1983 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked)); 1984 // Call __kmpc_dispatch_init( 1985 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 1986 // kmp_int[32|64] lower, kmp_int[32|64] upper, 1987 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 1988 1989 // If the Chunk was not specified in the clause - use default value 1. 1990 if (Chunk == nullptr) 1991 Chunk = CGF.Builder.getIntN(IVSize, 1); 1992 llvm::Value *Args[] = { 1993 emitUpdateLocation(CGF, Loc), 1994 getThreadID(CGF, Loc), 1995 CGF.Builder.getInt32(Schedule), // Schedule type 1996 CGF.Builder.getIntN(IVSize, 0), // Lower 1997 UB, // Upper 1998 CGF.Builder.getIntN(IVSize, 1), // Stride 1999 Chunk // Chunk 2000 }; 2001 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2002 } 2003 2004 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2005 SourceLocation Loc, 2006 OpenMPScheduleClauseKind ScheduleKind, 2007 unsigned IVSize, bool IVSigned, 2008 bool Ordered, Address IL, Address LB, 2009 Address UB, Address ST, 2010 llvm::Value *Chunk) { 2011 if (!CGF.HaveInsertPoint()) 2012 return; 2013 OpenMPSchedType Schedule = 2014 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered); 2015 assert(!Ordered); 2016 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2017 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked); 2018 2019 // Call __kmpc_for_static_init( 2020 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2021 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2022 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2023 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2024 if (Chunk == nullptr) { 2025 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) && 2026 "expected static non-chunked schedule"); 2027 // If the Chunk was not specified in the clause - use default value 1. 2028 Chunk = CGF.Builder.getIntN(IVSize, 1); 2029 } else { 2030 assert((Schedule == OMP_sch_static_chunked || 2031 Schedule == OMP_ord_static_chunked) && 2032 "expected static chunked schedule"); 2033 } 2034 llvm::Value *Args[] = { 2035 emitUpdateLocation(CGF, Loc), 2036 getThreadID(CGF, Loc), 2037 CGF.Builder.getInt32(Schedule), // Schedule type 2038 IL.getPointer(), // &isLastIter 2039 LB.getPointer(), // &LB 2040 UB.getPointer(), // &UB 2041 ST.getPointer(), // &Stride 2042 CGF.Builder.getIntN(IVSize, 1), // Incr 2043 Chunk // Chunk 2044 }; 2045 CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args); 2046 } 2047 2048 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2049 SourceLocation Loc) { 2050 if (!CGF.HaveInsertPoint()) 2051 return; 2052 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2053 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2054 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 2055 Args); 2056 } 2057 2058 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2059 SourceLocation Loc, 2060 unsigned IVSize, 2061 bool IVSigned) { 2062 if (!CGF.HaveInsertPoint()) 2063 return; 2064 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2065 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2066 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2067 } 2068 2069 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2070 SourceLocation Loc, unsigned IVSize, 2071 bool IVSigned, Address IL, 2072 Address LB, Address UB, 2073 Address ST) { 2074 // Call __kmpc_dispatch_next( 2075 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2076 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2077 // kmp_int[32|64] *p_stride); 2078 llvm::Value *Args[] = { 2079 emitUpdateLocation(CGF, Loc), 2080 getThreadID(CGF, Loc), 2081 IL.getPointer(), // &isLastIter 2082 LB.getPointer(), // &Lower 2083 UB.getPointer(), // &Upper 2084 ST.getPointer() // &Stride 2085 }; 2086 llvm::Value *Call = 2087 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2088 return CGF.EmitScalarConversion( 2089 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true), 2090 CGF.getContext().BoolTy, Loc); 2091 } 2092 2093 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2094 llvm::Value *NumThreads, 2095 SourceLocation Loc) { 2096 if (!CGF.HaveInsertPoint()) 2097 return; 2098 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2099 llvm::Value *Args[] = { 2100 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2101 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2102 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 2103 Args); 2104 } 2105 2106 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2107 OpenMPProcBindClauseKind ProcBind, 2108 SourceLocation Loc) { 2109 if (!CGF.HaveInsertPoint()) 2110 return; 2111 // Constants for proc bind value accepted by the runtime. 2112 enum ProcBindTy { 2113 ProcBindFalse = 0, 2114 ProcBindTrue, 2115 ProcBindMaster, 2116 ProcBindClose, 2117 ProcBindSpread, 2118 ProcBindIntel, 2119 ProcBindDefault 2120 } RuntimeProcBind; 2121 switch (ProcBind) { 2122 case OMPC_PROC_BIND_master: 2123 RuntimeProcBind = ProcBindMaster; 2124 break; 2125 case OMPC_PROC_BIND_close: 2126 RuntimeProcBind = ProcBindClose; 2127 break; 2128 case OMPC_PROC_BIND_spread: 2129 RuntimeProcBind = ProcBindSpread; 2130 break; 2131 case OMPC_PROC_BIND_unknown: 2132 llvm_unreachable("Unsupported proc_bind value."); 2133 } 2134 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2135 llvm::Value *Args[] = { 2136 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2137 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 2138 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 2139 } 2140 2141 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2142 SourceLocation Loc) { 2143 if (!CGF.HaveInsertPoint()) 2144 return; 2145 // Build call void __kmpc_flush(ident_t *loc) 2146 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 2147 emitUpdateLocation(CGF, Loc)); 2148 } 2149 2150 namespace { 2151 /// \brief Indexes of fields for type kmp_task_t. 2152 enum KmpTaskTFields { 2153 /// \brief List of shared variables. 2154 KmpTaskTShareds, 2155 /// \brief Task routine. 2156 KmpTaskTRoutine, 2157 /// \brief Partition id for the untied tasks. 2158 KmpTaskTPartId, 2159 /// \brief Function with call of destructors for private variables. 2160 KmpTaskTDestructors, 2161 }; 2162 } // anonymous namespace 2163 2164 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2165 // FIXME: Add other entries type when they become supported. 2166 return OffloadEntriesTargetRegion.empty(); 2167 } 2168 2169 /// \brief Initialize target region entry. 2170 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2171 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2172 StringRef ParentName, unsigned LineNum, 2173 unsigned Order) { 2174 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2175 "only required for the device " 2176 "code generation."); 2177 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 2178 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr); 2179 ++OffloadingEntriesNum; 2180 } 2181 2182 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2183 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2184 StringRef ParentName, unsigned LineNum, 2185 llvm::Constant *Addr, llvm::Constant *ID) { 2186 // If we are emitting code for a target, the entry is already initialized, 2187 // only has to be registered. 2188 if (CGM.getLangOpts().OpenMPIsDevice) { 2189 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && 2190 "Entry must exist."); 2191 auto &Entry = 2192 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 2193 assert(Entry.isValid() && "Entry not initialized!"); 2194 Entry.setAddress(Addr); 2195 Entry.setID(ID); 2196 return; 2197 } else { 2198 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID); 2199 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 2200 } 2201 } 2202 2203 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 2204 unsigned DeviceID, unsigned FileID, StringRef ParentName, 2205 unsigned LineNum) const { 2206 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 2207 if (PerDevice == OffloadEntriesTargetRegion.end()) 2208 return false; 2209 auto PerFile = PerDevice->second.find(FileID); 2210 if (PerFile == PerDevice->second.end()) 2211 return false; 2212 auto PerParentName = PerFile->second.find(ParentName); 2213 if (PerParentName == PerFile->second.end()) 2214 return false; 2215 auto PerLine = PerParentName->second.find(LineNum); 2216 if (PerLine == PerParentName->second.end()) 2217 return false; 2218 // Fail if this entry is already registered. 2219 if (PerLine->second.getAddress() || PerLine->second.getID()) 2220 return false; 2221 return true; 2222 } 2223 2224 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 2225 const OffloadTargetRegionEntryInfoActTy &Action) { 2226 // Scan all target region entries and perform the provided action. 2227 for (auto &D : OffloadEntriesTargetRegion) 2228 for (auto &F : D.second) 2229 for (auto &P : F.second) 2230 for (auto &L : P.second) 2231 Action(D.first, F.first, P.first(), L.first, L.second); 2232 } 2233 2234 /// \brief Create a Ctor/Dtor-like function whose body is emitted through 2235 /// \a Codegen. This is used to emit the two functions that register and 2236 /// unregister the descriptor of the current compilation unit. 2237 static llvm::Function * 2238 createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name, 2239 const RegionCodeGenTy &Codegen) { 2240 auto &C = CGM.getContext(); 2241 FunctionArgList Args; 2242 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(), 2243 /*Id=*/nullptr, C.VoidPtrTy); 2244 Args.push_back(&DummyPtr); 2245 2246 CodeGenFunction CGF(CGM); 2247 GlobalDecl(); 2248 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 2249 C.VoidTy, Args, FunctionType::ExtInfo(), 2250 /*isVariadic=*/false); 2251 auto FTy = CGM.getTypes().GetFunctionType(FI); 2252 auto *Fn = 2253 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation()); 2254 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation()); 2255 Codegen(CGF); 2256 CGF.FinishFunction(); 2257 return Fn; 2258 } 2259 2260 llvm::Function * 2261 CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { 2262 2263 // If we don't have entries or if we are emitting code for the device, we 2264 // don't need to do anything. 2265 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty()) 2266 return nullptr; 2267 2268 auto &M = CGM.getModule(); 2269 auto &C = CGM.getContext(); 2270 2271 // Get list of devices we care about 2272 auto &Devices = CGM.getLangOpts().OMPTargetTriples; 2273 2274 // We should be creating an offloading descriptor only if there are devices 2275 // specified. 2276 assert(!Devices.empty() && "No OpenMP offloading devices??"); 2277 2278 // Create the external variables that will point to the begin and end of the 2279 // host entries section. These will be defined by the linker. 2280 auto *OffloadEntryTy = 2281 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()); 2282 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable( 2283 M, OffloadEntryTy, /*isConstant=*/true, 2284 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 2285 ".omp_offloading.entries_begin"); 2286 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable( 2287 M, OffloadEntryTy, /*isConstant=*/true, 2288 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 2289 ".omp_offloading.entries_end"); 2290 2291 // Create all device images 2292 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires; 2293 auto *DeviceImageTy = cast<llvm::StructType>( 2294 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy())); 2295 2296 for (unsigned i = 0; i < Devices.size(); ++i) { 2297 StringRef T = Devices[i].getTriple(); 2298 auto *ImgBegin = new llvm::GlobalVariable( 2299 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, 2300 /*Initializer=*/nullptr, 2301 Twine(".omp_offloading.img_start.") + Twine(T)); 2302 auto *ImgEnd = new llvm::GlobalVariable( 2303 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, 2304 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T)); 2305 2306 llvm::Constant *Dev = 2307 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd, 2308 HostEntriesBegin, HostEntriesEnd, nullptr); 2309 DeviceImagesEntires.push_back(Dev); 2310 } 2311 2312 // Create device images global array. 2313 llvm::ArrayType *DeviceImagesInitTy = 2314 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size()); 2315 llvm::Constant *DeviceImagesInit = 2316 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires); 2317 2318 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable( 2319 M, DeviceImagesInitTy, /*isConstant=*/true, 2320 llvm::GlobalValue::InternalLinkage, DeviceImagesInit, 2321 ".omp_offloading.device_images"); 2322 DeviceImages->setUnnamedAddr(true); 2323 2324 // This is a Zero array to be used in the creation of the constant expressions 2325 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty), 2326 llvm::Constant::getNullValue(CGM.Int32Ty)}; 2327 2328 // Create the target region descriptor. 2329 auto *BinaryDescriptorTy = cast<llvm::StructType>( 2330 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy())); 2331 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get( 2332 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()), 2333 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages, 2334 Index), 2335 HostEntriesBegin, HostEntriesEnd, nullptr); 2336 2337 auto *Desc = new llvm::GlobalVariable( 2338 M, BinaryDescriptorTy, /*isConstant=*/true, 2339 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit, 2340 ".omp_offloading.descriptor"); 2341 2342 // Emit code to register or unregister the descriptor at execution 2343 // startup or closing, respectively. 2344 2345 // Create a variable to drive the registration and unregistration of the 2346 // descriptor, so we can reuse the logic that emits Ctors and Dtors. 2347 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var"); 2348 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(), 2349 IdentInfo, C.CharTy); 2350 2351 auto *UnRegFn = createOffloadingBinaryDescriptorFunction( 2352 CGM, ".omp_offloading.descriptor_unreg", [&](CodeGenFunction &CGF) { 2353 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib), 2354 Desc); 2355 }); 2356 auto *RegFn = createOffloadingBinaryDescriptorFunction( 2357 CGM, ".omp_offloading.descriptor_reg", [&](CodeGenFunction &CGF) { 2358 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib), 2359 Desc); 2360 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc); 2361 }); 2362 return RegFn; 2363 } 2364 2365 void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID, 2366 llvm::Constant *Addr, uint64_t Size) { 2367 StringRef Name = Addr->getName(); 2368 auto *TgtOffloadEntryType = cast<llvm::StructType>( 2369 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy())); 2370 llvm::LLVMContext &C = CGM.getModule().getContext(); 2371 llvm::Module &M = CGM.getModule(); 2372 2373 // Make sure the address has the right type. 2374 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy); 2375 2376 // Create constant string with the name. 2377 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 2378 2379 llvm::GlobalVariable *Str = 2380 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true, 2381 llvm::GlobalValue::InternalLinkage, StrPtrInit, 2382 ".omp_offloading.entry_name"); 2383 Str->setUnnamedAddr(true); 2384 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy); 2385 2386 // Create the entry struct. 2387 llvm::Constant *EntryInit = llvm::ConstantStruct::get( 2388 TgtOffloadEntryType, AddrPtr, StrPtr, 2389 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr); 2390 llvm::GlobalVariable *Entry = new llvm::GlobalVariable( 2391 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage, 2392 EntryInit, ".omp_offloading.entry"); 2393 2394 // The entry has to be created in the section the linker expects it to be. 2395 Entry->setSection(".omp_offloading.entries"); 2396 // We can't have any padding between symbols, so we need to have 1-byte 2397 // alignment. 2398 Entry->setAlignment(1); 2399 } 2400 2401 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 2402 // Emit the offloading entries and metadata so that the device codegen side 2403 // can 2404 // easily figure out what to emit. The produced metadata looks like this: 2405 // 2406 // !omp_offload.info = !{!1, ...} 2407 // 2408 // Right now we only generate metadata for function that contain target 2409 // regions. 2410 2411 // If we do not have entries, we dont need to do anything. 2412 if (OffloadEntriesInfoManager.empty()) 2413 return; 2414 2415 llvm::Module &M = CGM.getModule(); 2416 llvm::LLVMContext &C = M.getContext(); 2417 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16> 2418 OrderedEntries(OffloadEntriesInfoManager.size()); 2419 2420 // Create the offloading info metadata node. 2421 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 2422 2423 // Auxiliar methods to create metadata values and strings. 2424 auto getMDInt = [&](unsigned v) { 2425 return llvm::ConstantAsMetadata::get( 2426 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v)); 2427 }; 2428 2429 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); }; 2430 2431 // Create function that emits metadata for each target region entry; 2432 auto &&TargetRegionMetadataEmitter = [&]( 2433 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line, 2434 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 2435 llvm::SmallVector<llvm::Metadata *, 32> Ops; 2436 // Generate metadata for target regions. Each entry of this metadata 2437 // contains: 2438 // - Entry 0 -> Kind of this type of metadata (0). 2439 // - Entry 1 -> Device ID of the file where the entry was identified. 2440 // - Entry 2 -> File ID of the file where the entry was identified. 2441 // - Entry 3 -> Mangled name of the function where the entry was identified. 2442 // - Entry 4 -> Line in the file where the entry was identified. 2443 // - Entry 5 -> Order the entry was created. 2444 // The first element of the metadata node is the kind. 2445 Ops.push_back(getMDInt(E.getKind())); 2446 Ops.push_back(getMDInt(DeviceID)); 2447 Ops.push_back(getMDInt(FileID)); 2448 Ops.push_back(getMDString(ParentName)); 2449 Ops.push_back(getMDInt(Line)); 2450 Ops.push_back(getMDInt(E.getOrder())); 2451 2452 // Save this entry in the right position of the ordered entries array. 2453 OrderedEntries[E.getOrder()] = &E; 2454 2455 // Add metadata to the named metadata node. 2456 MD->addOperand(llvm::MDNode::get(C, Ops)); 2457 }; 2458 2459 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 2460 TargetRegionMetadataEmitter); 2461 2462 for (auto *E : OrderedEntries) { 2463 assert(E && "All ordered entries must exist!"); 2464 if (auto *CE = 2465 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 2466 E)) { 2467 assert(CE->getID() && CE->getAddress() && 2468 "Entry ID and Addr are invalid!"); 2469 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0); 2470 } else 2471 llvm_unreachable("Unsupported entry kind."); 2472 } 2473 } 2474 2475 /// \brief Loads all the offload entries information from the host IR 2476 /// metadata. 2477 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 2478 // If we are in target mode, load the metadata from the host IR. This code has 2479 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 2480 2481 if (!CGM.getLangOpts().OpenMPIsDevice) 2482 return; 2483 2484 if (CGM.getLangOpts().OMPHostIRFile.empty()) 2485 return; 2486 2487 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 2488 if (Buf.getError()) 2489 return; 2490 2491 llvm::LLVMContext C; 2492 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C); 2493 2494 if (ME.getError()) 2495 return; 2496 2497 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 2498 if (!MD) 2499 return; 2500 2501 for (auto I : MD->operands()) { 2502 llvm::MDNode *MN = cast<llvm::MDNode>(I); 2503 2504 auto getMDInt = [&](unsigned Idx) { 2505 llvm::ConstantAsMetadata *V = 2506 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 2507 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 2508 }; 2509 2510 auto getMDString = [&](unsigned Idx) { 2511 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx)); 2512 return V->getString(); 2513 }; 2514 2515 switch (getMDInt(0)) { 2516 default: 2517 llvm_unreachable("Unexpected metadata!"); 2518 break; 2519 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 2520 OFFLOAD_ENTRY_INFO_TARGET_REGION: 2521 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 2522 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2), 2523 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4), 2524 /*Order=*/getMDInt(5)); 2525 break; 2526 } 2527 } 2528 } 2529 2530 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 2531 if (!KmpRoutineEntryPtrTy) { 2532 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 2533 auto &C = CGM.getContext(); 2534 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 2535 FunctionProtoType::ExtProtoInfo EPI; 2536 KmpRoutineEntryPtrQTy = C.getPointerType( 2537 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 2538 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 2539 } 2540 } 2541 2542 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 2543 QualType FieldTy) { 2544 auto *Field = FieldDecl::Create( 2545 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 2546 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 2547 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 2548 Field->setAccess(AS_public); 2549 DC->addDecl(Field); 2550 return Field; 2551 } 2552 2553 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 2554 2555 // Make sure the type of the entry is already created. This is the type we 2556 // have to create: 2557 // struct __tgt_offload_entry{ 2558 // void *addr; // Pointer to the offload entry info. 2559 // // (function or global) 2560 // char *name; // Name of the function or global. 2561 // size_t size; // Size of the entry info (0 if it a function). 2562 // }; 2563 if (TgtOffloadEntryQTy.isNull()) { 2564 ASTContext &C = CGM.getContext(); 2565 auto *RD = C.buildImplicitRecord("__tgt_offload_entry"); 2566 RD->startDefinition(); 2567 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 2568 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 2569 addFieldToRecordDecl(C, RD, C.getSizeType()); 2570 RD->completeDefinition(); 2571 TgtOffloadEntryQTy = C.getRecordType(RD); 2572 } 2573 return TgtOffloadEntryQTy; 2574 } 2575 2576 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 2577 // These are the types we need to build: 2578 // struct __tgt_device_image{ 2579 // void *ImageStart; // Pointer to the target code start. 2580 // void *ImageEnd; // Pointer to the target code end. 2581 // // We also add the host entries to the device image, as it may be useful 2582 // // for the target runtime to have access to that information. 2583 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 2584 // // the entries. 2585 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 2586 // // entries (non inclusive). 2587 // }; 2588 if (TgtDeviceImageQTy.isNull()) { 2589 ASTContext &C = CGM.getContext(); 2590 auto *RD = C.buildImplicitRecord("__tgt_device_image"); 2591 RD->startDefinition(); 2592 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 2593 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 2594 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 2595 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 2596 RD->completeDefinition(); 2597 TgtDeviceImageQTy = C.getRecordType(RD); 2598 } 2599 return TgtDeviceImageQTy; 2600 } 2601 2602 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 2603 // struct __tgt_bin_desc{ 2604 // int32_t NumDevices; // Number of devices supported. 2605 // __tgt_device_image *DeviceImages; // Arrays of device images 2606 // // (one per device). 2607 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 2608 // // entries. 2609 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 2610 // // entries (non inclusive). 2611 // }; 2612 if (TgtBinaryDescriptorQTy.isNull()) { 2613 ASTContext &C = CGM.getContext(); 2614 auto *RD = C.buildImplicitRecord("__tgt_bin_desc"); 2615 RD->startDefinition(); 2616 addFieldToRecordDecl( 2617 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 2618 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 2619 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 2620 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 2621 RD->completeDefinition(); 2622 TgtBinaryDescriptorQTy = C.getRecordType(RD); 2623 } 2624 return TgtBinaryDescriptorQTy; 2625 } 2626 2627 namespace { 2628 struct PrivateHelpersTy { 2629 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 2630 const VarDecl *PrivateElemInit) 2631 : Original(Original), PrivateCopy(PrivateCopy), 2632 PrivateElemInit(PrivateElemInit) {} 2633 const VarDecl *Original; 2634 const VarDecl *PrivateCopy; 2635 const VarDecl *PrivateElemInit; 2636 }; 2637 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 2638 } // anonymous namespace 2639 2640 static RecordDecl * 2641 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 2642 if (!Privates.empty()) { 2643 auto &C = CGM.getContext(); 2644 // Build struct .kmp_privates_t. { 2645 // /* private vars */ 2646 // }; 2647 auto *RD = C.buildImplicitRecord(".kmp_privates.t"); 2648 RD->startDefinition(); 2649 for (auto &&Pair : Privates) { 2650 auto *VD = Pair.second.Original; 2651 auto Type = VD->getType(); 2652 Type = Type.getNonReferenceType(); 2653 auto *FD = addFieldToRecordDecl(C, RD, Type); 2654 if (VD->hasAttrs()) { 2655 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 2656 E(VD->getAttrs().end()); 2657 I != E; ++I) 2658 FD->addAttr(*I); 2659 } 2660 } 2661 RD->completeDefinition(); 2662 return RD; 2663 } 2664 return nullptr; 2665 } 2666 2667 static RecordDecl * 2668 createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty, 2669 QualType KmpRoutineEntryPointerQTy) { 2670 auto &C = CGM.getContext(); 2671 // Build struct kmp_task_t { 2672 // void * shareds; 2673 // kmp_routine_entry_t routine; 2674 // kmp_int32 part_id; 2675 // kmp_routine_entry_t destructors; 2676 // }; 2677 auto *RD = C.buildImplicitRecord("kmp_task_t"); 2678 RD->startDefinition(); 2679 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 2680 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 2681 addFieldToRecordDecl(C, RD, KmpInt32Ty); 2682 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 2683 RD->completeDefinition(); 2684 return RD; 2685 } 2686 2687 static RecordDecl * 2688 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 2689 ArrayRef<PrivateDataTy> Privates) { 2690 auto &C = CGM.getContext(); 2691 // Build struct kmp_task_t_with_privates { 2692 // kmp_task_t task_data; 2693 // .kmp_privates_t. privates; 2694 // }; 2695 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 2696 RD->startDefinition(); 2697 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 2698 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) { 2699 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 2700 } 2701 RD->completeDefinition(); 2702 return RD; 2703 } 2704 2705 /// \brief Emit a proxy function which accepts kmp_task_t as the second 2706 /// argument. 2707 /// \code 2708 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 2709 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, 2710 /// tt->shareds); 2711 /// return 0; 2712 /// } 2713 /// \endcode 2714 static llvm::Value * 2715 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 2716 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, 2717 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 2718 QualType SharedsPtrTy, llvm::Value *TaskFunction, 2719 llvm::Value *TaskPrivatesMap) { 2720 auto &C = CGM.getContext(); 2721 FunctionArgList Args; 2722 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 2723 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 2724 /*Id=*/nullptr, 2725 KmpTaskTWithPrivatesPtrQTy.withRestrict()); 2726 Args.push_back(&GtidArg); 2727 Args.push_back(&TaskTypeArg); 2728 FunctionType::ExtInfo Info; 2729 auto &TaskEntryFnInfo = 2730 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info, 2731 /*isVariadic=*/false); 2732 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 2733 auto *TaskEntry = 2734 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage, 2735 ".omp_task_entry.", &CGM.getModule()); 2736 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo); 2737 CodeGenFunction CGF(CGM); 2738 CGF.disableDebugInfo(); 2739 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args); 2740 2741 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 2742 // tt->task_data.shareds); 2743 auto *GtidParam = CGF.EmitLoadOfScalar( 2744 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 2745 LValue TDBase = CGF.EmitLoadOfPointerLValue( 2746 CGF.GetAddrOfLocalVar(&TaskTypeArg), 2747 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 2748 auto *KmpTaskTWithPrivatesQTyRD = 2749 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 2750 LValue Base = 2751 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 2752 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 2753 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 2754 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 2755 auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal(); 2756 2757 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 2758 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 2759 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2760 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(), 2761 CGF.ConvertTypeForMem(SharedsPtrTy)); 2762 2763 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 2764 llvm::Value *PrivatesParam; 2765 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 2766 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 2767 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2768 PrivatesLVal.getPointer(), CGF.VoidPtrTy); 2769 } else { 2770 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 2771 } 2772 2773 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam, 2774 TaskPrivatesMap, SharedsParam}; 2775 CGF.EmitCallOrInvoke(TaskFunction, CallArgs); 2776 CGF.EmitStoreThroughLValue( 2777 RValue::get(CGF.Builder.getInt32(/*C=*/0)), 2778 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 2779 CGF.FinishFunction(); 2780 return TaskEntry; 2781 } 2782 2783 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 2784 SourceLocation Loc, 2785 QualType KmpInt32Ty, 2786 QualType KmpTaskTWithPrivatesPtrQTy, 2787 QualType KmpTaskTWithPrivatesQTy) { 2788 auto &C = CGM.getContext(); 2789 FunctionArgList Args; 2790 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 2791 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 2792 /*Id=*/nullptr, 2793 KmpTaskTWithPrivatesPtrQTy.withRestrict()); 2794 Args.push_back(&GtidArg); 2795 Args.push_back(&TaskTypeArg); 2796 FunctionType::ExtInfo Info; 2797 auto &DestructorFnInfo = 2798 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info, 2799 /*isVariadic=*/false); 2800 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo); 2801 auto *DestructorFn = 2802 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 2803 ".omp_task_destructor.", &CGM.getModule()); 2804 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn, 2805 DestructorFnInfo); 2806 CodeGenFunction CGF(CGM); 2807 CGF.disableDebugInfo(); 2808 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 2809 Args); 2810 2811 LValue Base = CGF.EmitLoadOfPointerLValue( 2812 CGF.GetAddrOfLocalVar(&TaskTypeArg), 2813 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 2814 auto *KmpTaskTWithPrivatesQTyRD = 2815 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 2816 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 2817 Base = CGF.EmitLValueForField(Base, *FI); 2818 for (auto *Field : 2819 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 2820 if (auto DtorKind = Field->getType().isDestructedType()) { 2821 auto FieldLValue = CGF.EmitLValueForField(Base, Field); 2822 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 2823 } 2824 } 2825 CGF.FinishFunction(); 2826 return DestructorFn; 2827 } 2828 2829 /// \brief Emit a privates mapping function for correct handling of private and 2830 /// firstprivate variables. 2831 /// \code 2832 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 2833 /// **noalias priv1,..., <tyn> **noalias privn) { 2834 /// *priv1 = &.privates.priv1; 2835 /// ...; 2836 /// *privn = &.privates.privn; 2837 /// } 2838 /// \endcode 2839 static llvm::Value * 2840 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 2841 ArrayRef<const Expr *> PrivateVars, 2842 ArrayRef<const Expr *> FirstprivateVars, 2843 QualType PrivatesQTy, 2844 ArrayRef<PrivateDataTy> Privates) { 2845 auto &C = CGM.getContext(); 2846 FunctionArgList Args; 2847 ImplicitParamDecl TaskPrivatesArg( 2848 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 2849 C.getPointerType(PrivatesQTy).withConst().withRestrict()); 2850 Args.push_back(&TaskPrivatesArg); 2851 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 2852 unsigned Counter = 1; 2853 for (auto *E: PrivateVars) { 2854 Args.push_back(ImplicitParamDecl::Create( 2855 C, /*DC=*/nullptr, Loc, 2856 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 2857 .withConst() 2858 .withRestrict())); 2859 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2860 PrivateVarsPos[VD] = Counter; 2861 ++Counter; 2862 } 2863 for (auto *E : FirstprivateVars) { 2864 Args.push_back(ImplicitParamDecl::Create( 2865 C, /*DC=*/nullptr, Loc, 2866 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 2867 .withConst() 2868 .withRestrict())); 2869 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2870 PrivateVarsPos[VD] = Counter; 2871 ++Counter; 2872 } 2873 FunctionType::ExtInfo Info; 2874 auto &TaskPrivatesMapFnInfo = 2875 CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info, 2876 /*isVariadic=*/false); 2877 auto *TaskPrivatesMapTy = 2878 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 2879 auto *TaskPrivatesMap = llvm::Function::Create( 2880 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, 2881 ".omp_task_privates_map.", &CGM.getModule()); 2882 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap, 2883 TaskPrivatesMapFnInfo); 2884 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 2885 CodeGenFunction CGF(CGM); 2886 CGF.disableDebugInfo(); 2887 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 2888 TaskPrivatesMapFnInfo, Args); 2889 2890 // *privi = &.privates.privi; 2891 LValue Base = CGF.EmitLoadOfPointerLValue( 2892 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 2893 TaskPrivatesArg.getType()->castAs<PointerType>()); 2894 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 2895 Counter = 0; 2896 for (auto *Field : PrivatesQTyRD->fields()) { 2897 auto FieldLVal = CGF.EmitLValueForField(Base, Field); 2898 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 2899 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 2900 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue( 2901 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); 2902 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); 2903 ++Counter; 2904 } 2905 CGF.FinishFunction(); 2906 return TaskPrivatesMap; 2907 } 2908 2909 static int array_pod_sort_comparator(const PrivateDataTy *P1, 2910 const PrivateDataTy *P2) { 2911 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0); 2912 } 2913 2914 void CGOpenMPRuntime::emitTaskCall( 2915 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, 2916 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, 2917 llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds, 2918 const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, 2919 ArrayRef<const Expr *> PrivateCopies, 2920 ArrayRef<const Expr *> FirstprivateVars, 2921 ArrayRef<const Expr *> FirstprivateCopies, 2922 ArrayRef<const Expr *> FirstprivateInits, 2923 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) { 2924 if (!CGF.HaveInsertPoint()) 2925 return; 2926 auto &C = CGM.getContext(); 2927 llvm::SmallVector<PrivateDataTy, 8> Privates; 2928 // Aggregate privates and sort them by the alignment. 2929 auto I = PrivateCopies.begin(); 2930 for (auto *E : PrivateVars) { 2931 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2932 Privates.push_back(std::make_pair( 2933 C.getDeclAlign(VD), 2934 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 2935 /*PrivateElemInit=*/nullptr))); 2936 ++I; 2937 } 2938 I = FirstprivateCopies.begin(); 2939 auto IElemInitRef = FirstprivateInits.begin(); 2940 for (auto *E : FirstprivateVars) { 2941 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2942 Privates.push_back(std::make_pair( 2943 C.getDeclAlign(VD), 2944 PrivateHelpersTy( 2945 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 2946 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())))); 2947 ++I; 2948 ++IElemInitRef; 2949 } 2950 llvm::array_pod_sort(Privates.begin(), Privates.end(), 2951 array_pod_sort_comparator); 2952 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2953 // Build type kmp_routine_entry_t (if not built yet). 2954 emitKmpRoutineEntryT(KmpInt32Ty); 2955 // Build type kmp_task_t (if not built yet). 2956 if (KmpTaskTQTy.isNull()) { 2957 KmpTaskTQTy = C.getRecordType( 2958 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy)); 2959 } 2960 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 2961 // Build particular struct kmp_task_t for the given task. 2962 auto *KmpTaskTWithPrivatesQTyRD = 2963 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 2964 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 2965 QualType KmpTaskTWithPrivatesPtrQTy = 2966 C.getPointerType(KmpTaskTWithPrivatesQTy); 2967 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 2968 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo(); 2969 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 2970 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 2971 2972 // Emit initial values for private copies (if any). 2973 llvm::Value *TaskPrivatesMap = nullptr; 2974 auto *TaskPrivatesMapTy = 2975 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(), 2976 3) 2977 ->getType(); 2978 if (!Privates.empty()) { 2979 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 2980 TaskPrivatesMap = emitTaskPrivateMappingFunction( 2981 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates); 2982 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2983 TaskPrivatesMap, TaskPrivatesMapTy); 2984 } else { 2985 TaskPrivatesMap = llvm::ConstantPointerNull::get( 2986 cast<llvm::PointerType>(TaskPrivatesMapTy)); 2987 } 2988 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 2989 // kmp_task_t *tt); 2990 auto *TaskEntry = emitProxyTaskFunction( 2991 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy, 2992 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap); 2993 2994 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2995 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2996 // kmp_routine_entry_t *task_entry); 2997 // Task flags. Format is taken from 2998 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h, 2999 // description of kmp_tasking_flags struct. 3000 const unsigned TiedFlag = 0x1; 3001 const unsigned FinalFlag = 0x2; 3002 unsigned Flags = Tied ? TiedFlag : 0; 3003 auto *TaskFlags = 3004 Final.getPointer() 3005 ? CGF.Builder.CreateSelect(Final.getPointer(), 3006 CGF.Builder.getInt32(FinalFlag), 3007 CGF.Builder.getInt32(/*C=*/0)) 3008 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0); 3009 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 3010 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 3011 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc), 3012 getThreadID(CGF, Loc), TaskFlags, 3013 KmpTaskTWithPrivatesTySize, SharedsSize, 3014 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3015 TaskEntry, KmpRoutineEntryPtrTy)}; 3016 auto *NewTask = CGF.EmitRuntimeCall( 3017 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 3018 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3019 NewTask, KmpTaskTWithPrivatesPtrTy); 3020 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 3021 KmpTaskTWithPrivatesQTy); 3022 LValue TDBase = 3023 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3024 // Fill the data in the resulting kmp_task_t record. 3025 // Copy shareds if there are any. 3026 Address KmpTaskSharedsPtr = Address::invalid(); 3027 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 3028 KmpTaskSharedsPtr = 3029 Address(CGF.EmitLoadOfScalar( 3030 CGF.EmitLValueForField( 3031 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 3032 KmpTaskTShareds)), 3033 Loc), 3034 CGF.getNaturalTypeAlignment(SharedsTy)); 3035 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy); 3036 } 3037 // Emit initial values for private copies (if any). 3038 bool NeedsCleanup = false; 3039 if (!Privates.empty()) { 3040 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3041 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI); 3042 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3043 LValue SharedsBase; 3044 if (!FirstprivateVars.empty()) { 3045 SharedsBase = CGF.MakeAddrLValue( 3046 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3047 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3048 SharedsTy); 3049 } 3050 CodeGenFunction::CGCapturedStmtInfo CapturesInfo( 3051 cast<CapturedStmt>(*D.getAssociatedStmt())); 3052 for (auto &&Pair : Privates) { 3053 auto *VD = Pair.second.PrivateCopy; 3054 auto *Init = VD->getAnyInitializer(); 3055 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3056 if (Init) { 3057 if (auto *Elem = Pair.second.PrivateElemInit) { 3058 auto *OriginalVD = Pair.second.Original; 3059 auto *SharedField = CapturesInfo.lookup(OriginalVD); 3060 auto SharedRefLValue = 3061 CGF.EmitLValueForField(SharedsBase, SharedField); 3062 SharedRefLValue = CGF.MakeAddrLValue( 3063 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), 3064 SharedRefLValue.getType(), AlignmentSource::Decl); 3065 QualType Type = OriginalVD->getType(); 3066 if (Type->isArrayType()) { 3067 // Initialize firstprivate array. 3068 if (!isa<CXXConstructExpr>(Init) || 3069 CGF.isTrivialInitializer(Init)) { 3070 // Perform simple memcpy. 3071 CGF.EmitAggregateAssign(PrivateLValue.getAddress(), 3072 SharedRefLValue.getAddress(), Type); 3073 } else { 3074 // Initialize firstprivate array using element-by-element 3075 // intialization. 3076 CGF.EmitOMPAggregateAssign( 3077 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), 3078 Type, [&CGF, Elem, Init, &CapturesInfo]( 3079 Address DestElement, Address SrcElement) { 3080 // Clean up any temporaries needed by the initialization. 3081 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3082 InitScope.addPrivate(Elem, [SrcElement]() -> Address { 3083 return SrcElement; 3084 }); 3085 (void)InitScope.Privatize(); 3086 // Emit initialization for single element. 3087 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3088 CGF, &CapturesInfo); 3089 CGF.EmitAnyExprToMem(Init, DestElement, 3090 Init->getType().getQualifiers(), 3091 /*IsInitializer=*/false); 3092 }); 3093 } 3094 } else { 3095 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3096 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { 3097 return SharedRefLValue.getAddress(); 3098 }); 3099 (void)InitScope.Privatize(); 3100 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3101 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3102 /*capturedByInit=*/false); 3103 } 3104 } else { 3105 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3106 } 3107 } 3108 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType(); 3109 ++FI; 3110 } 3111 } 3112 // Provide pointer to function with destructors for privates. 3113 llvm::Value *DestructorFn = 3114 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty, 3115 KmpTaskTWithPrivatesPtrQTy, 3116 KmpTaskTWithPrivatesQTy) 3117 : llvm::ConstantPointerNull::get( 3118 cast<llvm::PointerType>(KmpRoutineEntryPtrTy)); 3119 LValue Destructor = CGF.EmitLValueForField( 3120 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors)); 3121 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3122 DestructorFn, KmpRoutineEntryPtrTy), 3123 Destructor); 3124 3125 // Process list of dependences. 3126 Address DependenciesArray = Address::invalid(); 3127 unsigned NumDependencies = Dependences.size(); 3128 if (NumDependencies) { 3129 // Dependence kind for RTL. 3130 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 }; 3131 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 3132 RecordDecl *KmpDependInfoRD; 3133 QualType FlagsTy = 3134 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 3135 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 3136 if (KmpDependInfoTy.isNull()) { 3137 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 3138 KmpDependInfoRD->startDefinition(); 3139 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 3140 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 3141 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 3142 KmpDependInfoRD->completeDefinition(); 3143 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 3144 } else { 3145 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 3146 } 3147 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy); 3148 // Define type kmp_depend_info[<Dependences.size()>]; 3149 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 3150 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 3151 ArrayType::Normal, /*IndexTypeQuals=*/0); 3152 // kmp_depend_info[<Dependences.size()>] deps; 3153 DependenciesArray = CGF.CreateMemTemp(KmpDependInfoArrayTy); 3154 for (unsigned i = 0; i < NumDependencies; ++i) { 3155 const Expr *E = Dependences[i].second; 3156 auto Addr = CGF.EmitLValue(E); 3157 llvm::Value *Size; 3158 QualType Ty = E->getType(); 3159 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 3160 LValue UpAddrLVal = 3161 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false); 3162 llvm::Value *UpAddr = 3163 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); 3164 llvm::Value *LowIntPtr = 3165 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); 3166 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 3167 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 3168 } else 3169 Size = CGF.getTypeSize(Ty); 3170 auto Base = CGF.MakeAddrLValue( 3171 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize), 3172 KmpDependInfoTy); 3173 // deps[i].base_addr = &<Dependences[i].second>; 3174 auto BaseAddrLVal = CGF.EmitLValueForField( 3175 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 3176 CGF.EmitStoreOfScalar( 3177 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), 3178 BaseAddrLVal); 3179 // deps[i].len = sizeof(<Dependences[i].second>); 3180 auto LenLVal = CGF.EmitLValueForField( 3181 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 3182 CGF.EmitStoreOfScalar(Size, LenLVal); 3183 // deps[i].flags = <Dependences[i].first>; 3184 RTLDependenceKindTy DepKind; 3185 switch (Dependences[i].first) { 3186 case OMPC_DEPEND_in: 3187 DepKind = DepIn; 3188 break; 3189 // Out and InOut dependencies must use the same code. 3190 case OMPC_DEPEND_out: 3191 case OMPC_DEPEND_inout: 3192 DepKind = DepInOut; 3193 break; 3194 case OMPC_DEPEND_source: 3195 case OMPC_DEPEND_sink: 3196 case OMPC_DEPEND_unknown: 3197 llvm_unreachable("Unknown task dependence type"); 3198 } 3199 auto FlagsLVal = CGF.EmitLValueForField( 3200 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 3201 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 3202 FlagsLVal); 3203 } 3204 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3205 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()), 3206 CGF.VoidPtrTy); 3207 } 3208 3209 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() 3210 // libcall. 3211 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 3212 // *new_task); 3213 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 3214 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 3215 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 3216 // list is not empty 3217 auto *ThreadID = getThreadID(CGF, Loc); 3218 auto *UpLoc = emitUpdateLocation(CGF, Loc); 3219 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 3220 llvm::Value *DepTaskArgs[7]; 3221 if (NumDependencies) { 3222 DepTaskArgs[0] = UpLoc; 3223 DepTaskArgs[1] = ThreadID; 3224 DepTaskArgs[2] = NewTask; 3225 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 3226 DepTaskArgs[4] = DependenciesArray.getPointer(); 3227 DepTaskArgs[5] = CGF.Builder.getInt32(0); 3228 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3229 } 3230 auto &&ThenCodeGen = [this, NumDependencies, 3231 &TaskArgs, &DepTaskArgs](CodeGenFunction &CGF) { 3232 // TODO: add check for untied tasks. 3233 if (NumDependencies) { 3234 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), 3235 DepTaskArgs); 3236 } else { 3237 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 3238 TaskArgs); 3239 } 3240 }; 3241 typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value> 3242 IfCallEndCleanup; 3243 3244 llvm::Value *DepWaitTaskArgs[6]; 3245 if (NumDependencies) { 3246 DepWaitTaskArgs[0] = UpLoc; 3247 DepWaitTaskArgs[1] = ThreadID; 3248 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 3249 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 3250 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 3251 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3252 } 3253 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 3254 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF) { 3255 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 3256 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 3257 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 3258 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 3259 // is specified. 3260 if (NumDependencies) 3261 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 3262 DepWaitTaskArgs); 3263 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 3264 // kmp_task_t *new_task); 3265 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), 3266 TaskArgs); 3267 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 3268 // kmp_task_t *new_task); 3269 CGF.EHStack.pushCleanup<IfCallEndCleanup>( 3270 NormalAndEHCleanup, 3271 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), 3272 llvm::makeArrayRef(TaskArgs)); 3273 3274 // Call proxy_task_entry(gtid, new_task); 3275 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 3276 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs); 3277 }; 3278 3279 if (IfCond) { 3280 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 3281 } else { 3282 CodeGenFunction::RunCleanupsScope Scope(CGF); 3283 ThenCodeGen(CGF); 3284 } 3285 } 3286 3287 /// \brief Emit reduction operation for each element of array (required for 3288 /// array sections) LHS op = RHS. 3289 /// \param Type Type of array. 3290 /// \param LHSVar Variable on the left side of the reduction operation 3291 /// (references element of array in original variable). 3292 /// \param RHSVar Variable on the right side of the reduction operation 3293 /// (references element of array in original variable). 3294 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 3295 /// RHSVar. 3296 static void EmitOMPAggregateReduction( 3297 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 3298 const VarDecl *RHSVar, 3299 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 3300 const Expr *, const Expr *)> &RedOpGen, 3301 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 3302 const Expr *UpExpr = nullptr) { 3303 // Perform element-by-element initialization. 3304 QualType ElementTy; 3305 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 3306 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 3307 3308 // Drill down to the base element type on both arrays. 3309 auto ArrayTy = Type->getAsArrayTypeUnsafe(); 3310 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 3311 3312 auto RHSBegin = RHSAddr.getPointer(); 3313 auto LHSBegin = LHSAddr.getPointer(); 3314 // Cast from pointer to array type to pointer to single element. 3315 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 3316 // The basic structure here is a while-do loop. 3317 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 3318 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 3319 auto IsEmpty = 3320 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 3321 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 3322 3323 // Enter the loop body, making that address the current address. 3324 auto EntryBB = CGF.Builder.GetInsertBlock(); 3325 CGF.EmitBlock(BodyBB); 3326 3327 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 3328 3329 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 3330 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 3331 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 3332 Address RHSElementCurrent = 3333 Address(RHSElementPHI, 3334 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 3335 3336 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 3337 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 3338 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 3339 Address LHSElementCurrent = 3340 Address(LHSElementPHI, 3341 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 3342 3343 // Emit copy. 3344 CodeGenFunction::OMPPrivateScope Scope(CGF); 3345 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; }); 3346 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; }); 3347 Scope.Privatize(); 3348 RedOpGen(CGF, XExpr, EExpr, UpExpr); 3349 Scope.ForceCleanup(); 3350 3351 // Shift the address forward by one element. 3352 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32( 3353 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 3354 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32( 3355 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 3356 // Check whether we've reached the end. 3357 auto Done = 3358 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 3359 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 3360 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 3361 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 3362 3363 // Done. 3364 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 3365 } 3366 3367 static llvm::Value *emitReductionFunction(CodeGenModule &CGM, 3368 llvm::Type *ArgsType, 3369 ArrayRef<const Expr *> Privates, 3370 ArrayRef<const Expr *> LHSExprs, 3371 ArrayRef<const Expr *> RHSExprs, 3372 ArrayRef<const Expr *> ReductionOps) { 3373 auto &C = CGM.getContext(); 3374 3375 // void reduction_func(void *LHSArg, void *RHSArg); 3376 FunctionArgList Args; 3377 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 3378 C.VoidPtrTy); 3379 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 3380 C.VoidPtrTy); 3381 Args.push_back(&LHSArg); 3382 Args.push_back(&RHSArg); 3383 FunctionType::ExtInfo EI; 3384 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration( 3385 C.VoidTy, Args, EI, /*isVariadic=*/false); 3386 auto *Fn = llvm::Function::Create( 3387 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 3388 ".omp.reduction.reduction_func", &CGM.getModule()); 3389 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI); 3390 CodeGenFunction CGF(CGM); 3391 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 3392 3393 // Dst = (void*[n])(LHSArg); 3394 // Src = (void*[n])(RHSArg); 3395 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3396 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3397 ArgsType), CGF.getPointerAlign()); 3398 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3399 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3400 ArgsType), CGF.getPointerAlign()); 3401 3402 // ... 3403 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 3404 // ... 3405 CodeGenFunction::OMPPrivateScope Scope(CGF); 3406 auto IPriv = Privates.begin(); 3407 unsigned Idx = 0; 3408 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 3409 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 3410 Scope.addPrivate(RHSVar, [&]() -> Address { 3411 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 3412 }); 3413 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 3414 Scope.addPrivate(LHSVar, [&]() -> Address { 3415 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 3416 }); 3417 QualType PrivTy = (*IPriv)->getType(); 3418 if (PrivTy->isVariablyModifiedType()) { 3419 // Get array size and emit VLA type. 3420 ++Idx; 3421 Address Elem = 3422 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize()); 3423 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 3424 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy); 3425 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 3426 CodeGenFunction::OpaqueValueMapping OpaqueMap( 3427 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 3428 CGF.EmitVariablyModifiedType(PrivTy); 3429 } 3430 } 3431 Scope.Privatize(); 3432 IPriv = Privates.begin(); 3433 auto ILHS = LHSExprs.begin(); 3434 auto IRHS = RHSExprs.begin(); 3435 for (auto *E : ReductionOps) { 3436 if ((*IPriv)->getType()->isArrayType()) { 3437 // Emit reduction for array section. 3438 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 3439 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 3440 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 3441 [=](CodeGenFunction &CGF, const Expr *, 3442 const Expr *, 3443 const Expr *) { CGF.EmitIgnoredExpr(E); }); 3444 } else 3445 // Emit reduction for array subscript or single variable. 3446 CGF.EmitIgnoredExpr(E); 3447 ++IPriv; 3448 ++ILHS; 3449 ++IRHS; 3450 } 3451 Scope.ForceCleanup(); 3452 CGF.FinishFunction(); 3453 return Fn; 3454 } 3455 3456 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 3457 ArrayRef<const Expr *> Privates, 3458 ArrayRef<const Expr *> LHSExprs, 3459 ArrayRef<const Expr *> RHSExprs, 3460 ArrayRef<const Expr *> ReductionOps, 3461 bool WithNowait, bool SimpleReduction) { 3462 if (!CGF.HaveInsertPoint()) 3463 return; 3464 // Next code should be emitted for reduction: 3465 // 3466 // static kmp_critical_name lock = { 0 }; 3467 // 3468 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 3469 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 3470 // ... 3471 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 3472 // *(Type<n>-1*)rhs[<n>-1]); 3473 // } 3474 // 3475 // ... 3476 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 3477 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 3478 // RedList, reduce_func, &<lock>)) { 3479 // case 1: 3480 // ... 3481 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 3482 // ... 3483 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 3484 // break; 3485 // case 2: 3486 // ... 3487 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 3488 // ... 3489 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 3490 // break; 3491 // default:; 3492 // } 3493 // 3494 // if SimpleReduction is true, only the next code is generated: 3495 // ... 3496 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 3497 // ... 3498 3499 auto &C = CGM.getContext(); 3500 3501 if (SimpleReduction) { 3502 CodeGenFunction::RunCleanupsScope Scope(CGF); 3503 auto IPriv = Privates.begin(); 3504 auto ILHS = LHSExprs.begin(); 3505 auto IRHS = RHSExprs.begin(); 3506 for (auto *E : ReductionOps) { 3507 if ((*IPriv)->getType()->isArrayType()) { 3508 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 3509 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 3510 EmitOMPAggregateReduction( 3511 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 3512 [=](CodeGenFunction &CGF, const Expr *, const Expr *, 3513 const Expr *) { CGF.EmitIgnoredExpr(E); }); 3514 } else 3515 CGF.EmitIgnoredExpr(E); 3516 ++IPriv; 3517 ++ILHS; 3518 ++IRHS; 3519 } 3520 return; 3521 } 3522 3523 // 1. Build a list of reduction variables. 3524 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 3525 auto Size = RHSExprs.size(); 3526 for (auto *E : Privates) { 3527 if (E->getType()->isVariablyModifiedType()) 3528 // Reserve place for array size. 3529 ++Size; 3530 } 3531 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 3532 QualType ReductionArrayTy = 3533 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 3534 /*IndexTypeQuals=*/0); 3535 Address ReductionList = 3536 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 3537 auto IPriv = Privates.begin(); 3538 unsigned Idx = 0; 3539 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 3540 Address Elem = 3541 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize()); 3542 CGF.Builder.CreateStore( 3543 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3544 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 3545 Elem); 3546 if ((*IPriv)->getType()->isVariablyModifiedType()) { 3547 // Store array size. 3548 ++Idx; 3549 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, 3550 CGF.getPointerSize()); 3551 llvm::Value *Size = CGF.Builder.CreateIntCast( 3552 CGF.getVLASize( 3553 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 3554 .first, 3555 CGF.SizeTy, /*isSigned=*/false); 3556 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 3557 Elem); 3558 } 3559 } 3560 3561 // 2. Emit reduce_func(). 3562 auto *ReductionFn = emitReductionFunction( 3563 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 3564 LHSExprs, RHSExprs, ReductionOps); 3565 3566 // 3. Create static kmp_critical_name lock = { 0 }; 3567 auto *Lock = getCriticalRegionLock(".reduction"); 3568 3569 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 3570 // RedList, reduce_func, &<lock>); 3571 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 3572 auto *ThreadId = getThreadID(CGF, Loc); 3573 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 3574 auto *RL = 3575 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(), 3576 CGF.VoidPtrTy); 3577 llvm::Value *Args[] = { 3578 IdentTLoc, // ident_t *<loc> 3579 ThreadId, // i32 <gtid> 3580 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 3581 ReductionArrayTySize, // size_type sizeof(RedList) 3582 RL, // void *RedList 3583 ReductionFn, // void (*) (void *, void *) <reduce_func> 3584 Lock // kmp_critical_name *&<lock> 3585 }; 3586 auto Res = CGF.EmitRuntimeCall( 3587 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 3588 : OMPRTL__kmpc_reduce), 3589 Args); 3590 3591 // 5. Build switch(res) 3592 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 3593 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 3594 3595 // 6. Build case 1: 3596 // ... 3597 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 3598 // ... 3599 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 3600 // break; 3601 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 3602 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 3603 CGF.EmitBlock(Case1BB); 3604 3605 { 3606 CodeGenFunction::RunCleanupsScope Scope(CGF); 3607 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 3608 llvm::Value *EndArgs[] = { 3609 IdentTLoc, // ident_t *<loc> 3610 ThreadId, // i32 <gtid> 3611 Lock // kmp_critical_name *&<lock> 3612 }; 3613 CGF.EHStack 3614 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>( 3615 NormalAndEHCleanup, 3616 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 3617 : OMPRTL__kmpc_end_reduce), 3618 llvm::makeArrayRef(EndArgs)); 3619 auto IPriv = Privates.begin(); 3620 auto ILHS = LHSExprs.begin(); 3621 auto IRHS = RHSExprs.begin(); 3622 for (auto *E : ReductionOps) { 3623 if ((*IPriv)->getType()->isArrayType()) { 3624 // Emit reduction for array section. 3625 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 3626 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 3627 EmitOMPAggregateReduction( 3628 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 3629 [=](CodeGenFunction &CGF, const Expr *, const Expr *, 3630 const Expr *) { CGF.EmitIgnoredExpr(E); }); 3631 } else 3632 // Emit reduction for array subscript or single variable. 3633 CGF.EmitIgnoredExpr(E); 3634 ++IPriv; 3635 ++ILHS; 3636 ++IRHS; 3637 } 3638 } 3639 3640 CGF.EmitBranch(DefaultBB); 3641 3642 // 7. Build case 2: 3643 // ... 3644 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 3645 // ... 3646 // break; 3647 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 3648 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 3649 CGF.EmitBlock(Case2BB); 3650 3651 { 3652 CodeGenFunction::RunCleanupsScope Scope(CGF); 3653 if (!WithNowait) { 3654 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 3655 llvm::Value *EndArgs[] = { 3656 IdentTLoc, // ident_t *<loc> 3657 ThreadId, // i32 <gtid> 3658 Lock // kmp_critical_name *&<lock> 3659 }; 3660 CGF.EHStack 3661 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>( 3662 NormalAndEHCleanup, 3663 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 3664 llvm::makeArrayRef(EndArgs)); 3665 } 3666 auto ILHS = LHSExprs.begin(); 3667 auto IRHS = RHSExprs.begin(); 3668 auto IPriv = Privates.begin(); 3669 for (auto *E : ReductionOps) { 3670 const Expr *XExpr = nullptr; 3671 const Expr *EExpr = nullptr; 3672 const Expr *UpExpr = nullptr; 3673 BinaryOperatorKind BO = BO_Comma; 3674 if (auto *BO = dyn_cast<BinaryOperator>(E)) { 3675 if (BO->getOpcode() == BO_Assign) { 3676 XExpr = BO->getLHS(); 3677 UpExpr = BO->getRHS(); 3678 } 3679 } 3680 // Try to emit update expression as a simple atomic. 3681 auto *RHSExpr = UpExpr; 3682 if (RHSExpr) { 3683 // Analyze RHS part of the whole expression. 3684 if (auto *ACO = dyn_cast<AbstractConditionalOperator>( 3685 RHSExpr->IgnoreParenImpCasts())) { 3686 // If this is a conditional operator, analyze its condition for 3687 // min/max reduction operator. 3688 RHSExpr = ACO->getCond(); 3689 } 3690 if (auto *BORHS = 3691 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 3692 EExpr = BORHS->getRHS(); 3693 BO = BORHS->getOpcode(); 3694 } 3695 } 3696 if (XExpr) { 3697 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 3698 auto &&AtomicRedGen = [this, BO, VD, IPriv, 3699 Loc](CodeGenFunction &CGF, const Expr *XExpr, 3700 const Expr *EExpr, const Expr *UpExpr) { 3701 LValue X = CGF.EmitLValue(XExpr); 3702 RValue E; 3703 if (EExpr) 3704 E = CGF.EmitAnyExpr(EExpr); 3705 CGF.EmitOMPAtomicSimpleUpdateExpr( 3706 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc, 3707 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) { 3708 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 3709 PrivateScope.addPrivate( 3710 VD, [&CGF, VD, XRValue, Loc]() -> Address { 3711 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 3712 CGF.emitOMPSimpleStore( 3713 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 3714 VD->getType().getNonReferenceType(), Loc); 3715 return LHSTemp; 3716 }); 3717 (void)PrivateScope.Privatize(); 3718 return CGF.EmitAnyExpr(UpExpr); 3719 }); 3720 }; 3721 if ((*IPriv)->getType()->isArrayType()) { 3722 // Emit atomic reduction for array section. 3723 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 3724 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 3725 AtomicRedGen, XExpr, EExpr, UpExpr); 3726 } else 3727 // Emit atomic reduction for array subscript or single variable. 3728 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 3729 } else { 3730 // Emit as a critical region. 3731 auto &&CritRedGen = [this, E, Loc](CodeGenFunction &CGF, const Expr *, 3732 const Expr *, const Expr *) { 3733 emitCriticalRegion( 3734 CGF, ".atomic_reduction", 3735 [E](CodeGenFunction &CGF) { CGF.EmitIgnoredExpr(E); }, Loc); 3736 }; 3737 if ((*IPriv)->getType()->isArrayType()) { 3738 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 3739 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 3740 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 3741 CritRedGen); 3742 } else 3743 CritRedGen(CGF, nullptr, nullptr, nullptr); 3744 } 3745 ++ILHS; 3746 ++IRHS; 3747 ++IPriv; 3748 } 3749 } 3750 3751 CGF.EmitBranch(DefaultBB); 3752 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 3753 } 3754 3755 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 3756 SourceLocation Loc) { 3757 if (!CGF.HaveInsertPoint()) 3758 return; 3759 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 3760 // global_tid); 3761 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3762 // Ignore return result until untied tasks are supported. 3763 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 3764 } 3765 3766 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 3767 OpenMPDirectiveKind InnerKind, 3768 const RegionCodeGenTy &CodeGen, 3769 bool HasCancel) { 3770 if (!CGF.HaveInsertPoint()) 3771 return; 3772 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 3773 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 3774 } 3775 3776 namespace { 3777 enum RTCancelKind { 3778 CancelNoreq = 0, 3779 CancelParallel = 1, 3780 CancelLoop = 2, 3781 CancelSections = 3, 3782 CancelTaskgroup = 4 3783 }; 3784 } // anonymous namespace 3785 3786 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 3787 RTCancelKind CancelKind = CancelNoreq; 3788 if (CancelRegion == OMPD_parallel) 3789 CancelKind = CancelParallel; 3790 else if (CancelRegion == OMPD_for) 3791 CancelKind = CancelLoop; 3792 else if (CancelRegion == OMPD_sections) 3793 CancelKind = CancelSections; 3794 else { 3795 assert(CancelRegion == OMPD_taskgroup); 3796 CancelKind = CancelTaskgroup; 3797 } 3798 return CancelKind; 3799 } 3800 3801 void CGOpenMPRuntime::emitCancellationPointCall( 3802 CodeGenFunction &CGF, SourceLocation Loc, 3803 OpenMPDirectiveKind CancelRegion) { 3804 if (!CGF.HaveInsertPoint()) 3805 return; 3806 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 3807 // global_tid, kmp_int32 cncl_kind); 3808 if (auto *OMPRegionInfo = 3809 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 3810 if (OMPRegionInfo->hasCancel()) { 3811 llvm::Value *Args[] = { 3812 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3813 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 3814 // Ignore return result until untied tasks are supported. 3815 auto *Result = CGF.EmitRuntimeCall( 3816 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 3817 // if (__kmpc_cancellationpoint()) { 3818 // __kmpc_cancel_barrier(); 3819 // exit from construct; 3820 // } 3821 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3822 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 3823 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 3824 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3825 CGF.EmitBlock(ExitBB); 3826 // __kmpc_cancel_barrier(); 3827 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 3828 // exit from construct; 3829 auto CancelDest = 3830 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3831 CGF.EmitBranchThroughCleanup(CancelDest); 3832 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3833 } 3834 } 3835 } 3836 3837 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 3838 const Expr *IfCond, 3839 OpenMPDirectiveKind CancelRegion) { 3840 if (!CGF.HaveInsertPoint()) 3841 return; 3842 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 3843 // kmp_int32 cncl_kind); 3844 if (auto *OMPRegionInfo = 3845 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 3846 auto &&ThenGen = [this, Loc, CancelRegion, 3847 OMPRegionInfo](CodeGenFunction &CGF) { 3848 llvm::Value *Args[] = { 3849 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3850 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 3851 // Ignore return result until untied tasks are supported. 3852 auto *Result = 3853 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 3854 // if (__kmpc_cancel()) { 3855 // __kmpc_cancel_barrier(); 3856 // exit from construct; 3857 // } 3858 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3859 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 3860 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 3861 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3862 CGF.EmitBlock(ExitBB); 3863 // __kmpc_cancel_barrier(); 3864 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 3865 // exit from construct; 3866 auto CancelDest = 3867 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3868 CGF.EmitBranchThroughCleanup(CancelDest); 3869 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3870 }; 3871 if (IfCond) 3872 emitOMPIfClause(CGF, IfCond, ThenGen, [](CodeGenFunction &) {}); 3873 else 3874 ThenGen(CGF); 3875 } 3876 } 3877 3878 /// \brief Obtain information that uniquely identifies a target entry. This 3879 /// consists of the file and device IDs as well as line number associated with 3880 /// the relevant entry source location. 3881 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 3882 unsigned &DeviceID, unsigned &FileID, 3883 unsigned &LineNum) { 3884 3885 auto &SM = C.getSourceManager(); 3886 3887 // The loc should be always valid and have a file ID (the user cannot use 3888 // #pragma directives in macros) 3889 3890 assert(Loc.isValid() && "Source location is expected to be always valid."); 3891 assert(Loc.isFileID() && "Source location is expected to refer to a file."); 3892 3893 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 3894 assert(PLoc.isValid() && "Source location is expected to be always valid."); 3895 3896 llvm::sys::fs::UniqueID ID; 3897 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 3898 llvm_unreachable("Source file with target region no longer exists!"); 3899 3900 DeviceID = ID.getDevice(); 3901 FileID = ID.getFile(); 3902 LineNum = PLoc.getLine(); 3903 } 3904 3905 void CGOpenMPRuntime::emitTargetOutlinedFunction( 3906 const OMPExecutableDirective &D, StringRef ParentName, 3907 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 3908 bool IsOffloadEntry) { 3909 assert(!ParentName.empty() && "Invalid target region parent name!"); 3910 3911 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 3912 3913 // Emit target region as a standalone region. 3914 auto &&CodeGen = [&CS](CodeGenFunction &CGF) { 3915 CGF.EmitStmt(CS.getCapturedStmt()); 3916 }; 3917 3918 // Create a unique name for the entry function using the source location 3919 // information of the current target region. The name will be something like: 3920 // 3921 // __omp_offloading_DD_FFFF_PP_lBB 3922 // 3923 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 3924 // mangled name of the function that encloses the target region and BB is the 3925 // line number of the target region. 3926 3927 unsigned DeviceID; 3928 unsigned FileID; 3929 unsigned Line; 3930 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID, 3931 Line); 3932 SmallString<64> EntryFnName; 3933 { 3934 llvm::raw_svector_ostream OS(EntryFnName); 3935 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 3936 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 3937 } 3938 3939 CodeGenFunction CGF(CGM, true); 3940 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 3941 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 3942 3943 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 3944 3945 // If this target outline function is not an offload entry, we don't need to 3946 // register it. 3947 if (!IsOffloadEntry) 3948 return; 3949 3950 // The target region ID is used by the runtime library to identify the current 3951 // target region, so it only has to be unique and not necessarily point to 3952 // anything. It could be the pointer to the outlined function that implements 3953 // the target region, but we aren't using that so that the compiler doesn't 3954 // need to keep that, and could therefore inline the host function if proven 3955 // worthwhile during optimization. In the other hand, if emitting code for the 3956 // device, the ID has to be the function address so that it can retrieved from 3957 // the offloading entry and launched by the runtime library. We also mark the 3958 // outlined function to have external linkage in case we are emitting code for 3959 // the device, because these functions will be entry points to the device. 3960 3961 if (CGM.getLangOpts().OpenMPIsDevice) { 3962 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 3963 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage); 3964 } else 3965 OutlinedFnID = new llvm::GlobalVariable( 3966 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 3967 llvm::GlobalValue::PrivateLinkage, 3968 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id"); 3969 3970 // Register the information for the entry associated with this target region. 3971 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 3972 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID); 3973 } 3974 3975 void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, 3976 const OMPExecutableDirective &D, 3977 llvm::Value *OutlinedFn, 3978 llvm::Value *OutlinedFnID, 3979 const Expr *IfCond, const Expr *Device, 3980 ArrayRef<llvm::Value *> CapturedVars) { 3981 if (!CGF.HaveInsertPoint()) 3982 return; 3983 /// \brief Values for bit flags used to specify the mapping type for 3984 /// offloading. 3985 enum OpenMPOffloadMappingFlags { 3986 /// \brief Allocate memory on the device and move data from host to device. 3987 OMP_MAP_TO = 0x01, 3988 /// \brief Allocate memory on the device and move data from device to host. 3989 OMP_MAP_FROM = 0x02, 3990 /// \brief The element passed to the device is a pointer. 3991 OMP_MAP_PTR = 0x20, 3992 /// \brief Pass the element to the device by value. 3993 OMP_MAP_BYCOPY = 0x80, 3994 }; 3995 3996 enum OpenMPOffloadingReservedDeviceIDs { 3997 /// \brief Device ID if the device was not defined, runtime should get it 3998 /// from environment variables in the spec. 3999 OMP_DEVICEID_UNDEF = -1, 4000 }; 4001 4002 assert(OutlinedFn && "Invalid outlined function!"); 4003 4004 auto &Ctx = CGF.getContext(); 4005 4006 // Fill up the arrays with the all the captured variables. 4007 SmallVector<llvm::Value *, 16> BasePointers; 4008 SmallVector<llvm::Value *, 16> Pointers; 4009 SmallVector<llvm::Value *, 16> Sizes; 4010 SmallVector<unsigned, 16> MapTypes; 4011 4012 bool hasVLACaptures = false; 4013 4014 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4015 auto RI = CS.getCapturedRecordDecl()->field_begin(); 4016 // auto II = CS.capture_init_begin(); 4017 auto CV = CapturedVars.begin(); 4018 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 4019 CE = CS.capture_end(); 4020 CI != CE; ++CI, ++RI, ++CV) { 4021 StringRef Name; 4022 QualType Ty; 4023 llvm::Value *BasePointer; 4024 llvm::Value *Pointer; 4025 llvm::Value *Size; 4026 unsigned MapType; 4027 4028 // VLA sizes are passed to the outlined region by copy. 4029 if (CI->capturesVariableArrayType()) { 4030 BasePointer = Pointer = *CV; 4031 Size = CGF.getTypeSize(RI->getType()); 4032 // Copy to the device as an argument. No need to retrieve it. 4033 MapType = OMP_MAP_BYCOPY; 4034 hasVLACaptures = true; 4035 } else if (CI->capturesThis()) { 4036 BasePointer = Pointer = *CV; 4037 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr()); 4038 Size = CGF.getTypeSize(PtrTy->getPointeeType()); 4039 // Default map type. 4040 MapType = OMP_MAP_TO | OMP_MAP_FROM; 4041 } else if (CI->capturesVariableByCopy()) { 4042 MapType = OMP_MAP_BYCOPY; 4043 if (!RI->getType()->isAnyPointerType()) { 4044 // If the field is not a pointer, we need to save the actual value and 4045 // load it as a void pointer. 4046 auto DstAddr = CGF.CreateMemTemp( 4047 Ctx.getUIntPtrType(), 4048 Twine(CI->getCapturedVar()->getName()) + ".casted"); 4049 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); 4050 4051 auto *SrcAddrVal = CGF.EmitScalarConversion( 4052 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), 4053 Ctx.getPointerType(RI->getType()), SourceLocation()); 4054 LValue SrcLV = 4055 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType()); 4056 4057 // Store the value using the source type pointer. 4058 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV); 4059 4060 // Load the value using the destination type pointer. 4061 BasePointer = Pointer = 4062 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal(); 4063 } else { 4064 MapType |= OMP_MAP_PTR; 4065 BasePointer = Pointer = *CV; 4066 } 4067 Size = CGF.getTypeSize(RI->getType()); 4068 } else { 4069 assert(CI->capturesVariable() && "Expected captured reference."); 4070 BasePointer = Pointer = *CV; 4071 4072 const ReferenceType *PtrTy = 4073 cast<ReferenceType>(RI->getType().getTypePtr()); 4074 QualType ElementType = PtrTy->getPointeeType(); 4075 Size = CGF.getTypeSize(ElementType); 4076 // The default map type for a scalar/complex type is 'to' because by 4077 // default the value doesn't have to be retrieved. For an aggregate type, 4078 // the default is 'tofrom'. 4079 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM) 4080 : OMP_MAP_TO; 4081 if (ElementType->isAnyPointerType()) 4082 MapType |= OMP_MAP_PTR; 4083 } 4084 4085 BasePointers.push_back(BasePointer); 4086 Pointers.push_back(Pointer); 4087 Sizes.push_back(Size); 4088 MapTypes.push_back(MapType); 4089 } 4090 4091 // Keep track on whether the host function has to be executed. 4092 auto OffloadErrorQType = 4093 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true); 4094 auto OffloadError = CGF.MakeAddrLValue( 4095 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"), 4096 OffloadErrorQType); 4097 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty), 4098 OffloadError); 4099 4100 // Fill up the pointer arrays and transfer execution to the device. 4101 auto &&ThenGen = [this, &Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes, 4102 hasVLACaptures, Device, OutlinedFnID, OffloadError, 4103 OffloadErrorQType](CodeGenFunction &CGF) { 4104 unsigned PointerNumVal = BasePointers.size(); 4105 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal); 4106 llvm::Value *BasePointersArray; 4107 llvm::Value *PointersArray; 4108 llvm::Value *SizesArray; 4109 llvm::Value *MapTypesArray; 4110 4111 if (PointerNumVal) { 4112 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true); 4113 QualType PointerArrayType = Ctx.getConstantArrayType( 4114 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal, 4115 /*IndexTypeQuals=*/0); 4116 4117 BasePointersArray = 4118 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 4119 PointersArray = 4120 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 4121 4122 // If we don't have any VLA types, we can use a constant array for the map 4123 // sizes, otherwise we need to fill up the arrays as we do for the 4124 // pointers. 4125 if (hasVLACaptures) { 4126 QualType SizeArrayType = Ctx.getConstantArrayType( 4127 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal, 4128 /*IndexTypeQuals=*/0); 4129 SizesArray = 4130 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 4131 } else { 4132 // We expect all the sizes to be constant, so we collect them to create 4133 // a constant array. 4134 SmallVector<llvm::Constant *, 16> ConstSizes; 4135 for (auto S : Sizes) 4136 ConstSizes.push_back(cast<llvm::Constant>(S)); 4137 4138 auto *SizesArrayInit = llvm::ConstantArray::get( 4139 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes); 4140 auto *SizesArrayGbl = new llvm::GlobalVariable( 4141 CGM.getModule(), SizesArrayInit->getType(), 4142 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 4143 SizesArrayInit, ".offload_sizes"); 4144 SizesArrayGbl->setUnnamedAddr(true); 4145 SizesArray = SizesArrayGbl; 4146 } 4147 4148 // The map types are always constant so we don't need to generate code to 4149 // fill arrays. Instead, we create an array constant. 4150 llvm::Constant *MapTypesArrayInit = 4151 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes); 4152 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 4153 CGM.getModule(), MapTypesArrayInit->getType(), 4154 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 4155 MapTypesArrayInit, ".offload_maptypes"); 4156 MapTypesArrayGbl->setUnnamedAddr(true); 4157 MapTypesArray = MapTypesArrayGbl; 4158 4159 for (unsigned i = 0; i < PointerNumVal; ++i) { 4160 llvm::Value *BPVal = BasePointers[i]; 4161 if (BPVal->getType()->isPointerTy()) 4162 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy); 4163 else { 4164 assert(BPVal->getType()->isIntegerTy() && 4165 "If not a pointer, the value type must be an integer."); 4166 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy); 4167 } 4168 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 4169 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), 4170 BasePointersArray, 0, i); 4171 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 4172 CGF.Builder.CreateStore(BPVal, BPAddr); 4173 4174 llvm::Value *PVal = Pointers[i]; 4175 if (PVal->getType()->isPointerTy()) 4176 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy); 4177 else { 4178 assert(PVal->getType()->isIntegerTy() && 4179 "If not a pointer, the value type must be an integer."); 4180 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy); 4181 } 4182 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 4183 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray, 4184 0, i); 4185 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 4186 CGF.Builder.CreateStore(PVal, PAddr); 4187 4188 if (hasVLACaptures) { 4189 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 4190 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray, 4191 /*Idx0=*/0, 4192 /*Idx1=*/i); 4193 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType())); 4194 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast( 4195 Sizes[i], CGM.SizeTy, /*isSigned=*/true), 4196 SAddr); 4197 } 4198 } 4199 4200 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32( 4201 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray, 4202 /*Idx0=*/0, /*Idx1=*/0); 4203 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32( 4204 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray, 4205 /*Idx0=*/0, 4206 /*Idx1=*/0); 4207 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32( 4208 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray, 4209 /*Idx0=*/0, /*Idx1=*/0); 4210 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32( 4211 llvm::ArrayType::get(CGM.Int32Ty, PointerNumVal), MapTypesArray, 4212 /*Idx0=*/0, 4213 /*Idx1=*/0); 4214 4215 } else { 4216 BasePointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 4217 PointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 4218 SizesArray = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo()); 4219 MapTypesArray = 4220 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()); 4221 } 4222 4223 // On top of the arrays that were filled up, the target offloading call 4224 // takes as arguments the device id as well as the host pointer. The host 4225 // pointer is used by the runtime library to identify the current target 4226 // region, so it only has to be unique and not necessarily point to 4227 // anything. It could be the pointer to the outlined function that 4228 // implements the target region, but we aren't using that so that the 4229 // compiler doesn't need to keep that, and could therefore inline the host 4230 // function if proven worthwhile during optimization. 4231 4232 // From this point on, we need to have an ID of the target region defined. 4233 assert(OutlinedFnID && "Invalid outlined function ID!"); 4234 4235 // Emit device ID if any. 4236 llvm::Value *DeviceID; 4237 if (Device) 4238 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4239 CGM.Int32Ty, /*isSigned=*/true); 4240 else 4241 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 4242 4243 llvm::Value *OffloadingArgs[] = { 4244 DeviceID, OutlinedFnID, PointerNum, BasePointersArray, 4245 PointersArray, SizesArray, MapTypesArray}; 4246 auto Return = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target), 4247 OffloadingArgs); 4248 4249 CGF.EmitStoreOfScalar(Return, OffloadError); 4250 }; 4251 4252 // Notify that the host version must be executed. 4253 auto &&ElseGen = [this, OffloadError, 4254 OffloadErrorQType](CodeGenFunction &CGF) { 4255 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u), 4256 OffloadError); 4257 }; 4258 4259 // If we have a target function ID it means that we need to support 4260 // offloading, otherwise, just execute on the host. We need to execute on host 4261 // regardless of the conditional in the if clause if, e.g., the user do not 4262 // specify target triples. 4263 if (OutlinedFnID) { 4264 if (IfCond) { 4265 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 4266 } else { 4267 CodeGenFunction::RunCleanupsScope Scope(CGF); 4268 ThenGen(CGF); 4269 } 4270 } else { 4271 CodeGenFunction::RunCleanupsScope Scope(CGF); 4272 ElseGen(CGF); 4273 } 4274 4275 // Check the error code and execute the host version if required. 4276 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed"); 4277 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont"); 4278 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation()); 4279 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal); 4280 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 4281 4282 CGF.EmitBlock(OffloadFailedBlock); 4283 CGF.Builder.CreateCall(OutlinedFn, BasePointers); 4284 CGF.EmitBranch(OffloadContBlock); 4285 4286 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 4287 } 4288 4289 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 4290 StringRef ParentName) { 4291 if (!S) 4292 return; 4293 4294 // If we find a OMP target directive, codegen the outline function and 4295 // register the result. 4296 // FIXME: Add other directives with target when they become supported. 4297 bool isTargetDirective = isa<OMPTargetDirective>(S); 4298 4299 if (isTargetDirective) { 4300 auto *E = cast<OMPExecutableDirective>(S); 4301 unsigned DeviceID; 4302 unsigned FileID; 4303 unsigned Line; 4304 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID, 4305 FileID, Line); 4306 4307 // Is this a target region that should not be emitted as an entry point? If 4308 // so just signal we are done with this target region. 4309 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 4310 ParentName, Line)) 4311 return; 4312 4313 llvm::Function *Fn; 4314 llvm::Constant *Addr; 4315 emitTargetOutlinedFunction(*E, ParentName, Fn, Addr, 4316 /*isOffloadEntry=*/true); 4317 assert(Fn && Addr && "Target region emission failed."); 4318 return; 4319 } 4320 4321 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) { 4322 if (!E->getAssociatedStmt()) 4323 return; 4324 4325 scanForTargetRegionsFunctions( 4326 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(), 4327 ParentName); 4328 return; 4329 } 4330 4331 // If this is a lambda function, look into its body. 4332 if (auto *L = dyn_cast<LambdaExpr>(S)) 4333 S = L->getBody(); 4334 4335 // Keep looking for target regions recursively. 4336 for (auto *II : S->children()) 4337 scanForTargetRegionsFunctions(II, ParentName); 4338 } 4339 4340 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 4341 auto &FD = *cast<FunctionDecl>(GD.getDecl()); 4342 4343 // If emitting code for the host, we do not process FD here. Instead we do 4344 // the normal code generation. 4345 if (!CGM.getLangOpts().OpenMPIsDevice) 4346 return false; 4347 4348 // Try to detect target regions in the function. 4349 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD)); 4350 4351 // We should not emit any function othen that the ones created during the 4352 // scanning. Therefore, we signal that this function is completely dealt 4353 // with. 4354 return true; 4355 } 4356 4357 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 4358 if (!CGM.getLangOpts().OpenMPIsDevice) 4359 return false; 4360 4361 // Check if there are Ctors/Dtors in this declaration and look for target 4362 // regions in it. We use the complete variant to produce the kernel name 4363 // mangling. 4364 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 4365 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 4366 for (auto *Ctor : RD->ctors()) { 4367 StringRef ParentName = 4368 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 4369 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 4370 } 4371 auto *Dtor = RD->getDestructor(); 4372 if (Dtor) { 4373 StringRef ParentName = 4374 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 4375 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 4376 } 4377 } 4378 4379 // If we are in target mode we do not emit any global (declare target is not 4380 // implemented yet). Therefore we signal that GD was processed in this case. 4381 return true; 4382 } 4383 4384 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 4385 auto *VD = GD.getDecl(); 4386 if (isa<FunctionDecl>(VD)) 4387 return emitTargetFunctions(GD); 4388 4389 return emitTargetGlobalVariable(GD); 4390 } 4391 4392 llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { 4393 // If we have offloading in the current module, we need to emit the entries 4394 // now and register the offloading descriptor. 4395 createOffloadEntriesAndInfoMetadata(); 4396 4397 // Create and register the offloading binary descriptors. This is the main 4398 // entity that captures all the information about offloading in the current 4399 // compilation unit. 4400 return createOffloadingBinaryDescriptorRegistration(); 4401 } 4402