diff options
Diffstat (limited to 'clang/lib/CodeGen/CGOpenMPRuntime.h')
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.h | 311 |
1 files changed, 232 insertions, 79 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 8159f5e8b790..eb22f155f5ef 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -20,12 +20,15 @@ #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" +#include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/ValueHandle.h" +#include "llvm/Support/AtomicOrdering.h" namespace llvm { class ArrayType; @@ -35,6 +38,7 @@ class GlobalVariable; class StructType; class Type; class Value; +class OpenMPIRBuilder; } // namespace llvm namespace clang { @@ -80,11 +84,10 @@ public: template <typename Callable> RegionCodeGenTy( Callable &&CodeGen, - typename std::enable_if< - !std::is_same<typename std::remove_reference<Callable>::type, - RegionCodeGenTy>::value>::type * = nullptr) + std::enable_if_t<!std::is_same<std::remove_reference_t<Callable>, + RegionCodeGenTy>::value> * = nullptr) : CodeGen(reinterpret_cast<intptr_t>(&CodeGen)), - Callback(CallbackFn<typename std::remove_reference<Callable>::type>), + Callback(CallbackFn<std::remove_reference_t<Callable>>), PrePostAction(nullptr) {} void setAction(PrePostActionTy &Action) const { PrePostAction = &Action; } void operator()(CodeGenFunction &CGF) const; @@ -99,9 +102,18 @@ struct OMPTaskDataTy final { SmallVector<const Expr *, 4> LastprivateVars; SmallVector<const Expr *, 4> LastprivateCopies; SmallVector<const Expr *, 4> ReductionVars; + SmallVector<const Expr *, 4> ReductionOrigs; SmallVector<const Expr *, 4> ReductionCopies; SmallVector<const Expr *, 4> ReductionOps; - SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 4> Dependences; + struct DependData { + OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; + const Expr *IteratorExpr = nullptr; + SmallVector<const Expr *, 4> DepExprs; + explicit DependData() = default; + DependData(OpenMPDependClauseKind DepKind, const Expr *IteratorExpr) + : DepKind(DepKind), IteratorExpr(IteratorExpr) {} + }; + SmallVector<DependData, 4> Dependences; llvm::PointerIntPair<llvm::Value *, 1, bool> Final; llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule; llvm::PointerIntPair<llvm::Value *, 1, bool> Priority; @@ -109,6 +121,8 @@ struct OMPTaskDataTy final { unsigned NumberOfParts = 0; bool Tied = true; bool Nogroup = false; + bool IsReductionWithTaskMod = false; + bool IsWorksharingReduction = false; }; /// Class intended to support codegen of all kind of the reduction clauses. @@ -116,20 +130,26 @@ class ReductionCodeGen { private: /// Data required for codegen of reduction clauses. struct ReductionData { - /// Reference to the original shared item. + /// Reference to the item shared between tasks to reduce into. + const Expr *Shared = nullptr; + /// Reference to the original item. const Expr *Ref = nullptr; /// Helper expression for generation of private copy. const Expr *Private = nullptr; /// Helper expression for generation reduction operation. const Expr *ReductionOp = nullptr; - ReductionData(const Expr *Ref, const Expr *Private, const Expr *ReductionOp) - : Ref(Ref), Private(Private), ReductionOp(ReductionOp) {} + ReductionData(const Expr *Shared, const Expr *Ref, const Expr *Private, + const Expr *ReductionOp) + : Shared(Shared), Ref(Ref), Private(Private), ReductionOp(ReductionOp) { + } }; /// List of reduction-based clauses. SmallVector<ReductionData, 4> ClausesData; - /// List of addresses of original shared variables/expressions. + /// List of addresses of shared variables/expressions. SmallVector<std::pair<LValue, LValue>, 4> SharedAddresses; + /// List of addresses of original variables/expressions. + SmallVector<std::pair<LValue, LValue>, 4> OrigAddresses; /// Sizes of the reduction items in chars. SmallVector<std::pair<llvm::Value *, llvm::Value *>, 4> Sizes; /// Base declarations for the reduction items. @@ -149,12 +169,12 @@ private: const OMPDeclareReductionDecl *DRD); public: - ReductionCodeGen(ArrayRef<const Expr *> Shareds, + ReductionCodeGen(ArrayRef<const Expr *> Shareds, ArrayRef<const Expr *> Origs, ArrayRef<const Expr *> Privates, ArrayRef<const Expr *> ReductionOps); - /// Emits lvalue for a reduction item. + /// Emits lvalue for the shared and original reduction item. /// \param N Number of the reduction item. - void emitSharedLValue(CodeGenFunction &CGF, unsigned N); + void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N); /// Emits the code for the variable-modified type, if required. /// \param N Number of the reduction item. void emitAggregateType(CodeGenFunction &CGF, unsigned N); @@ -186,6 +206,8 @@ public: Address PrivateAddr); /// Returns LValue for the reduction item. LValue getSharedLValue(unsigned N) const { return SharedAddresses[N].first; } + /// Returns LValue for the original reduction item. + LValue getOrigLValue(unsigned N) const { return OrigAddresses[N].first; } /// Returns the size of the reduction item (in chars and total number of /// elements in the item), or nullptr, if the size is a constant. std::pair<llvm::Value *, llvm::Value *> getSizes(unsigned N) const { @@ -230,26 +252,42 @@ public: /// Also, stores the expression for the private loop counter and it /// threaprivate name. struct LastprivateConditionalData { - llvm::SmallDenseMap<CanonicalDeclPtr<const Decl>, SmallString<16>> - DeclToUniqeName; + llvm::MapVector<CanonicalDeclPtr<const Decl>, SmallString<16>> + DeclToUniqueName; LValue IVLVal; - SmallString<16> IVName; - /// True if original lvalue for loop counter can be used in codegen (simd - /// region or simd only mode) and no need to create threadprivate - /// references. - bool UseOriginalIV = false; + llvm::Function *Fn = nullptr; + bool Disabled = false; }; /// Manages list of lastprivate conditional decls for the specified directive. class LastprivateConditionalRAII { + enum class ActionToDo { + DoNotPush, + PushAsLastprivateConditional, + DisableLastprivateConditional, + }; CodeGenModule &CGM; - const bool NeedToPush; + ActionToDo Action = ActionToDo::DoNotPush; + + /// Check and try to disable analysis of inner regions for changes in + /// lastprivate conditional. + void tryToDisableInnerAnalysis(const OMPExecutableDirective &S, + llvm::DenseSet<CanonicalDeclPtr<const Decl>> + &NeedToAddForLPCsAsDisabled) const; - public: LastprivateConditionalRAII(CodeGenFunction &CGF, - const OMPExecutableDirective &S, LValue IVLVal); + const OMPExecutableDirective &S); + + public: + explicit LastprivateConditionalRAII(CodeGenFunction &CGF, + const OMPExecutableDirective &S, + LValue IVLVal); + static LastprivateConditionalRAII disable(CodeGenFunction &CGF, + const OMPExecutableDirective &S); ~LastprivateConditionalRAII(); }; + llvm::OpenMPIRBuilder &getOMPBuilder() { return OMPBuilder; } + protected: CodeGenModule &CGM; StringRef FirstSeparator, Separator; @@ -319,17 +357,6 @@ protected: /// default location. virtual unsigned getDefaultLocationReserved2Flags() const { return 0; } - /// Tries to emit declare variant function for \p OldGD from \p NewGD. - /// \param OrigAddr LLVM IR value for \p OldGD. - /// \param IsForDefinition true, if requested emission for the definition of - /// \p OldGD. - /// \returns true, was able to emit a definition function for \p OldGD, which - /// points to \p NewGD. - virtual bool tryEmitDeclareVariant(const GlobalDecl &NewGD, - const GlobalDecl &OldGD, - llvm::GlobalValue *OrigAddr, - bool IsForDefinition); - /// Returns default flags for the barriers depending on the directive, for /// which this barier is going to be emitted. static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind); @@ -345,6 +372,8 @@ protected: llvm::Value *getCriticalRegionLock(StringRef CriticalName); private: + /// An OpenMP-IR-Builder instance. + llvm::OpenMPIRBuilder OMPBuilder; /// Default const ident_t object used for initialization of all other /// ident_t objects. llvm::Constant *DefaultOpenMPPSource = nullptr; @@ -392,6 +421,13 @@ private: llvm::DenseMap<llvm::Function *, SmallVector<const OMPDeclareMapperDecl *, 4>>; FunctionUDMMapTy FunctionUDMMap; + /// Maps local variables marked as lastprivate conditional to their internal + /// types. + llvm::DenseMap<llvm::Function *, + llvm::DenseMap<CanonicalDeclPtr<const Decl>, + std::tuple<QualType, const FieldDecl *, + const FieldDecl *, LValue>>> + LastprivateConditionalToTypes; /// Type kmp_critical_name, originally defined as typedef kmp_int32 /// kmp_critical_name[8]; llvm::ArrayType *KmpCriticalNameTy; @@ -428,6 +464,16 @@ private: /// } flags; /// } kmp_depend_info_t; QualType KmpDependInfoTy; + /// Type typedef struct kmp_task_affinity_info { + /// kmp_intptr_t base_addr; + /// size_t len; + /// struct { + /// bool flag1 : 1; + /// bool flag2 : 1; + /// kmp_int32 reserved : 30; + /// } flags; + /// } kmp_task_affinity_info_t; + QualType KmpTaskAffinityInfoTy; /// struct kmp_dim { // loop bounds info casted to kmp_int64 /// kmp_int64 lo; // lower /// kmp_int64 up; // upper @@ -664,12 +710,6 @@ private: /// must be emitted. llvm::SmallDenseSet<const VarDecl *> DeferredGlobalVariables; - /// Mapping of the original functions to their variants and original global - /// decl. - llvm::MapVector<CanonicalDeclPtr<const FunctionDecl>, - std::pair<GlobalDecl, GlobalDecl>> - DeferredVariantFunction; - using NontemporalDeclsSet = llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>>; /// Stack for list of declarations in current context marked as nontemporal. /// The set is the union of all current stack elements. @@ -684,6 +724,9 @@ private: /// directive is present. bool HasRequiresUnifiedSharedMemory = false; + /// Atomic ordering from the omp requires directive. + llvm::AtomicOrdering RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; + /// Flag for keeping track of weather a target region has been emitted. bool HasEmittedTargetRegion = false; @@ -710,11 +753,6 @@ private: /// Returns pointer to kmpc_micro type. llvm::Type *getKmpc_MicroPointerTy(); - /// Returns specified OpenMP runtime function. - /// \param Function OpenMP runtime function. - /// \return Specified function. - llvm::FunctionCallee createRuntimeFunction(unsigned Function); - /// Returns __kmpc_for_static_init_* runtime function for the specified /// size \a IVSize and sign \a IVSigned. llvm::FunctionCallee createForStaticInitFunction(unsigned IVSize, @@ -826,6 +864,19 @@ private: const OMPLoopDirective &D)> SizeEmitter); + /// Emit update for lastprivate conditional data. + void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, + StringRef UniqueDeclName, LValue LVal, + SourceLocation Loc); + + /// Returns the number of the elements and the address of the depobj + /// dependency array. + /// \return Number of elements in depobj array and the pointer to the array of + /// dependencies. + std::pair<llvm::Value *, LValue> getDepobjElements(CodeGenFunction &CGF, + LValue DepobjLVal, + SourceLocation Loc); + public: explicit CGOpenMPRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM, ".", ".") {} @@ -1220,7 +1271,7 @@ public: /// Emit flush of the variables specified in 'omp flush' directive. /// \param Vars List of variables to flush. virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars, - SourceLocation Loc); + SourceLocation Loc, llvm::AtomicOrdering AO); /// Emit task region for the task directive. The task region is /// emitted in several steps: @@ -1381,18 +1432,34 @@ public: /// should be emitted for reduction: /// \code /// - /// _task_red_item_t red_data[n]; + /// _taskred_item_t red_data[n]; /// ... - /// red_data[i].shar = &origs[i]; + /// red_data[i].shar = &shareds[i]; + /// red_data[i].orig = &origs[i]; /// red_data[i].size = sizeof(origs[i]); /// red_data[i].f_init = (void*)RedInit<i>; /// red_data[i].f_fini = (void*)RedDest<i>; /// red_data[i].f_comb = (void*)RedOp<i>; /// red_data[i].flags = <Flag_i>; /// ... - /// void* tg1 = __kmpc_task_reduction_init(gtid, n, red_data); + /// void* tg1 = __kmpc_taskred_init(gtid, n, red_data); /// \endcode + /// For reduction clause with task modifier it emits the next call: + /// \code /// + /// _taskred_item_t red_data[n]; + /// ... + /// red_data[i].shar = &shareds[i]; + /// red_data[i].orig = &origs[i]; + /// red_data[i].size = sizeof(origs[i]); + /// red_data[i].f_init = (void*)RedInit<i>; + /// red_data[i].f_fini = (void*)RedDest<i>; + /// red_data[i].f_comb = (void*)RedOp<i>; + /// red_data[i].flags = <Flag_i>; + /// ... + /// void* tg1 = __kmpc_taskred_modifier_init(loc, gtid, is_worksharing, n, + /// red_data); + /// \endcode /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations. /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations. /// \param Data Additional data for task generation like tiedness, final @@ -1403,11 +1470,16 @@ public: ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data); + /// Emits the following code for reduction clause with task modifier: + /// \code + /// __kmpc_task_reduction_modifier_fini(loc, gtid, is_worksharing); + /// \endcode + virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, + bool IsWorksharingReduction); + /// Required to resolve existing problems in the runtime. Emits threadprivate /// variables to store the size of the VLAs/array sections for - /// initializer/combiner/finalizer functions + emits threadprivate variable to - /// store the pointer to the original reduction item for the custom - /// initializer defined by declare reduction construct. + /// initializer/combiner/finalizer functions. /// \param RCG Allows to reuse an existing data for the reductions. /// \param N Reduction item for which fixups must be emitted. virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, @@ -1467,16 +1539,16 @@ public: /// \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. + /// target directive, or null if no device clause is used and device modifier. /// \param SizeEmitter Callback to emit number of iterations for loop-based /// directives. - virtual void - emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, - llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, - const Expr *IfCond, const Expr *Device, - llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, - const OMPLoopDirective &D)> - SizeEmitter); + virtual void emitTargetCall( + CodeGenFunction &CGF, const OMPExecutableDirective &D, + llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, + llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, + llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, + const OMPLoopDirective &D)> + SizeEmitter); /// Emit the target regions enclosed in \a GD function definition or /// the function itself in case it is a valid device function. Returns true if @@ -1675,7 +1747,10 @@ public: /// Perform check on requires decl to ensure that target architecture /// supports unified addressing - virtual void checkArchForUnifiedAddressing(const OMPRequiresDecl *D); + virtual void processRequiresDirective(const OMPRequiresDecl *D); + + /// Gets default memory ordering as specified in requires directive. + llvm::AtomicOrdering getDefaultMemoryOrdering() const; /// Checks if the variable has associated OMPAllocateDeclAttr attribute with /// the predefined allocator and translates it into the corresponding address @@ -1685,17 +1760,13 @@ public: /// Return whether the unified_shared_memory has been specified. bool hasRequiresUnifiedSharedMemory() const; - /// Emits the definition of the declare variant function. - virtual bool emitDeclareVariant(GlobalDecl GD, bool IsForDefinition); - /// Checks if the \p VD variable is marked as nontemporal declaration in /// current context. bool isNontemporalDecl(const ValueDecl *VD) const; - /// Initializes global counter for lastprivate conditional. - virtual void - initLastprivateConditionalCounter(CodeGenFunction &CGF, - const OMPExecutableDirective &S); + /// Create specialized alloca to handle lastprivate conditionals. + Address emitLastprivateConditionalInit(CodeGenFunction &CGF, + const VarDecl *VD); /// Checks if the provided \p LVal is lastprivate conditional and emits the /// code to update the value of the original variable. @@ -1713,6 +1784,30 @@ public: virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS); + /// Checks if the lastprivate conditional was updated in inner region and + /// writes the value. + /// \code + /// lastprivate(conditional: a) + /// ... + /// <type> a;bool Fired = false; + /// #pragma omp ... shared(a) + /// { + /// lp_a = ...; + /// Fired = true; + /// } + /// if (Fired) { + /// #pragma omp critical(a) + /// if (last_iv_a <= iv) { + /// last_iv_a = iv; + /// global_a = lp_a; + /// } + /// Fired = false; + /// } + /// \endcode + virtual void checkAndEmitSharedLastprivateConditional( + CodeGenFunction &CGF, const OMPExecutableDirective &D, + const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls); + /// Gets the address of the global copy used for lastprivate conditional /// update, if any. /// \param PrivLVal LValue for the private copy. @@ -1721,6 +1816,41 @@ public: LValue PrivLVal, const VarDecl *VD, SourceLocation Loc); + + /// Emits list of dependecies based on the provided data (array of + /// dependence/expression pairs). + /// \returns Pointer to the first element of the array casted to VoidPtr type. + std::pair<llvm::Value *, Address> + emitDependClause(CodeGenFunction &CGF, + ArrayRef<OMPTaskDataTy::DependData> Dependencies, + SourceLocation Loc); + + /// Emits list of dependecies based on the provided data (array of + /// dependence/expression pairs) for depobj construct. In this case, the + /// variable is allocated in dynamically. \returns Pointer to the first + /// element of the array casted to VoidPtr type. + Address emitDepobjDependClause(CodeGenFunction &CGF, + const OMPTaskDataTy::DependData &Dependencies, + SourceLocation Loc); + + /// Emits the code to destroy the dependency object provided in depobj + /// directive. + void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, + SourceLocation Loc); + + /// Updates the dependency kind in the specified depobj object. + /// \param DepobjLVal LValue for the main depobj object. + /// \param NewDepKind New dependency kind. + void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, + OpenMPDependClauseKind NewDepKind, SourceLocation Loc); + + /// Initializes user defined allocators specified in the uses_allocators + /// clauses. + void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, + const Expr *AllocatorTraits); + + /// Destroys user defined allocators specified in the uses_allocators clause. + void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator); }; /// Class supports emissionof SIMD-only code. @@ -1985,7 +2115,7 @@ public: /// Emit flush of the variables specified in 'omp flush' directive. /// \param Vars List of variables to flush. void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars, - SourceLocation Loc) override; + SourceLocation Loc, llvm::AtomicOrdering AO) override; /// Emit task region for the task directive. The task region is /// emitted in several steps: @@ -2107,18 +2237,34 @@ public: /// should be emitted for reduction: /// \code /// - /// _task_red_item_t red_data[n]; + /// _taskred_item_t red_data[n]; /// ... - /// red_data[i].shar = &origs[i]; + /// red_data[i].shar = &shareds[i]; + /// red_data[i].orig = &origs[i]; /// red_data[i].size = sizeof(origs[i]); /// red_data[i].f_init = (void*)RedInit<i>; /// red_data[i].f_fini = (void*)RedDest<i>; /// red_data[i].f_comb = (void*)RedOp<i>; /// red_data[i].flags = <Flag_i>; /// ... - /// void* tg1 = __kmpc_task_reduction_init(gtid, n, red_data); + /// void* tg1 = __kmpc_taskred_init(gtid, n, red_data); /// \endcode + /// For reduction clause with task modifier it emits the next call: + /// \code /// + /// _taskred_item_t red_data[n]; + /// ... + /// red_data[i].shar = &shareds[i]; + /// red_data[i].orig = &origs[i]; + /// red_data[i].size = sizeof(origs[i]); + /// red_data[i].f_init = (void*)RedInit<i>; + /// red_data[i].f_fini = (void*)RedDest<i>; + /// red_data[i].f_comb = (void*)RedOp<i>; + /// red_data[i].flags = <Flag_i>; + /// ... + /// void* tg1 = __kmpc_taskred_modifier_init(loc, gtid, is_worksharing, n, + /// red_data); + /// \endcode /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations. /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations. /// \param Data Additional data for task generation like tiedness, final @@ -2128,6 +2274,13 @@ public: ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) override; + /// Emits the following code for reduction clause with task modifier: + /// \code + /// __kmpc_task_reduction_modifier_fini(loc, gtid, is_worksharing); + /// \endcode + void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, + bool IsWorksharingReduction) override; + /// Required to resolve existing problems in the runtime. Emits threadprivate /// variables to store the size of the VLAs/array sections for /// initializer/combiner/finalizer functions + emits threadprivate variable to @@ -2191,14 +2344,14 @@ public: /// \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. - void - emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, - llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, - const Expr *IfCond, const Expr *Device, - llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, - const OMPLoopDirective &D)> - SizeEmitter) override; + /// target directive, or null if no device clause is used and device modifier. + void emitTargetCall( + CodeGenFunction &CGF, const OMPExecutableDirective &D, + llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, + llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, + llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, + const OMPLoopDirective &D)> + SizeEmitter) override; /// Emit the target regions enclosed in \a GD function definition or /// the function itself in case it is a valid device function. Returns true if |