diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h | 567 |
1 files changed, 316 insertions, 251 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h index b325637..270de8d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -14,18 +14,19 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H #define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H +#include "CGValue.h" #include "clang/AST/Type.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" +#include "llvm/IR/Function.h" #include "llvm/IR/ValueHandle.h" namespace llvm { class ArrayType; class Constant; -class Function; class FunctionType; class GlobalVariable; class StructType; @@ -36,222 +37,116 @@ class Value; namespace clang { class Expr; class GlobalDecl; +class OMPDependClause; class OMPExecutableDirective; +class OMPLoopDirective; class VarDecl; +class OMPDeclareReductionDecl; +class IdentifierInfo; namespace CodeGen { class Address; class CodeGenFunction; class CodeGenModule; -typedef llvm::function_ref<void(CodeGenFunction &)> RegionCodeGenTy; +/// A basic class for pre|post-action for advanced codegen sequence for OpenMP +/// region. +class PrePostActionTy { +public: + explicit PrePostActionTy() {} + virtual void Enter(CodeGenFunction &CGF) {} + virtual void Exit(CodeGenFunction &CGF) {} + virtual ~PrePostActionTy() {} +}; -class CGOpenMPRuntime { -private: - enum OpenMPRTLFunction { - /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, - /// kmpc_micro microtask, ...); - OMPRTL__kmpc_fork_call, - /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc, - /// kmp_int32 global_tid, void *data, size_t size, void ***cache); - OMPRTL__kmpc_threadprivate_cached, - /// \brief Call to void __kmpc_threadprivate_register( ident_t *, - /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); - OMPRTL__kmpc_threadprivate_register, - // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); - OMPRTL__kmpc_global_thread_num, - // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *crit); - OMPRTL__kmpc_critical, - // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 - // global_tid, kmp_critical_name *crit, uintptr_t hint); - OMPRTL__kmpc_critical_with_hint, - // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *crit); - OMPRTL__kmpc_end_critical, - // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 - // global_tid); - OMPRTL__kmpc_cancel_barrier, - // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_barrier, - // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_for_static_fini, - // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 - // global_tid); - OMPRTL__kmpc_serialized_parallel, - // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 - // global_tid); - OMPRTL__kmpc_end_serialized_parallel, - // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 num_threads); - OMPRTL__kmpc_push_num_threads, - // Call to void __kmpc_flush(ident_t *loc); - OMPRTL__kmpc_flush, - // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); - OMPRTL__kmpc_master, - // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); - OMPRTL__kmpc_end_master, - // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, - // int end_part); - OMPRTL__kmpc_omp_taskyield, - // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); - OMPRTL__kmpc_single, - // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); - OMPRTL__kmpc_end_single, - // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, - // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, - // kmp_routine_entry_t *task_entry); - OMPRTL__kmpc_omp_task_alloc, - // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * - // new_task); - OMPRTL__kmpc_omp_task, - // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, - // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), - // kmp_int32 didit); - OMPRTL__kmpc_copyprivate, - // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void - // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); - OMPRTL__kmpc_reduce, - // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, - // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name - // *lck); - OMPRTL__kmpc_reduce_nowait, - // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *lck); - OMPRTL__kmpc_end_reduce, - // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, - // kmp_critical_name *lck); - OMPRTL__kmpc_end_reduce_nowait, - // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, - // kmp_task_t * new_task); - OMPRTL__kmpc_omp_task_begin_if0, - // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, - // kmp_task_t * new_task); - OMPRTL__kmpc_omp_task_complete_if0, - // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_ordered, - // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_end_ordered, - // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 - // global_tid); - OMPRTL__kmpc_omp_taskwait, - // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_taskgroup, - // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); - OMPRTL__kmpc_end_taskgroup, - // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, - // int proc_bind); - OMPRTL__kmpc_push_proc_bind, - // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 - // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t - // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); - OMPRTL__kmpc_omp_task_with_deps, - // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 - // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 - // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); - OMPRTL__kmpc_omp_wait_deps, - // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 - // global_tid, kmp_int32 cncl_kind); - OMPRTL__kmpc_cancellationpoint, - // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, - // kmp_int32 cncl_kind); - OMPRTL__kmpc_cancel, - - // - // Offloading related calls - // - // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t - // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t - // *arg_types); - OMPRTL__tgt_target, - // Call to void __tgt_register_lib(__tgt_bin_desc *desc); - OMPRTL__tgt_register_lib, - // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); - OMPRTL__tgt_unregister_lib, - }; +/// Class provides a way to call simple version of codegen for OpenMP region, or +/// an advanced with possible pre|post-actions in codegen. +class RegionCodeGenTy final { + intptr_t CodeGen; + typedef void (*CodeGenTy)(intptr_t, CodeGenFunction &, PrePostActionTy &); + CodeGenTy Callback; + mutable PrePostActionTy *PrePostAction; + RegionCodeGenTy() = delete; + RegionCodeGenTy &operator=(const RegionCodeGenTy &) = delete; + template <typename Callable> + static void CallbackFn(intptr_t CodeGen, CodeGenFunction &CGF, + PrePostActionTy &Action) { + return (*reinterpret_cast<Callable *>(CodeGen))(CGF, Action); + } - /// \brief Values for bit flags used in the ident_t to describe the fields. - /// All enumeric elements are named and described in accordance with the code - /// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h - enum OpenMPLocationFlags { - /// \brief Use trampoline for internal microtask. - OMP_IDENT_IMD = 0x01, - /// \brief Use c-style ident structure. - OMP_IDENT_KMPC = 0x02, - /// \brief Atomic reduction option for kmpc_reduce. - OMP_ATOMIC_REDUCE = 0x10, - /// \brief Explicit 'barrier' directive. - OMP_IDENT_BARRIER_EXPL = 0x20, - /// \brief Implicit barrier in code. - OMP_IDENT_BARRIER_IMPL = 0x40, - /// \brief Implicit barrier in 'for' directive. - OMP_IDENT_BARRIER_IMPL_FOR = 0x40, - /// \brief Implicit barrier in 'sections' directive. - OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, - /// \brief Implicit barrier in 'single' directive. - OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140 - }; +public: + template <typename Callable> + RegionCodeGenTy( + Callable &&CodeGen, + typename std::enable_if< + !std::is_same<typename std::remove_reference<Callable>::type, + RegionCodeGenTy>::value>::type * = nullptr) + : CodeGen(reinterpret_cast<intptr_t>(&CodeGen)), + Callback(CallbackFn<typename std::remove_reference<Callable>::type>), + PrePostAction(nullptr) {} + void setAction(PrePostActionTy &Action) const { PrePostAction = &Action; } + void operator()(CodeGenFunction &CGF) const; +}; + +struct OMPTaskDataTy final { + SmallVector<const Expr *, 4> PrivateVars; + SmallVector<const Expr *, 4> PrivateCopies; + SmallVector<const Expr *, 4> FirstprivateVars; + SmallVector<const Expr *, 4> FirstprivateCopies; + SmallVector<const Expr *, 4> FirstprivateInits; + SmallVector<const Expr *, 4> LastprivateVars; + SmallVector<const Expr *, 4> LastprivateCopies; + SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 4> Dependences; + llvm::PointerIntPair<llvm::Value *, 1, bool> Final; + llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule; + llvm::PointerIntPair<llvm::Value *, 1, bool> Priority; + unsigned NumberOfParts = 0; + bool Tied = true; + bool Nogroup = false; +}; + +class CGOpenMPRuntime { +protected: CodeGenModule &CGM; + + /// \brief Creates offloading entry for the provided entry ID \a ID, + /// address \a Addr and size \a Size. + virtual void createOffloadEntry(llvm::Constant *ID, llvm::Constant *Addr, + uint64_t Size); + + /// \brief Helper to emit outlined function for 'target' directive. + /// \param D Directive to emit. + /// \param ParentName Name of the function that encloses the target region. + /// \param OutlinedFn Outlined function value to be defined by this call. + /// \param OutlinedFnID Outlined function ID value to be defined by this call. + /// \param IsOffloadEntry True if the outlined function is an offload entry. + /// \param CodeGen Lambda codegen specific to an accelerator device. + /// An oulined function may not be an entry if, e.g. the if clause always + /// evaluates to false. + virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, + StringRef ParentName, + llvm::Function *&OutlinedFn, + llvm::Constant *&OutlinedFnID, + bool IsOffloadEntry, + const RegionCodeGenTy &CodeGen); + +private: /// \brief Default const ident_t object used for initialization of all other /// ident_t objects. - llvm::Constant *DefaultOpenMPPSource; + llvm::Constant *DefaultOpenMPPSource = nullptr; /// \brief Map of flags and corresponding default locations. typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy; OpenMPDefaultLocMapTy OpenMPDefaultLocMap; - Address getOrCreateDefaultLocation(OpenMPLocationFlags Flags); + Address getOrCreateDefaultLocation(unsigned Flags); -public: - /// \brief Describes ident structure that describes a source location. - /// All descriptions are taken from - /// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h - /// Original structure: - /// typedef struct ident { - /// kmp_int32 reserved_1; /**< might be used in Fortran; - /// see above */ - /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; - /// KMP_IDENT_KMPC identifies this union - /// member */ - /// kmp_int32 reserved_2; /**< not really used in Fortran any more; - /// see above */ - ///#if USE_ITT_BUILD - /// /* but currently used for storing - /// region-specific ITT */ - /// /* contextual information. */ - ///#endif /* USE_ITT_BUILD */ - /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for - /// C++ */ - /// char const *psource; /**< String describing the source location. - /// The string is composed of semi-colon separated - // fields which describe the source file, - /// the function and a pair of line numbers that - /// delimit the construct. - /// */ - /// } ident_t; - enum IdentFieldIndex { - /// \brief might be used in Fortran - IdentField_Reserved_1, - /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. - IdentField_Flags, - /// \brief Not really used in Fortran any more - IdentField_Reserved_2, - /// \brief Source[4] in Fortran, do not use for C++ - IdentField_Reserved_3, - /// \brief String describing the source location. The string is composed of - /// semi-colon separated fields which describe the source file, the function - /// and a pair of line numbers that delimit the construct. - IdentField_PSource - }; -private: - llvm::StructType *IdentTy; + llvm::StructType *IdentTy = nullptr; /// \brief Map for SourceLocation and OpenMP runtime library debug locations. typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDebugLocMapTy; OpenMPDebugLocMapTy OpenMPDebugLocMap; /// \brief The type for a microtask which gets passed to __kmpc_fork_call(). /// Original representation is: /// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...); - llvm::FunctionType *Kmpc_MicroTy; + llvm::FunctionType *Kmpc_MicroTy = nullptr; /// \brief Stores debug location and ThreadID for the function. struct DebugLocThreadIdTy { llvm::Value *DebugLoc; @@ -261,6 +156,20 @@ private: typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy> OpenMPLocThreadIDMapTy; OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap; + /// Map of UDRs and corresponding combiner/initializer. + typedef llvm::DenseMap<const OMPDeclareReductionDecl *, + std::pair<llvm::Function *, llvm::Function *>> + UDRMapTy; + UDRMapTy UDRMap; + /// Map of functions and locally defined UDRs. + typedef llvm::DenseMap<llvm::Function *, + SmallVector<const OMPDeclareReductionDecl *, 4>> + FunctionUDRMapTy; + FunctionUDRMapTy FunctionUDRMap; + IdentifierInfo *In = nullptr; + IdentifierInfo *Out = nullptr; + IdentifierInfo *Priv = nullptr; + IdentifierInfo *Orig = nullptr; /// \brief Type kmp_critical_name, originally defined as typedef kmp_int32 /// kmp_critical_name[8]; llvm::ArrayType *KmpCriticalNameTy; @@ -272,7 +181,7 @@ private: llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator> InternalVars; /// \brief Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); - llvm::Type *KmpRoutineEntryPtrTy; + llvm::Type *KmpRoutineEntryPtrTy = nullptr; QualType KmpRoutineEntryPtrQTy; /// \brief Type typedef struct kmp_task { /// void * shareds; /**< pointer to block of pointers to @@ -293,6 +202,12 @@ private: /// } flags; /// } kmp_depend_info_t; QualType KmpDependInfoTy; + /// struct kmp_dim { // loop bounds info casted to kmp_int64 + /// kmp_int64 lo; // lower + /// kmp_int64 up; // upper + /// kmp_int64 st; // stride + /// }; + QualType KmpDimTy; /// \brief Type struct __tgt_offload_entry{ /// void *addr; // Pointer to the offload entry info. /// // (function or global) @@ -402,30 +317,27 @@ private: /// \brief Initialize target region entry. void initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, - unsigned ColNum, unsigned Order); + unsigned Order); /// \brief Register target region entry. void registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, - unsigned ColNum, llvm::Constant *Addr, + llvm::Constant *Addr, llvm::Constant *ID); /// \brief Return true if a target region entry with the provided /// information exists. bool hasTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, - StringRef ParentName, unsigned LineNum, - unsigned ColNum) const; + StringRef ParentName, unsigned LineNum) const; /// brief Applies action \a Action on all registered entries. typedef llvm::function_ref<void(unsigned, unsigned, StringRef, unsigned, - unsigned, OffloadEntryInfoTargetRegion &)> + OffloadEntryInfoTargetRegion &)> OffloadTargetRegionEntryInfoActTy; void actOnTargetRegionEntriesInfo( const OffloadTargetRegionEntryInfoActTy &Action); private: // Storage for target region entries kind. The storage is to be indexed by - // file ID, device ID, parent function name, lane number, and column number. + // file ID, device ID, parent function name and line number. typedef llvm::DenseMap<unsigned, OffloadEntryInfoTargetRegion> - OffloadEntriesTargetRegionPerColumn; - typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerColumn> OffloadEntriesTargetRegionPerLine; typedef llvm::StringMap<OffloadEntriesTargetRegionPerLine> OffloadEntriesTargetRegionPerParentName; @@ -442,10 +354,6 @@ private: /// compilation unit. The function that does the registration is returned. llvm::Function *createOffloadingBinaryDescriptorRegistration(); - /// \brief Creates offloading entry for the provided address \a Addr, - /// name \a Name and size \a Size. - void createOffloadEntry(llvm::Constant *Addr, StringRef Name, uint64_t Size); - /// \brief Creates all the offload entries in the current compilation unit /// along with the associated metadata. void createOffloadEntriesAndInfoMetadata(); @@ -476,7 +384,7 @@ private: /// \param Flags Flags for OpenMP location. /// llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPLocationFlags Flags = OMP_IDENT_KMPC); + unsigned Flags = 0); /// \brief Returns pointer to ident_t type. llvm::Type *getIdentTyPointerTy(); @@ -487,7 +395,7 @@ private: /// \brief Returns specified OpenMP runtime function. /// \param Function OpenMP runtime function. /// \return Specified function. - llvm::Constant *createRuntimeFunction(OpenMPRTLFunction Function); + llvm::Constant *createRuntimeFunction(unsigned Function); /// \brief Returns __kmpc_for_static_init_* runtime function for the specified /// size \a IVSize and sign \a IVSigned. @@ -530,7 +438,7 @@ private: const llvm::Twine &Name); /// \brief Set of threadprivate variables with the generated initializer. - llvm::DenseSet<const VarDecl *> ThreadPrivateWithDefinition; + llvm::SmallPtrSet<const VarDecl *, 4> ThreadPrivateWithDefinition; /// \brief Emits initialization code for the threadprivate variables. /// \param VDAddr Address of the global variable \a VD. @@ -549,11 +457,52 @@ private: /// llvm::Value *getCriticalRegionLock(StringRef CriticalName); + struct TaskResultTy { + llvm::Value *NewTask = nullptr; + llvm::Value *TaskEntry = nullptr; + llvm::Value *NewTaskNewTaskTTy = nullptr; + LValue TDBase; + RecordDecl *KmpTaskTQTyRD = nullptr; + llvm::Value *TaskDupFn = nullptr; + }; + /// Emit task region for the task directive. The task region is emitted in + /// several steps: + /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 + /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, + /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the + /// function: + /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { + /// TaskFunction(gtid, tt->part_id, tt->shareds); + /// return 0; + /// } + /// 2. Copy a list of shared variables to field shareds of the resulting + /// structure kmp_task_t returned by the previous call (if any). + /// 3. Copy a pointer to destructions function to field destructions of the + /// resulting structure kmp_task_t. + /// \param D Current task directive. + /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 + /// /*part_id*/, captured_struct */*__context*/); + /// \param SharedsTy A type which contains references the shared variables. + /// \param Shareds Context with the list of shared variables from the \p + /// TaskFunction. + /// \param Data Additional data for task generation like tiednsee, final + /// state, list of privates etc. + TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, + const OMPExecutableDirective &D, + llvm::Value *TaskFunction, QualType SharedsTy, + Address Shareds, const OMPTaskDataTy &Data); + public: explicit CGOpenMPRuntime(CodeGenModule &CGM); virtual ~CGOpenMPRuntime() {} virtual void clear(); + /// Emit code for the specified user defined reduction construct. + virtual void emitUserDefinedReduction(CodeGenFunction *CGF, + const OMPDeclareReductionDecl *D); + /// Get combiner/initializer for the specified user-defined reduction, if any. + virtual std::pair<llvm::Function *, llvm::Function *> + getUserDefinedReduction(const OMPDeclareReductionDecl *D); /// \brief Emits outlined function for the specified OpenMP parallel directive /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, /// kmp_int32 BoundID, struct context_vars*). @@ -562,22 +511,30 @@ public: /// \param InnermostKind Kind of innermost directive (for simple directives it /// is a directive itself, for combined - its innermost directive). /// \param CodeGen Code generation sequence for the \a D directive. - virtual llvm::Value *emitParallelOutlinedFunction( + virtual llvm::Value *emitParallelOrTeamsOutlinedFunction( const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen); /// \brief Emits outlined function for the OpenMP task directive \a D. This - /// outlined function has type void(*)(kmp_int32 ThreadID, kmp_int32 - /// PartID, struct context_vars*). + /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t* + /// TaskT). /// \param D OpenMP directive. /// \param ThreadIDVar Variable for thread id in the current OpenMP region. + /// \param PartIDVar Variable for partition id in the current OpenMP untied + /// task region. + /// \param TaskTVar Variable for task_t argument. /// \param InnermostKind Kind of innermost directive (for simple directives it /// is a directive itself, for combined - its innermost directive). /// \param CodeGen Code generation sequence for the \a D directive. + /// \param Tied true if task is generated for tied task, false otherwise. + /// \param NumberOfParts Number of parts in untied task. Ignored for tied + /// tasks. /// virtual llvm::Value *emitTaskOutlinedFunction( const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, - OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen); + const VarDecl *PartIDVar, const VarDecl *TaskTVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, + bool Tied, unsigned &NumberOfParts); /// \brief Cleans up references to the objects in finished function. /// @@ -664,6 +621,14 @@ public: virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const; + /// \brief Check if the specified \a ScheduleKind is static non-chunked. + /// This kind of distribute directive is emitted without outer loop. + /// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause. + /// \param Chunked True if chunk is specified in the clause. + /// + virtual bool isStaticNonchunked(OpenMPDistScheduleClauseKind ScheduleKind, + bool Chunked) const; + /// \brief Check if the specified \a ScheduleKind is dynamic. /// This kind of worksharing directive is emitted without outer loop. /// \param ScheduleKind Schedule Kind specified in the 'schedule' clause. @@ -671,9 +636,9 @@ public: virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const; virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPScheduleClauseKind SchedKind, - unsigned IVSize, bool IVSigned, - bool Ordered, llvm::Value *UB, + const OpenMPScheduleTy &ScheduleKind, + unsigned IVSize, bool IVSigned, bool Ordered, + llvm::Value *UB, llvm::Value *Chunk = nullptr); /// \brief Call the appropriate runtime routine to initialize it before start @@ -685,7 +650,7 @@ public: /// /// \param CGF Reference to current CodeGenFunction. /// \param Loc Clang source location. - /// \param SchedKind Schedule kind, specified by the 'schedule' clause. + /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. /// \param IVSize Size of the iteration variable in bits. /// \param IVSigned Sign of the interation variable. /// \param Ordered true if loop is ordered, false otherwise. @@ -701,12 +666,36 @@ public: /// For the default (nullptr) value, the chunk 1 will be used. /// virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, - OpenMPScheduleClauseKind SchedKind, + const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, - Address IL, Address LB, - Address UB, Address ST, + Address IL, Address LB, Address UB, Address ST, llvm::Value *Chunk = nullptr); + /// + /// \param CGF Reference to current CodeGenFunction. + /// \param Loc Clang source location. + /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause. + /// \param IVSize Size of the iteration variable in bits. + /// \param IVSigned Sign of the interation variable. + /// \param Ordered true if loop is ordered, false otherwise. + /// \param IL Address of the output variable in which the flag of the + /// last iteration is returned. + /// \param LB Address of the output variable in which the lower iteration + /// number is returned. + /// \param UB Address of the output variable in which the upper iteration + /// number is returned. + /// \param ST Address of the output variable in which the stride value is + /// returned nesessary to generated the static_chunked scheduled loop. + /// \param Chunk Value of the chunk for the static_chunked scheduled loop. + /// For the default (nullptr) value, the chunk 1 will be used. + /// + virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDistScheduleClauseKind SchedKind, + unsigned IVSize, bool IVSigned, + bool Ordered, Address IL, Address LB, + Address UB, Address ST, + llvm::Value *Chunk = nullptr); + /// \brief Call the appropriate runtime routine to notify that we finished /// iteration of the ordered loop with the dynamic scheduling. /// @@ -807,12 +796,6 @@ public: /// kmp_task_t *new_task), where new_task is a resulting structure from /// previous items. /// \param D Current task directive. - /// \param Tied true if the task is tied (the task is tied to the thread that - /// can suspend its task region), false - untied (the task is not tied to any - /// thread). - /// \param Final Contains either constant bool value, or llvm::Value * of i1 - /// type for final clause. If the value is true, the task forces all of its - /// child tasks to become final and included tasks. /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 /// /*part_id*/, captured_struct */*__context*/); /// \param SharedsTy A type which contains references the shared variables. @@ -820,29 +803,47 @@ public: /// TaskFunction. /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr /// otherwise. - /// \param PrivateVars List of references to private variables for the task - /// directive. - /// \param PrivateCopies List of private copies for each private variable in - /// \p PrivateVars. - /// \param FirstprivateVars List of references to private variables for the - /// task directive. - /// \param FirstprivateCopies List of private copies for each private variable - /// in \p FirstprivateVars. - /// \param FirstprivateInits List of references to auto generated variables - /// used for initialization of a single array element. Used if firstprivate - /// variable is of array type. - /// \param Dependences List of dependences for the 'task' construct, including - /// original expression and dependency type. - virtual void emitTaskCall( - CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, - bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, + /// \param Data Additional data for task generation like tiednsee, final + /// state, list of privates etc. + virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, + const OMPExecutableDirective &D, + llvm::Value *TaskFunction, QualType SharedsTy, + Address Shareds, const Expr *IfCond, + const OMPTaskDataTy &Data); + + /// Emit task region for the taskloop directive. The taskloop region is + /// emitted in several steps: + /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 + /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, + /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the + /// function: + /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { + /// TaskFunction(gtid, tt->part_id, tt->shareds); + /// return 0; + /// } + /// 2. Copy a list of shared variables to field shareds of the resulting + /// structure kmp_task_t returned by the previous call (if any). + /// 3. Copy a pointer to destructions function to field destructions of the + /// resulting structure kmp_task_t. + /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t + /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int + /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task + /// is a resulting structure from + /// previous items. + /// \param D Current task directive. + /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 + /// /*part_id*/, captured_struct */*__context*/); + /// \param SharedsTy A type which contains references the shared variables. + /// \param Shareds Context with the list of shared variables from the \p + /// TaskFunction. + /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr + /// otherwise. + /// \param Data Additional data for task generation like tiednsee, final + /// state, list of privates etc. + virtual void emitTaskLoopCall( + CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds, - const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, - ArrayRef<const Expr *> PrivateCopies, - ArrayRef<const Expr *> FirstprivateVars, - ArrayRef<const Expr *> FirstprivateCopies, - ArrayRef<const Expr *> FirstprivateInits, - ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences); + const Expr *IfCond, const OMPTaskDataTy &Data); /// \brief Emit code for the directive that does not require outlining. /// @@ -926,13 +927,15 @@ public: /// \param OutlinedFn Outlined function value to be defined by this call. /// \param OutlinedFnID Outlined function ID value to be defined by this call. /// \param IsOffloadEntry True if the outlined function is an offload entry. + /// \param CodeGen Code generation sequence for the \a D directive. /// An oulined function may not be an entry if, e.g. the if clause always /// evaluates to false. virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, - bool IsOffloadEntry); + bool IsOffloadEntry, + const RegionCodeGenTy &CodeGen); /// \brief Emit the target offloading code associated with \a D. The emitted /// code attempts offloading the execution to the device, an the event of @@ -972,6 +975,68 @@ public: /// was emitted in the current module and return the function that registers /// it. virtual llvm::Function *emitRegistrationFunction(); + + /// \brief Emits code for teams call of the \a OutlinedFn with + /// variables captured in a record which address is stored in \a + /// CapturedStruct. + /// \param OutlinedFn Outlined function to be run by team masters. Type of + /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). + /// \param CapturedVars A pointer to the record with the references to + /// variables used in \a OutlinedFn function. + /// + virtual void emitTeamsCall(CodeGenFunction &CGF, + const OMPExecutableDirective &D, + SourceLocation Loc, llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars); + + /// \brief Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 + /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code + /// for num_teams clause. + /// \param NumTeams An integer expression of teams. + /// \param ThreadLimit An integer expression of threads. + virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, + const Expr *ThreadLimit, SourceLocation Loc); + + /// \brief Emit the target data mapping code associated with \a D. + /// \param D Directive to emit. + /// \param IfCond Expression evaluated in if clause associated with the target + /// directive, or null if no if clause is used. + /// \param Device Expression evaluated in device clause associated with the + /// target directive, or null if no device clause is used. + /// \param CodeGen Function that emits the enclosed region. + virtual void emitTargetDataCalls(CodeGenFunction &CGF, + const OMPExecutableDirective &D, + const Expr *IfCond, const Expr *Device, + const RegionCodeGenTy &CodeGen); + + /// \brief Emit the data mapping/movement code associated with the directive + /// \a D that should be of the form 'target [{enter|exit} data | update]'. + /// \param D Directive to emit. + /// \param IfCond Expression evaluated in if clause associated with the target + /// directive, or null if no if clause is used. + /// \param Device Expression evaluated in device clause associated with the + /// target directive, or null if no device clause is used. + virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, + const OMPExecutableDirective &D, + const Expr *IfCond, + const Expr *Device); + + /// Marks function \a Fn with properly mangled versions of vector functions. + /// \param FD Function marked as 'declare simd'. + /// \param Fn LLVM function that must be marked with 'declare simd' + /// attributes. + virtual void emitDeclareSimdFunction(const FunctionDecl *FD, + llvm::Function *Fn); + + /// Emit initialization for doacross loop nesting support. + /// \param D Loop-based construct used in doacross nesting construct. + virtual void emitDoacrossInit(CodeGenFunction &CGF, + const OMPLoopDirective &D); + + /// Emit code for doacross ordered directive with 'depend' clause. + /// \param C 'depend' clause with 'sink|source' dependency kind. + virtual void emitDoacrossOrdered(CodeGenFunction &CGF, + const OMPDependClause *C); }; } // namespace CodeGen |