10b57cec5SDimitry Andric //===----- CGOpenMPRuntime.h - Interface to OpenMP Runtimes -----*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This provides a class for OpenMP runtime code generation. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H 140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "CGValue.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclOpenMP.h" 18a7dea167SDimitry Andric #include "clang/AST/GlobalDecl.h" 190b57cec5SDimitry Andric #include "clang/AST/Type.h" 200b57cec5SDimitry Andric #include "clang/Basic/OpenMPKinds.h" 210b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 220b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 235ffd83dbSDimitry Andric #include "llvm/ADT/PointerIntPair.h" 24480093f4SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 250b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h" 260b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h" 27480093f4SDimitry Andric #include "llvm/Frontend/OpenMP/OMPConstants.h" 285ffd83dbSDimitry Andric #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 290b57cec5SDimitry Andric #include "llvm/IR/Function.h" 300b57cec5SDimitry Andric #include "llvm/IR/ValueHandle.h" 315ffd83dbSDimitry Andric #include "llvm/Support/AtomicOrdering.h" 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace llvm { 340b57cec5SDimitry Andric class ArrayType; 350b57cec5SDimitry Andric class Constant; 360b57cec5SDimitry Andric class FunctionType; 370b57cec5SDimitry Andric class GlobalVariable; 380b57cec5SDimitry Andric class Type; 390b57cec5SDimitry Andric class Value; 405ffd83dbSDimitry Andric class OpenMPIRBuilder; 410b57cec5SDimitry Andric } // namespace llvm 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric namespace clang { 440b57cec5SDimitry Andric class Expr; 450b57cec5SDimitry Andric class OMPDependClause; 460b57cec5SDimitry Andric class OMPExecutableDirective; 470b57cec5SDimitry Andric class OMPLoopDirective; 480b57cec5SDimitry Andric class VarDecl; 490b57cec5SDimitry Andric class OMPDeclareReductionDecl; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric namespace CodeGen { 520b57cec5SDimitry Andric class Address; 530b57cec5SDimitry Andric class CodeGenFunction; 540b57cec5SDimitry Andric class CodeGenModule; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 570b57cec5SDimitry Andric /// region. 580b57cec5SDimitry Andric class PrePostActionTy { 590b57cec5SDimitry Andric public: PrePostActionTy()600b57cec5SDimitry Andric explicit PrePostActionTy() {} Enter(CodeGenFunction & CGF)610b57cec5SDimitry Andric virtual void Enter(CodeGenFunction &CGF) {} Exit(CodeGenFunction & CGF)620b57cec5SDimitry Andric virtual void Exit(CodeGenFunction &CGF) {} ~PrePostActionTy()630b57cec5SDimitry Andric virtual ~PrePostActionTy() {} 640b57cec5SDimitry Andric }; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric /// Class provides a way to call simple version of codegen for OpenMP region, or 670b57cec5SDimitry Andric /// an advanced with possible pre|post-actions in codegen. 680b57cec5SDimitry Andric class RegionCodeGenTy final { 690b57cec5SDimitry Andric intptr_t CodeGen; 700b57cec5SDimitry Andric typedef void (*CodeGenTy)(intptr_t, CodeGenFunction &, PrePostActionTy &); 710b57cec5SDimitry Andric CodeGenTy Callback; 720b57cec5SDimitry Andric mutable PrePostActionTy *PrePostAction; 730b57cec5SDimitry Andric RegionCodeGenTy() = delete; 740b57cec5SDimitry Andric template <typename Callable> CallbackFn(intptr_t CodeGen,CodeGenFunction & CGF,PrePostActionTy & Action)750b57cec5SDimitry Andric static void CallbackFn(intptr_t CodeGen, CodeGenFunction &CGF, 760b57cec5SDimitry Andric PrePostActionTy &Action) { 770b57cec5SDimitry Andric return (*reinterpret_cast<Callable *>(CodeGen))(CGF, Action); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric public: 810b57cec5SDimitry Andric template <typename Callable> 820b57cec5SDimitry Andric RegionCodeGenTy( 830b57cec5SDimitry Andric Callable &&CodeGen, 845ffd83dbSDimitry Andric std::enable_if_t<!std::is_same<std::remove_reference_t<Callable>, 855ffd83dbSDimitry Andric RegionCodeGenTy>::value> * = nullptr) CodeGen(reinterpret_cast<intptr_t> (& CodeGen))860b57cec5SDimitry Andric : CodeGen(reinterpret_cast<intptr_t>(&CodeGen)), 875ffd83dbSDimitry Andric Callback(CallbackFn<std::remove_reference_t<Callable>>), 880b57cec5SDimitry Andric PrePostAction(nullptr) {} setAction(PrePostActionTy & Action)890b57cec5SDimitry Andric void setAction(PrePostActionTy &Action) const { PrePostAction = &Action; } 900b57cec5SDimitry Andric void operator()(CodeGenFunction &CGF) const; 910b57cec5SDimitry Andric }; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric struct OMPTaskDataTy final { 940b57cec5SDimitry Andric SmallVector<const Expr *, 4> PrivateVars; 950b57cec5SDimitry Andric SmallVector<const Expr *, 4> PrivateCopies; 960b57cec5SDimitry Andric SmallVector<const Expr *, 4> FirstprivateVars; 970b57cec5SDimitry Andric SmallVector<const Expr *, 4> FirstprivateCopies; 980b57cec5SDimitry Andric SmallVector<const Expr *, 4> FirstprivateInits; 990b57cec5SDimitry Andric SmallVector<const Expr *, 4> LastprivateVars; 1000b57cec5SDimitry Andric SmallVector<const Expr *, 4> LastprivateCopies; 1010b57cec5SDimitry Andric SmallVector<const Expr *, 4> ReductionVars; 1025ffd83dbSDimitry Andric SmallVector<const Expr *, 4> ReductionOrigs; 1030b57cec5SDimitry Andric SmallVector<const Expr *, 4> ReductionCopies; 1040b57cec5SDimitry Andric SmallVector<const Expr *, 4> ReductionOps; 105e8d8bef9SDimitry Andric SmallVector<CanonicalDeclPtr<const VarDecl>, 4> PrivateLocals; 1065ffd83dbSDimitry Andric struct DependData { 1075ffd83dbSDimitry Andric OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; 1085ffd83dbSDimitry Andric const Expr *IteratorExpr = nullptr; 1095ffd83dbSDimitry Andric SmallVector<const Expr *, 4> DepExprs; 1105ffd83dbSDimitry Andric explicit DependData() = default; DependDatafinal::DependData1115ffd83dbSDimitry Andric DependData(OpenMPDependClauseKind DepKind, const Expr *IteratorExpr) 1125ffd83dbSDimitry Andric : DepKind(DepKind), IteratorExpr(IteratorExpr) {} 1135ffd83dbSDimitry Andric }; 1145ffd83dbSDimitry Andric SmallVector<DependData, 4> Dependences; 1150b57cec5SDimitry Andric llvm::PointerIntPair<llvm::Value *, 1, bool> Final; 1160b57cec5SDimitry Andric llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule; 1170b57cec5SDimitry Andric llvm::PointerIntPair<llvm::Value *, 1, bool> Priority; 1180b57cec5SDimitry Andric llvm::Value *Reductions = nullptr; 1190b57cec5SDimitry Andric unsigned NumberOfParts = 0; 1200b57cec5SDimitry Andric bool Tied = true; 1210b57cec5SDimitry Andric bool Nogroup = false; 1225ffd83dbSDimitry Andric bool IsReductionWithTaskMod = false; 1235ffd83dbSDimitry Andric bool IsWorksharingReduction = false; 124bdd1243dSDimitry Andric bool HasNowaitClause = false; 1250b57cec5SDimitry Andric }; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /// Class intended to support codegen of all kind of the reduction clauses. 1280b57cec5SDimitry Andric class ReductionCodeGen { 1290b57cec5SDimitry Andric private: 1300b57cec5SDimitry Andric /// Data required for codegen of reduction clauses. 1310b57cec5SDimitry Andric struct ReductionData { 1325ffd83dbSDimitry Andric /// Reference to the item shared between tasks to reduce into. 1335ffd83dbSDimitry Andric const Expr *Shared = nullptr; 1345ffd83dbSDimitry Andric /// Reference to the original item. 1350b57cec5SDimitry Andric const Expr *Ref = nullptr; 1360b57cec5SDimitry Andric /// Helper expression for generation of private copy. 1370b57cec5SDimitry Andric const Expr *Private = nullptr; 1380b57cec5SDimitry Andric /// Helper expression for generation reduction operation. 1390b57cec5SDimitry Andric const Expr *ReductionOp = nullptr; ReductionDataReductionData1405ffd83dbSDimitry Andric ReductionData(const Expr *Shared, const Expr *Ref, const Expr *Private, 1415ffd83dbSDimitry Andric const Expr *ReductionOp) 1425ffd83dbSDimitry Andric : Shared(Shared), Ref(Ref), Private(Private), ReductionOp(ReductionOp) { 1435ffd83dbSDimitry Andric } 1440b57cec5SDimitry Andric }; 1450b57cec5SDimitry Andric /// List of reduction-based clauses. 1460b57cec5SDimitry Andric SmallVector<ReductionData, 4> ClausesData; 1470b57cec5SDimitry Andric 1485ffd83dbSDimitry Andric /// List of addresses of shared variables/expressions. 1490b57cec5SDimitry Andric SmallVector<std::pair<LValue, LValue>, 4> SharedAddresses; 1505ffd83dbSDimitry Andric /// List of addresses of original variables/expressions. 1515ffd83dbSDimitry Andric SmallVector<std::pair<LValue, LValue>, 4> OrigAddresses; 1520b57cec5SDimitry Andric /// Sizes of the reduction items in chars. 1530b57cec5SDimitry Andric SmallVector<std::pair<llvm::Value *, llvm::Value *>, 4> Sizes; 1540b57cec5SDimitry Andric /// Base declarations for the reduction items. 1550b57cec5SDimitry Andric SmallVector<const VarDecl *, 4> BaseDecls; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric /// Emits lvalue for shared expression. 1580b57cec5SDimitry Andric LValue emitSharedLValue(CodeGenFunction &CGF, const Expr *E); 1590b57cec5SDimitry Andric /// Emits upper bound for shared expression (if array section). 1600b57cec5SDimitry Andric LValue emitSharedLValueUB(CodeGenFunction &CGF, const Expr *E); 1610b57cec5SDimitry Andric /// Performs aggregate initialization. 1620b57cec5SDimitry Andric /// \param N Number of reduction item in the common list. 1630b57cec5SDimitry Andric /// \param PrivateAddr Address of the corresponding private item. 1640eae32dcSDimitry Andric /// \param SharedAddr Address of the original shared variable. 1650b57cec5SDimitry Andric /// \param DRD Declare reduction construct used for reduction item. 1660b57cec5SDimitry Andric void emitAggregateInitialization(CodeGenFunction &CGF, unsigned N, 1670eae32dcSDimitry Andric Address PrivateAddr, Address SharedAddr, 1680b57cec5SDimitry Andric const OMPDeclareReductionDecl *DRD); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric public: 1715ffd83dbSDimitry Andric ReductionCodeGen(ArrayRef<const Expr *> Shareds, ArrayRef<const Expr *> Origs, 1720b57cec5SDimitry Andric ArrayRef<const Expr *> Privates, 1730b57cec5SDimitry Andric ArrayRef<const Expr *> ReductionOps); 1745ffd83dbSDimitry Andric /// Emits lvalue for the shared and original reduction item. 1750b57cec5SDimitry Andric /// \param N Number of the reduction item. 1765ffd83dbSDimitry Andric void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N); 1770b57cec5SDimitry Andric /// Emits the code for the variable-modified type, if required. 1780b57cec5SDimitry Andric /// \param N Number of the reduction item. 1790b57cec5SDimitry Andric void emitAggregateType(CodeGenFunction &CGF, unsigned N); 1800b57cec5SDimitry Andric /// Emits the code for the variable-modified type, if required. 1810b57cec5SDimitry Andric /// \param N Number of the reduction item. 1820b57cec5SDimitry Andric /// \param Size Size of the type in chars. 1830b57cec5SDimitry Andric void emitAggregateType(CodeGenFunction &CGF, unsigned N, llvm::Value *Size); 1840b57cec5SDimitry Andric /// Performs initialization of the private copy for the reduction item. 1850b57cec5SDimitry Andric /// \param N Number of the reduction item. 1860b57cec5SDimitry Andric /// \param PrivateAddr Address of the corresponding private item. 1870b57cec5SDimitry Andric /// \param DefaultInit Default initialization sequence that should be 1880b57cec5SDimitry Andric /// performed if no reduction specific initialization is found. 1890eae32dcSDimitry Andric /// \param SharedAddr Address of the original shared variable. 1900b57cec5SDimitry Andric void 1910b57cec5SDimitry Andric emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, 1920eae32dcSDimitry Andric Address SharedAddr, 1930b57cec5SDimitry Andric llvm::function_ref<bool(CodeGenFunction &)> DefaultInit); 1940b57cec5SDimitry Andric /// Returns true if the private copy requires cleanups. 1950b57cec5SDimitry Andric bool needCleanups(unsigned N); 1960b57cec5SDimitry Andric /// Emits cleanup code for the reduction item. 1970b57cec5SDimitry Andric /// \param N Number of the reduction item. 1980b57cec5SDimitry Andric /// \param PrivateAddr Address of the corresponding private item. 1990b57cec5SDimitry Andric void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr); 2000b57cec5SDimitry Andric /// Adjusts \p PrivatedAddr for using instead of the original variable 2010b57cec5SDimitry Andric /// address in normal operations. 2020b57cec5SDimitry Andric /// \param N Number of the reduction item. 2030b57cec5SDimitry Andric /// \param PrivateAddr Address of the corresponding private item. 2040b57cec5SDimitry Andric Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 2050b57cec5SDimitry Andric Address PrivateAddr); 2060b57cec5SDimitry Andric /// Returns LValue for the reduction item. getSharedLValue(unsigned N)2070b57cec5SDimitry Andric LValue getSharedLValue(unsigned N) const { return SharedAddresses[N].first; } 2085ffd83dbSDimitry Andric /// Returns LValue for the original reduction item. getOrigLValue(unsigned N)2095ffd83dbSDimitry Andric LValue getOrigLValue(unsigned N) const { return OrigAddresses[N].first; } 2100b57cec5SDimitry Andric /// Returns the size of the reduction item (in chars and total number of 2110b57cec5SDimitry Andric /// elements in the item), or nullptr, if the size is a constant. getSizes(unsigned N)2120b57cec5SDimitry Andric std::pair<llvm::Value *, llvm::Value *> getSizes(unsigned N) const { 2130b57cec5SDimitry Andric return Sizes[N]; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric /// Returns the base declaration of the reduction item. getBaseDecl(unsigned N)2160b57cec5SDimitry Andric const VarDecl *getBaseDecl(unsigned N) const { return BaseDecls[N]; } 2170b57cec5SDimitry Andric /// Returns the base declaration of the reduction item. getRefExpr(unsigned N)2180b57cec5SDimitry Andric const Expr *getRefExpr(unsigned N) const { return ClausesData[N].Ref; } 2190b57cec5SDimitry Andric /// Returns true if the initialization of the reduction item uses initializer 2200b57cec5SDimitry Andric /// from declare reduction construct. 2210b57cec5SDimitry Andric bool usesReductionInitializer(unsigned N) const; 22281ad6265SDimitry Andric /// Return the type of the private item. getPrivateType(unsigned N)22381ad6265SDimitry Andric QualType getPrivateType(unsigned N) const { 22481ad6265SDimitry Andric return cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()) 22581ad6265SDimitry Andric ->getType(); 22681ad6265SDimitry Andric } 2270b57cec5SDimitry Andric }; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric class CGOpenMPRuntime { 2300b57cec5SDimitry Andric public: 2310b57cec5SDimitry Andric /// Allows to disable automatic handling of functions used in target regions 2320b57cec5SDimitry Andric /// as those marked as `omp declare target`. 2330b57cec5SDimitry Andric class DisableAutoDeclareTargetRAII { 2340b57cec5SDimitry Andric CodeGenModule &CGM; 23506c3fb27SDimitry Andric bool SavedShouldMarkAsGlobal = false; 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric public: 2380b57cec5SDimitry Andric DisableAutoDeclareTargetRAII(CodeGenModule &CGM); 2390b57cec5SDimitry Andric ~DisableAutoDeclareTargetRAII(); 2400b57cec5SDimitry Andric }; 2410b57cec5SDimitry Andric 242480093f4SDimitry Andric /// Manages list of nontemporal decls for the specified directive. 243480093f4SDimitry Andric class NontemporalDeclsRAII { 244480093f4SDimitry Andric CodeGenModule &CGM; 245480093f4SDimitry Andric const bool NeedToPush; 246480093f4SDimitry Andric 247480093f4SDimitry Andric public: 248480093f4SDimitry Andric NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S); 249480093f4SDimitry Andric ~NontemporalDeclsRAII(); 250480093f4SDimitry Andric }; 251480093f4SDimitry Andric 252e8d8bef9SDimitry Andric /// Manages list of nontemporal decls for the specified directive. 253e8d8bef9SDimitry Andric class UntiedTaskLocalDeclsRAII { 254e8d8bef9SDimitry Andric CodeGenModule &CGM; 255e8d8bef9SDimitry Andric const bool NeedToPush; 256e8d8bef9SDimitry Andric 257e8d8bef9SDimitry Andric public: 258e8d8bef9SDimitry Andric UntiedTaskLocalDeclsRAII( 259e8d8bef9SDimitry Andric CodeGenFunction &CGF, 260fe6060f1SDimitry Andric const llvm::MapVector<CanonicalDeclPtr<const VarDecl>, 261e8d8bef9SDimitry Andric std::pair<Address, Address>> &LocalVars); 262e8d8bef9SDimitry Andric ~UntiedTaskLocalDeclsRAII(); 263e8d8bef9SDimitry Andric }; 264e8d8bef9SDimitry Andric 265480093f4SDimitry Andric /// Maps the expression for the lastprivate variable to the global copy used 266480093f4SDimitry Andric /// to store new value because original variables are not mapped in inner 267480093f4SDimitry Andric /// parallel regions. Only private copies are captured but we need also to 268480093f4SDimitry Andric /// store private copy in shared address. 269480093f4SDimitry Andric /// Also, stores the expression for the private loop counter and it 270480093f4SDimitry Andric /// threaprivate name. 271480093f4SDimitry Andric struct LastprivateConditionalData { 2725ffd83dbSDimitry Andric llvm::MapVector<CanonicalDeclPtr<const Decl>, SmallString<16>> 2735ffd83dbSDimitry Andric DeclToUniqueName; 274480093f4SDimitry Andric LValue IVLVal; 2755ffd83dbSDimitry Andric llvm::Function *Fn = nullptr; 2765ffd83dbSDimitry Andric bool Disabled = false; 277480093f4SDimitry Andric }; 278480093f4SDimitry Andric /// Manages list of lastprivate conditional decls for the specified directive. 279480093f4SDimitry Andric class LastprivateConditionalRAII { 2805ffd83dbSDimitry Andric enum class ActionToDo { 2815ffd83dbSDimitry Andric DoNotPush, 2825ffd83dbSDimitry Andric PushAsLastprivateConditional, 2835ffd83dbSDimitry Andric DisableLastprivateConditional, 2845ffd83dbSDimitry Andric }; 285480093f4SDimitry Andric CodeGenModule &CGM; 2865ffd83dbSDimitry Andric ActionToDo Action = ActionToDo::DoNotPush; 2875ffd83dbSDimitry Andric 2885ffd83dbSDimitry Andric /// Check and try to disable analysis of inner regions for changes in 2895ffd83dbSDimitry Andric /// lastprivate conditional. 2905ffd83dbSDimitry Andric void tryToDisableInnerAnalysis(const OMPExecutableDirective &S, 2915ffd83dbSDimitry Andric llvm::DenseSet<CanonicalDeclPtr<const Decl>> 2925ffd83dbSDimitry Andric &NeedToAddForLPCsAsDisabled) const; 2935ffd83dbSDimitry Andric 2945ffd83dbSDimitry Andric LastprivateConditionalRAII(CodeGenFunction &CGF, 2955ffd83dbSDimitry Andric const OMPExecutableDirective &S); 296480093f4SDimitry Andric 297480093f4SDimitry Andric public: 2985ffd83dbSDimitry Andric explicit LastprivateConditionalRAII(CodeGenFunction &CGF, 2995ffd83dbSDimitry Andric const OMPExecutableDirective &S, 3005ffd83dbSDimitry Andric LValue IVLVal); 3015ffd83dbSDimitry Andric static LastprivateConditionalRAII disable(CodeGenFunction &CGF, 3025ffd83dbSDimitry Andric const OMPExecutableDirective &S); 303480093f4SDimitry Andric ~LastprivateConditionalRAII(); 304480093f4SDimitry Andric }; 305480093f4SDimitry Andric getOMPBuilder()3065ffd83dbSDimitry Andric llvm::OpenMPIRBuilder &getOMPBuilder() { return OMPBuilder; } 3075ffd83dbSDimitry Andric 3080b57cec5SDimitry Andric protected: 3090b57cec5SDimitry Andric CodeGenModule &CGM; 3100b57cec5SDimitry Andric 311e8d8bef9SDimitry Andric /// An OpenMP-IR-Builder instance. 312e8d8bef9SDimitry Andric llvm::OpenMPIRBuilder OMPBuilder; 313e8d8bef9SDimitry Andric 3145f757f3fSDimitry Andric /// Helper to determine the min/max number of threads/teams for \p D. 3155f757f3fSDimitry Andric void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, 3165f757f3fSDimitry Andric CodeGenFunction &CGF, 3175f757f3fSDimitry Andric int32_t &MinThreadsVal, 3185f757f3fSDimitry Andric int32_t &MaxThreadsVal, 3195f757f3fSDimitry Andric int32_t &MinTeamsVal, 3205f757f3fSDimitry Andric int32_t &MaxTeamsVal); 3215f757f3fSDimitry Andric 3220b57cec5SDimitry Andric /// Helper to emit outlined function for 'target' directive. 3230b57cec5SDimitry Andric /// \param D Directive to emit. 3240b57cec5SDimitry Andric /// \param ParentName Name of the function that encloses the target region. 3250b57cec5SDimitry Andric /// \param OutlinedFn Outlined function value to be defined by this call. 3260b57cec5SDimitry Andric /// \param OutlinedFnID Outlined function ID value to be defined by this call. 3270b57cec5SDimitry Andric /// \param IsOffloadEntry True if the outlined function is an offload entry. 3280b57cec5SDimitry Andric /// \param CodeGen Lambda codegen specific to an accelerator device. 3290b57cec5SDimitry Andric /// An outlined function may not be an entry if, e.g. the if clause always 3300b57cec5SDimitry Andric /// evaluates to false. 3310b57cec5SDimitry Andric virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, 3320b57cec5SDimitry Andric StringRef ParentName, 3330b57cec5SDimitry Andric llvm::Function *&OutlinedFn, 3340b57cec5SDimitry Andric llvm::Constant *&OutlinedFnID, 3350b57cec5SDimitry Andric bool IsOffloadEntry, 3360b57cec5SDimitry Andric const RegionCodeGenTy &CodeGen); 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric /// Returns pointer to ident_t type. 3390b57cec5SDimitry Andric llvm::Type *getIdentTyPointerTy(); 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric /// Gets thread id value for the current thread. 3420b57cec5SDimitry Andric /// 3430b57cec5SDimitry Andric llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric /// Get the function name of an outlined region. 34606c3fb27SDimitry Andric std::string getOutlinedHelperName(StringRef Name) const; 34706c3fb27SDimitry Andric std::string getOutlinedHelperName(CodeGenFunction &CGF) const; 34806c3fb27SDimitry Andric 34906c3fb27SDimitry Andric /// Get the function name of a reduction function. 35006c3fb27SDimitry Andric std::string getReductionFuncName(StringRef Name) const; 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric /// Emits \p Callee function call with arguments \p Args with location \p Loc. 3530b57cec5SDimitry Andric void emitCall(CodeGenFunction &CGF, SourceLocation Loc, 3540b57cec5SDimitry Andric llvm::FunctionCallee Callee, 355bdd1243dSDimitry Andric ArrayRef<llvm::Value *> Args = std::nullopt) const; 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric /// Emits address of the word in a memory where current thread id is 3580b57cec5SDimitry Andric /// stored. 3590b57cec5SDimitry Andric virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc); 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric void setLocThreadIdInsertPt(CodeGenFunction &CGF, 3620b57cec5SDimitry Andric bool AtCurrentPoint = false); 3630b57cec5SDimitry Andric void clearLocThreadIdInsertPt(CodeGenFunction &CGF); 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric /// Check if the default location must be constant. 3660b57cec5SDimitry Andric /// Default is false to support OMPT/OMPD. isDefaultLocationConstant()3670b57cec5SDimitry Andric virtual bool isDefaultLocationConstant() const { return false; } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric /// Returns additional flags that can be stored in reserved_2 field of the 3700b57cec5SDimitry Andric /// default location. getDefaultLocationReserved2Flags()3710b57cec5SDimitry Andric virtual unsigned getDefaultLocationReserved2Flags() const { return 0; } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric /// Returns default flags for the barriers depending on the directive, for 3740b57cec5SDimitry Andric /// which this barier is going to be emitted. 3750b57cec5SDimitry Andric static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind); 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric /// Get the LLVM type for the critical name. getKmpCriticalNameTy()3780b57cec5SDimitry Andric llvm::ArrayType *getKmpCriticalNameTy() const {return KmpCriticalNameTy;} 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric /// Returns corresponding lock object for the specified critical region 3810b57cec5SDimitry Andric /// name. If the lock object does not exist it is created, otherwise the 3820b57cec5SDimitry Andric /// reference to the existing copy is returned. 3830b57cec5SDimitry Andric /// \param CriticalName Name of the critical region. 3840b57cec5SDimitry Andric /// 3850b57cec5SDimitry Andric llvm::Value *getCriticalRegionLock(StringRef CriticalName); 3860b57cec5SDimitry Andric 387bdd1243dSDimitry Andric protected: 3880b57cec5SDimitry Andric /// Map for SourceLocation and OpenMP runtime library debug locations. 389e8d8bef9SDimitry Andric typedef llvm::DenseMap<SourceLocation, llvm::Value *> OpenMPDebugLocMapTy; 3900b57cec5SDimitry Andric OpenMPDebugLocMapTy OpenMPDebugLocMap; 3910b57cec5SDimitry Andric /// The type for a microtask which gets passed to __kmpc_fork_call(). 3920b57cec5SDimitry Andric /// Original representation is: 3930b57cec5SDimitry Andric /// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...); 3940b57cec5SDimitry Andric llvm::FunctionType *Kmpc_MicroTy = nullptr; 3950b57cec5SDimitry Andric /// Stores debug location and ThreadID for the function. 3960b57cec5SDimitry Andric struct DebugLocThreadIdTy { 3970b57cec5SDimitry Andric llvm::Value *DebugLoc; 3980b57cec5SDimitry Andric llvm::Value *ThreadID; 3990b57cec5SDimitry Andric /// Insert point for the service instructions. 4000b57cec5SDimitry Andric llvm::AssertingVH<llvm::Instruction> ServiceInsertPt = nullptr; 4010b57cec5SDimitry Andric }; 4020b57cec5SDimitry Andric /// Map of local debug location, ThreadId and functions. 4030b57cec5SDimitry Andric typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy> 4040b57cec5SDimitry Andric OpenMPLocThreadIDMapTy; 4050b57cec5SDimitry Andric OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap; 4060b57cec5SDimitry Andric /// Map of UDRs and corresponding combiner/initializer. 4070b57cec5SDimitry Andric typedef llvm::DenseMap<const OMPDeclareReductionDecl *, 4080b57cec5SDimitry Andric std::pair<llvm::Function *, llvm::Function *>> 4090b57cec5SDimitry Andric UDRMapTy; 4100b57cec5SDimitry Andric UDRMapTy UDRMap; 4110b57cec5SDimitry Andric /// Map of functions and locally defined UDRs. 4120b57cec5SDimitry Andric typedef llvm::DenseMap<llvm::Function *, 4130b57cec5SDimitry Andric SmallVector<const OMPDeclareReductionDecl *, 4>> 4140b57cec5SDimitry Andric FunctionUDRMapTy; 4150b57cec5SDimitry Andric FunctionUDRMapTy FunctionUDRMap; 416a7dea167SDimitry Andric /// Map from the user-defined mapper declaration to its corresponding 417a7dea167SDimitry Andric /// functions. 418a7dea167SDimitry Andric llvm::DenseMap<const OMPDeclareMapperDecl *, llvm::Function *> UDMMap; 419a7dea167SDimitry Andric /// Map of functions and their local user-defined mappers. 420a7dea167SDimitry Andric using FunctionUDMMapTy = 421a7dea167SDimitry Andric llvm::DenseMap<llvm::Function *, 422a7dea167SDimitry Andric SmallVector<const OMPDeclareMapperDecl *, 4>>; 423a7dea167SDimitry Andric FunctionUDMMapTy FunctionUDMMap; 4245ffd83dbSDimitry Andric /// Maps local variables marked as lastprivate conditional to their internal 4255ffd83dbSDimitry Andric /// types. 4265ffd83dbSDimitry Andric llvm::DenseMap<llvm::Function *, 4275ffd83dbSDimitry Andric llvm::DenseMap<CanonicalDeclPtr<const Decl>, 4285ffd83dbSDimitry Andric std::tuple<QualType, const FieldDecl *, 4295ffd83dbSDimitry Andric const FieldDecl *, LValue>>> 4305ffd83dbSDimitry Andric LastprivateConditionalToTypes; 431e8d8bef9SDimitry Andric /// Maps function to the position of the untied task locals stack. 432e8d8bef9SDimitry Andric llvm::DenseMap<llvm::Function *, unsigned> FunctionToUntiedTaskStackMap; 4330b57cec5SDimitry Andric /// Type kmp_critical_name, originally defined as typedef kmp_int32 4340b57cec5SDimitry Andric /// kmp_critical_name[8]; 4350b57cec5SDimitry Andric llvm::ArrayType *KmpCriticalNameTy; 4360b57cec5SDimitry Andric /// An ordered map of auto-generated variables to their unique names. 4370b57cec5SDimitry Andric /// It stores variables with the following names: 1) ".gomp_critical_user_" + 4380b57cec5SDimitry Andric /// <critical_section_name> + ".var" for "omp critical" directives; 2) 4390b57cec5SDimitry Andric /// <mangled_name_for_global_var> + ".cache." for cache for threadprivate 4400b57cec5SDimitry Andric /// variables. 4410eae32dcSDimitry Andric llvm::StringMap<llvm::AssertingVH<llvm::GlobalVariable>, 4420eae32dcSDimitry Andric llvm::BumpPtrAllocator> InternalVars; 4430b57cec5SDimitry Andric /// Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); 4440b57cec5SDimitry Andric llvm::Type *KmpRoutineEntryPtrTy = nullptr; 4450b57cec5SDimitry Andric QualType KmpRoutineEntryPtrQTy; 4460b57cec5SDimitry Andric /// Type typedef struct kmp_task { 4470b57cec5SDimitry Andric /// void * shareds; /**< pointer to block of pointers to 4480b57cec5SDimitry Andric /// shared vars */ 4490b57cec5SDimitry Andric /// kmp_routine_entry_t routine; /**< pointer to routine to call for 4500b57cec5SDimitry Andric /// executing task */ 4510b57cec5SDimitry Andric /// kmp_int32 part_id; /**< part id for the task */ 4520b57cec5SDimitry Andric /// kmp_routine_entry_t destructors; /* pointer to function to invoke 4530b57cec5SDimitry Andric /// deconstructors of firstprivate C++ objects */ 4540b57cec5SDimitry Andric /// } kmp_task_t; 4550b57cec5SDimitry Andric QualType KmpTaskTQTy; 4560b57cec5SDimitry Andric /// Saved kmp_task_t for task directive. 4570b57cec5SDimitry Andric QualType SavedKmpTaskTQTy; 4580b57cec5SDimitry Andric /// Saved kmp_task_t for taskloop-based directive. 4590b57cec5SDimitry Andric QualType SavedKmpTaskloopTQTy; 4600b57cec5SDimitry Andric /// Type typedef struct kmp_depend_info { 4610b57cec5SDimitry Andric /// kmp_intptr_t base_addr; 4620b57cec5SDimitry Andric /// size_t len; 4630b57cec5SDimitry Andric /// struct { 4640b57cec5SDimitry Andric /// bool in:1; 4650b57cec5SDimitry Andric /// bool out:1; 4660b57cec5SDimitry Andric /// } flags; 4670b57cec5SDimitry Andric /// } kmp_depend_info_t; 4680b57cec5SDimitry Andric QualType KmpDependInfoTy; 4695ffd83dbSDimitry Andric /// Type typedef struct kmp_task_affinity_info { 4705ffd83dbSDimitry Andric /// kmp_intptr_t base_addr; 4715ffd83dbSDimitry Andric /// size_t len; 4725ffd83dbSDimitry Andric /// struct { 4735ffd83dbSDimitry Andric /// bool flag1 : 1; 4745ffd83dbSDimitry Andric /// bool flag2 : 1; 4755ffd83dbSDimitry Andric /// kmp_int32 reserved : 30; 4765ffd83dbSDimitry Andric /// } flags; 4775ffd83dbSDimitry Andric /// } kmp_task_affinity_info_t; 4785ffd83dbSDimitry Andric QualType KmpTaskAffinityInfoTy; 4790b57cec5SDimitry Andric /// struct kmp_dim { // loop bounds info casted to kmp_int64 4800b57cec5SDimitry Andric /// kmp_int64 lo; // lower 4810b57cec5SDimitry Andric /// kmp_int64 up; // upper 4820b57cec5SDimitry Andric /// kmp_int64 st; // stride 4830b57cec5SDimitry Andric /// }; 4840b57cec5SDimitry Andric QualType KmpDimTy; 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric bool ShouldMarkAsGlobal = true; 487480093f4SDimitry Andric /// List of the emitted declarations. 488480093f4SDimitry Andric llvm::DenseSet<CanonicalDeclPtr<const Decl>> AlreadyEmittedTargetDecls; 4890b57cec5SDimitry Andric /// List of the global variables with their addresses that should not be 4900b57cec5SDimitry Andric /// emitted for the target. 4910b57cec5SDimitry Andric llvm::StringMap<llvm::WeakTrackingVH> EmittedNonTargetVariables; 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric /// List of variables that can become declare target implicitly and, thus, 4940b57cec5SDimitry Andric /// must be emitted. 4950b57cec5SDimitry Andric llvm::SmallDenseSet<const VarDecl *> DeferredGlobalVariables; 4960b57cec5SDimitry Andric 497480093f4SDimitry Andric using NontemporalDeclsSet = llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>>; 498480093f4SDimitry Andric /// Stack for list of declarations in current context marked as nontemporal. 499480093f4SDimitry Andric /// The set is the union of all current stack elements. 500480093f4SDimitry Andric llvm::SmallVector<NontemporalDeclsSet, 4> NontemporalDeclsStack; 501480093f4SDimitry Andric 502e8d8bef9SDimitry Andric using UntiedLocalVarsAddressesMap = 503fe6060f1SDimitry Andric llvm::MapVector<CanonicalDeclPtr<const VarDecl>, 504e8d8bef9SDimitry Andric std::pair<Address, Address>>; 505e8d8bef9SDimitry Andric llvm::SmallVector<UntiedLocalVarsAddressesMap, 4> UntiedLocalVarsStack; 506e8d8bef9SDimitry Andric 507480093f4SDimitry Andric /// Stack for list of addresses of declarations in current context marked as 508480093f4SDimitry Andric /// lastprivate conditional. The set is the union of all current stack 509480093f4SDimitry Andric /// elements. 510480093f4SDimitry Andric llvm::SmallVector<LastprivateConditionalData, 4> LastprivateConditionalStack; 511480093f4SDimitry Andric 5120b57cec5SDimitry Andric /// Flag for keeping track of weather a requires unified_shared_memory 5130b57cec5SDimitry Andric /// directive is present. 5140b57cec5SDimitry Andric bool HasRequiresUnifiedSharedMemory = false; 5150b57cec5SDimitry Andric 5165ffd83dbSDimitry Andric /// Atomic ordering from the omp requires directive. 5175ffd83dbSDimitry Andric llvm::AtomicOrdering RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 5185ffd83dbSDimitry Andric 5190b57cec5SDimitry Andric /// Flag for keeping track of weather a target region has been emitted. 5200b57cec5SDimitry Andric bool HasEmittedTargetRegion = false; 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric /// Flag for keeping track of weather a device routine has been emitted. 5230b57cec5SDimitry Andric /// Device routines are specific to the 5240b57cec5SDimitry Andric bool HasEmittedDeclareTargetRegion = false; 5250b57cec5SDimitry Andric 526bdd1243dSDimitry Andric /// Start scanning from statement \a S and emit all target regions 5270b57cec5SDimitry Andric /// found along the way. 5280b57cec5SDimitry Andric /// \param S Starting statement. 5290b57cec5SDimitry Andric /// \param ParentName Name of the function declaration that is being scanned. 5300b57cec5SDimitry Andric void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName); 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric /// Build type kmp_routine_entry_t (if not built yet). 5330b57cec5SDimitry Andric void emitKmpRoutineEntryT(QualType KmpInt32Ty); 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric /// Returns pointer to kmpc_micro type. 5360b57cec5SDimitry Andric llvm::Type *getKmpc_MicroPointerTy(); 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric /// If the specified mangled name is not in the module, create and 5390b57cec5SDimitry Andric /// return threadprivate cache object. This object is a pointer's worth of 5400b57cec5SDimitry Andric /// storage that's reserved for use by the OpenMP runtime. 5410b57cec5SDimitry Andric /// \param VD Threadprivate variable. 5420b57cec5SDimitry Andric /// \return Cache variable for the specified threadprivate. 5430b57cec5SDimitry Andric llvm::Constant *getOrCreateThreadPrivateCache(const VarDecl *VD); 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric /// Set of threadprivate variables with the generated initializer. 5460b57cec5SDimitry Andric llvm::StringSet<> ThreadPrivateWithDefinition; 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric /// Set of declare target variables with the generated initializer. 5490b57cec5SDimitry Andric llvm::StringSet<> DeclareTargetWithDefinition; 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric /// Emits initialization code for the threadprivate variables. 5520b57cec5SDimitry Andric /// \param VDAddr Address of the global variable \a VD. 5530b57cec5SDimitry Andric /// \param Ctor Pointer to a global init function for \a VD. 5540b57cec5SDimitry Andric /// \param CopyCtor Pointer to a global copy function for \a VD. 5550b57cec5SDimitry Andric /// \param Dtor Pointer to a global destructor function for \a VD. 5560b57cec5SDimitry Andric /// \param Loc Location of threadprivate declaration. 5570b57cec5SDimitry Andric void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, 5580b57cec5SDimitry Andric llvm::Value *Ctor, llvm::Value *CopyCtor, 5590b57cec5SDimitry Andric llvm::Value *Dtor, SourceLocation Loc); 5600b57cec5SDimitry Andric 561a7dea167SDimitry Andric /// Emit the array initialization or deletion portion for user-defined mapper 562a7dea167SDimitry Andric /// code generation. 563a7dea167SDimitry Andric void emitUDMapperArrayInitOrDel(CodeGenFunction &MapperCGF, 564a7dea167SDimitry Andric llvm::Value *Handle, llvm::Value *BasePtr, 565a7dea167SDimitry Andric llvm::Value *Ptr, llvm::Value *Size, 566fe6060f1SDimitry Andric llvm::Value *MapType, llvm::Value *MapName, 567fe6060f1SDimitry Andric CharUnits ElementSize, 568a7dea167SDimitry Andric llvm::BasicBlock *ExitBB, bool IsInit); 569a7dea167SDimitry Andric 5700b57cec5SDimitry Andric struct TaskResultTy { 5710b57cec5SDimitry Andric llvm::Value *NewTask = nullptr; 5720b57cec5SDimitry Andric llvm::Function *TaskEntry = nullptr; 5730b57cec5SDimitry Andric llvm::Value *NewTaskNewTaskTTy = nullptr; 5740b57cec5SDimitry Andric LValue TDBase; 5750b57cec5SDimitry Andric const RecordDecl *KmpTaskTQTyRD = nullptr; 5760b57cec5SDimitry Andric llvm::Value *TaskDupFn = nullptr; 5770b57cec5SDimitry Andric }; 5780b57cec5SDimitry Andric /// Emit task region for the task directive. The task region is emitted in 5790b57cec5SDimitry Andric /// several steps: 5800b57cec5SDimitry Andric /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 5810b57cec5SDimitry Andric /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5820b57cec5SDimitry Andric /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the 5830b57cec5SDimitry Andric /// function: 5840b57cec5SDimitry Andric /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 5850b57cec5SDimitry Andric /// TaskFunction(gtid, tt->part_id, tt->shareds); 5860b57cec5SDimitry Andric /// return 0; 5870b57cec5SDimitry Andric /// } 5880b57cec5SDimitry Andric /// 2. Copy a list of shared variables to field shareds of the resulting 5890b57cec5SDimitry Andric /// structure kmp_task_t returned by the previous call (if any). 5900b57cec5SDimitry Andric /// 3. Copy a pointer to destructions function to field destructions of the 5910b57cec5SDimitry Andric /// resulting structure kmp_task_t. 5920b57cec5SDimitry Andric /// \param D Current task directive. 5930b57cec5SDimitry Andric /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 5940b57cec5SDimitry Andric /// /*part_id*/, captured_struct */*__context*/); 5950b57cec5SDimitry Andric /// \param SharedsTy A type which contains references the shared variables. 5960b57cec5SDimitry Andric /// \param Shareds Context with the list of shared variables from the \p 5970b57cec5SDimitry Andric /// TaskFunction. 5980b57cec5SDimitry Andric /// \param Data Additional data for task generation like tiednsee, final 5990b57cec5SDimitry Andric /// state, list of privates etc. 6000b57cec5SDimitry Andric TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 6010b57cec5SDimitry Andric const OMPExecutableDirective &D, 6020b57cec5SDimitry Andric llvm::Function *TaskFunction, QualType SharedsTy, 6030b57cec5SDimitry Andric Address Shareds, const OMPTaskDataTy &Data); 6040b57cec5SDimitry Andric 6055ffd83dbSDimitry Andric /// Emit update for lastprivate conditional data. 6065ffd83dbSDimitry Andric void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, 6075ffd83dbSDimitry Andric StringRef UniqueDeclName, LValue LVal, 6085ffd83dbSDimitry Andric SourceLocation Loc); 6095ffd83dbSDimitry Andric 6105ffd83dbSDimitry Andric /// Returns the number of the elements and the address of the depobj 6115ffd83dbSDimitry Andric /// dependency array. 6125ffd83dbSDimitry Andric /// \return Number of elements in depobj array and the pointer to the array of 6135ffd83dbSDimitry Andric /// dependencies. 6145ffd83dbSDimitry Andric std::pair<llvm::Value *, LValue> getDepobjElements(CodeGenFunction &CGF, 6155ffd83dbSDimitry Andric LValue DepobjLVal, 6165ffd83dbSDimitry Andric SourceLocation Loc); 6175ffd83dbSDimitry Andric 61881ad6265SDimitry Andric SmallVector<llvm::Value *, 4> 61981ad6265SDimitry Andric emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 62081ad6265SDimitry Andric const OMPTaskDataTy::DependData &Data); 62181ad6265SDimitry Andric 62281ad6265SDimitry Andric void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 62381ad6265SDimitry Andric LValue PosLVal, const OMPTaskDataTy::DependData &Data, 62481ad6265SDimitry Andric Address DependenciesArray); 62581ad6265SDimitry Andric 6260b57cec5SDimitry Andric public: 627bdd1243dSDimitry Andric explicit CGOpenMPRuntime(CodeGenModule &CGM); ~CGOpenMPRuntime()6280b57cec5SDimitry Andric virtual ~CGOpenMPRuntime() {} 6290b57cec5SDimitry Andric virtual void clear(); 6300b57cec5SDimitry Andric 63106c3fb27SDimitry Andric /// Emits object of ident_t type with info for source location. 63206c3fb27SDimitry Andric /// \param Flags Flags for OpenMP location. 63306c3fb27SDimitry Andric /// \param EmitLoc emit source location with debug-info is off. 63406c3fb27SDimitry Andric /// 63506c3fb27SDimitry Andric llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, 63606c3fb27SDimitry Andric unsigned Flags = 0, bool EmitLoc = false); 63706c3fb27SDimitry Andric 63806c3fb27SDimitry Andric /// Emit the number of teams for a target directive. Inspect the num_teams 63906c3fb27SDimitry Andric /// clause associated with a teams construct combined or closely nested 64006c3fb27SDimitry Andric /// with the target directive. 64106c3fb27SDimitry Andric /// 64206c3fb27SDimitry Andric /// Emit a team of size one for directives such as 'target parallel' that 64306c3fb27SDimitry Andric /// have no associated teams construct. 64406c3fb27SDimitry Andric /// 64506c3fb27SDimitry Andric /// Otherwise, return nullptr. 64606c3fb27SDimitry Andric const Expr *getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, 64706c3fb27SDimitry Andric const OMPExecutableDirective &D, 6485f757f3fSDimitry Andric int32_t &MinTeamsVal, 6495f757f3fSDimitry Andric int32_t &MaxTeamsVal); 65006c3fb27SDimitry Andric llvm::Value *emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 65106c3fb27SDimitry Andric const OMPExecutableDirective &D); 6525f757f3fSDimitry Andric 6535f757f3fSDimitry Andric /// Check for a number of threads upper bound constant value (stored in \p 6545f757f3fSDimitry Andric /// UpperBound), or expression (returned). If the value is conditional (via an 6555f757f3fSDimitry Andric /// if-clause), store the condition in \p CondExpr. Similarly, a potential 6565f757f3fSDimitry Andric /// thread limit expression is stored in \p ThreadLimitExpr. If \p 6575f757f3fSDimitry Andric /// UpperBoundOnly is true, no expression evaluation is perfomed. 6585f757f3fSDimitry Andric const Expr *getNumThreadsExprForTargetDirective( 6595f757f3fSDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 6605f757f3fSDimitry Andric int32_t &UpperBound, bool UpperBoundOnly, 6615f757f3fSDimitry Andric llvm::Value **CondExpr = nullptr, const Expr **ThreadLimitExpr = nullptr); 6625f757f3fSDimitry Andric 6635f757f3fSDimitry Andric /// Emit an expression that denotes the number of threads a target region 6645f757f3fSDimitry Andric /// shall use. Will generate "i32 0" to allow the runtime to choose. 66506c3fb27SDimitry Andric llvm::Value * 66606c3fb27SDimitry Andric emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 66706c3fb27SDimitry Andric const OMPExecutableDirective &D); 66806c3fb27SDimitry Andric 66906c3fb27SDimitry Andric /// Return the trip count of loops associated with constructs / 'target teams 67006c3fb27SDimitry Andric /// distribute' and 'teams distribute parallel for'. \param SizeEmitter Emits 67106c3fb27SDimitry Andric /// the int64 value for the number of iterations of the associated loop. 67206c3fb27SDimitry Andric llvm::Value *emitTargetNumIterationsCall( 67306c3fb27SDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 67406c3fb27SDimitry Andric llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 67506c3fb27SDimitry Andric const OMPLoopDirective &D)> 67606c3fb27SDimitry Andric SizeEmitter); 67706c3fb27SDimitry Andric 678bdd1243dSDimitry Andric /// Returns true if the current target is a GPU. isGPU()67906c3fb27SDimitry Andric virtual bool isGPU() const { return false; } 68006c3fb27SDimitry Andric 68106c3fb27SDimitry Andric /// Check if the variable length declaration is delayed: isDelayedVariableLengthDecl(CodeGenFunction & CGF,const VarDecl * VD)68206c3fb27SDimitry Andric virtual bool isDelayedVariableLengthDecl(CodeGenFunction &CGF, 68306c3fb27SDimitry Andric const VarDecl *VD) const { 68406c3fb27SDimitry Andric return false; 68506c3fb27SDimitry Andric }; 68606c3fb27SDimitry Andric 68706c3fb27SDimitry Andric /// Get call to __kmpc_alloc_shared 68806c3fb27SDimitry Andric virtual std::pair<llvm::Value *, llvm::Value *> getKmpcAllocShared(CodeGenFunction & CGF,const VarDecl * VD)68906c3fb27SDimitry Andric getKmpcAllocShared(CodeGenFunction &CGF, const VarDecl *VD) { 69006c3fb27SDimitry Andric llvm_unreachable("not implemented"); 69106c3fb27SDimitry Andric } 69206c3fb27SDimitry Andric 69306c3fb27SDimitry Andric /// Get call to __kmpc_free_shared getKmpcFreeShared(CodeGenFunction & CGF,const std::pair<llvm::Value *,llvm::Value * > & AddrSizePair)69406c3fb27SDimitry Andric virtual void getKmpcFreeShared( 69506c3fb27SDimitry Andric CodeGenFunction &CGF, 69606c3fb27SDimitry Andric const std::pair<llvm::Value *, llvm::Value *> &AddrSizePair) { 69706c3fb27SDimitry Andric llvm_unreachable("not implemented"); 69806c3fb27SDimitry Andric } 699bdd1243dSDimitry Andric 700480093f4SDimitry Andric /// Emits code for OpenMP 'if' clause using specified \a CodeGen 701480093f4SDimitry Andric /// function. Here is the logic: 702480093f4SDimitry Andric /// if (Cond) { 703480093f4SDimitry Andric /// ThenGen(); 704480093f4SDimitry Andric /// } else { 705480093f4SDimitry Andric /// ElseGen(); 706480093f4SDimitry Andric /// } 707480093f4SDimitry Andric void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 708480093f4SDimitry Andric const RegionCodeGenTy &ThenGen, 709480093f4SDimitry Andric const RegionCodeGenTy &ElseGen); 710480093f4SDimitry Andric 7110b57cec5SDimitry Andric /// Checks if the \p Body is the \a CompoundStmt and returns its child 7120b57cec5SDimitry Andric /// statement iff there is only one that is not evaluatable at the compile 7130b57cec5SDimitry Andric /// time. 7140b57cec5SDimitry Andric static const Stmt *getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body); 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric /// Get the platform-specific name separator. 7170b57cec5SDimitry Andric std::string getName(ArrayRef<StringRef> Parts) const; 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric /// Emit code for the specified user defined reduction construct. 7200b57cec5SDimitry Andric virtual void emitUserDefinedReduction(CodeGenFunction *CGF, 7210b57cec5SDimitry Andric const OMPDeclareReductionDecl *D); 7220b57cec5SDimitry Andric /// Get combiner/initializer for the specified user-defined reduction, if any. 7230b57cec5SDimitry Andric virtual std::pair<llvm::Function *, llvm::Function *> 7240b57cec5SDimitry Andric getUserDefinedReduction(const OMPDeclareReductionDecl *D); 7250b57cec5SDimitry Andric 726a7dea167SDimitry Andric /// Emit the function for the user defined mapper construct. 727a7dea167SDimitry Andric void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 728a7dea167SDimitry Andric CodeGenFunction *CGF = nullptr); 729e8d8bef9SDimitry Andric /// Get the function for the specified user-defined mapper. If it does not 730e8d8bef9SDimitry Andric /// exist, create one. 731e8d8bef9SDimitry Andric llvm::Function * 732e8d8bef9SDimitry Andric getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D); 733a7dea167SDimitry Andric 7340b57cec5SDimitry Andric /// Emits outlined function for the specified OpenMP parallel directive 7350b57cec5SDimitry Andric /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, 7360b57cec5SDimitry Andric /// kmp_int32 BoundID, struct context_vars*). 73706c3fb27SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 7380b57cec5SDimitry Andric /// \param D OpenMP directive. 7390b57cec5SDimitry Andric /// \param ThreadIDVar Variable for thread id in the current OpenMP region. 7400b57cec5SDimitry Andric /// \param InnermostKind Kind of innermost directive (for simple directives it 7410b57cec5SDimitry Andric /// is a directive itself, for combined - its innermost directive). 7420b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 7430b57cec5SDimitry Andric virtual llvm::Function *emitParallelOutlinedFunction( 74406c3fb27SDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 74506c3fb27SDimitry Andric const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 74606c3fb27SDimitry Andric const RegionCodeGenTy &CodeGen); 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric /// Emits outlined function for the specified OpenMP teams directive 7490b57cec5SDimitry Andric /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, 7500b57cec5SDimitry Andric /// kmp_int32 BoundID, struct context_vars*). 75106c3fb27SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 7520b57cec5SDimitry Andric /// \param D OpenMP directive. 7530b57cec5SDimitry Andric /// \param ThreadIDVar Variable for thread id in the current OpenMP region. 7540b57cec5SDimitry Andric /// \param InnermostKind Kind of innermost directive (for simple directives it 7550b57cec5SDimitry Andric /// is a directive itself, for combined - its innermost directive). 7560b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 7570b57cec5SDimitry Andric virtual llvm::Function *emitTeamsOutlinedFunction( 75806c3fb27SDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 75906c3fb27SDimitry Andric const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 76006c3fb27SDimitry Andric const RegionCodeGenTy &CodeGen); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric /// Emits outlined function for the OpenMP task directive \a D. This 7630b57cec5SDimitry Andric /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t* 7640b57cec5SDimitry Andric /// TaskT). 7650b57cec5SDimitry Andric /// \param D OpenMP directive. 7660b57cec5SDimitry Andric /// \param ThreadIDVar Variable for thread id in the current OpenMP region. 7670b57cec5SDimitry Andric /// \param PartIDVar Variable for partition id in the current OpenMP untied 7680b57cec5SDimitry Andric /// task region. 7690b57cec5SDimitry Andric /// \param TaskTVar Variable for task_t argument. 7700b57cec5SDimitry Andric /// \param InnermostKind Kind of innermost directive (for simple directives it 7710b57cec5SDimitry Andric /// is a directive itself, for combined - its innermost directive). 7720b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 7730b57cec5SDimitry Andric /// \param Tied true if task is generated for tied task, false otherwise. 7740b57cec5SDimitry Andric /// \param NumberOfParts Number of parts in untied task. Ignored for tied 7750b57cec5SDimitry Andric /// tasks. 7760b57cec5SDimitry Andric /// 7770b57cec5SDimitry Andric virtual llvm::Function *emitTaskOutlinedFunction( 7780b57cec5SDimitry Andric const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 7790b57cec5SDimitry Andric const VarDecl *PartIDVar, const VarDecl *TaskTVar, 7800b57cec5SDimitry Andric OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 7810b57cec5SDimitry Andric bool Tied, unsigned &NumberOfParts); 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric /// Cleans up references to the objects in finished function. 7840b57cec5SDimitry Andric /// 7850b57cec5SDimitry Andric virtual void functionFinished(CodeGenFunction &CGF); 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric /// Emits code for parallel or serial call of the \a OutlinedFn with 7880b57cec5SDimitry Andric /// variables captured in a record which address is stored in \a 7890b57cec5SDimitry Andric /// CapturedStruct. 7900b57cec5SDimitry Andric /// \param OutlinedFn Outlined function to be run in parallel threads. Type of 7910b57cec5SDimitry Andric /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). 7920b57cec5SDimitry Andric /// \param CapturedVars A pointer to the record with the references to 7930b57cec5SDimitry Andric /// variables used in \a OutlinedFn function. 7940b57cec5SDimitry Andric /// \param IfCond Condition in the associated 'if' clause, if it was 7950b57cec5SDimitry Andric /// specified, nullptr otherwise. 7960eae32dcSDimitry Andric /// \param NumThreads The value corresponding to the num_threads clause, if 7970eae32dcSDimitry Andric /// any, or nullptr. 7980b57cec5SDimitry Andric /// 7990b57cec5SDimitry Andric virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 8000b57cec5SDimitry Andric llvm::Function *OutlinedFn, 8010b57cec5SDimitry Andric ArrayRef<llvm::Value *> CapturedVars, 8020eae32dcSDimitry Andric const Expr *IfCond, llvm::Value *NumThreads); 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric /// Emits a critical region. 8050b57cec5SDimitry Andric /// \param CriticalName Name of the critical region. 8060b57cec5SDimitry Andric /// \param CriticalOpGen Generator for the statement associated with the given 8070b57cec5SDimitry Andric /// critical region. 8080b57cec5SDimitry Andric /// \param Hint Value of the 'hint' clause (optional). 8090b57cec5SDimitry Andric virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, 8100b57cec5SDimitry Andric const RegionCodeGenTy &CriticalOpGen, 8110b57cec5SDimitry Andric SourceLocation Loc, 8120b57cec5SDimitry Andric const Expr *Hint = nullptr); 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric /// Emits a master region. 8150b57cec5SDimitry Andric /// \param MasterOpGen Generator for the statement associated with the given 8160b57cec5SDimitry Andric /// master region. 8170b57cec5SDimitry Andric virtual void emitMasterRegion(CodeGenFunction &CGF, 8180b57cec5SDimitry Andric const RegionCodeGenTy &MasterOpGen, 8190b57cec5SDimitry Andric SourceLocation Loc); 8200b57cec5SDimitry Andric 821fe6060f1SDimitry Andric /// Emits a masked region. 822fe6060f1SDimitry Andric /// \param MaskedOpGen Generator for the statement associated with the given 823fe6060f1SDimitry Andric /// masked region. 824fe6060f1SDimitry Andric virtual void emitMaskedRegion(CodeGenFunction &CGF, 825fe6060f1SDimitry Andric const RegionCodeGenTy &MaskedOpGen, 826fe6060f1SDimitry Andric SourceLocation Loc, 827fe6060f1SDimitry Andric const Expr *Filter = nullptr); 828fe6060f1SDimitry Andric 8290b57cec5SDimitry Andric /// Emits code for a taskyield directive. 8300b57cec5SDimitry Andric virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc); 8310b57cec5SDimitry Andric 832bdd1243dSDimitry Andric /// Emit __kmpc_error call for error directive 833bdd1243dSDimitry Andric /// extern void __kmpc_error(ident_t *loc, int severity, const char *message); 834bdd1243dSDimitry Andric virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, 835bdd1243dSDimitry Andric bool IsFatal); 836bdd1243dSDimitry Andric 8370b57cec5SDimitry Andric /// Emit a taskgroup region. 8380b57cec5SDimitry Andric /// \param TaskgroupOpGen Generator for the statement associated with the 8390b57cec5SDimitry Andric /// given taskgroup region. 8400b57cec5SDimitry Andric virtual void emitTaskgroupRegion(CodeGenFunction &CGF, 8410b57cec5SDimitry Andric const RegionCodeGenTy &TaskgroupOpGen, 8420b57cec5SDimitry Andric SourceLocation Loc); 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric /// Emits a single region. 8450b57cec5SDimitry Andric /// \param SingleOpGen Generator for the statement associated with the given 8460b57cec5SDimitry Andric /// single region. 8470b57cec5SDimitry Andric virtual void emitSingleRegion(CodeGenFunction &CGF, 8480b57cec5SDimitry Andric const RegionCodeGenTy &SingleOpGen, 8490b57cec5SDimitry Andric SourceLocation Loc, 8500b57cec5SDimitry Andric ArrayRef<const Expr *> CopyprivateVars, 8510b57cec5SDimitry Andric ArrayRef<const Expr *> DestExprs, 8520b57cec5SDimitry Andric ArrayRef<const Expr *> SrcExprs, 8530b57cec5SDimitry Andric ArrayRef<const Expr *> AssignmentOps); 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric /// Emit an ordered region. 8560b57cec5SDimitry Andric /// \param OrderedOpGen Generator for the statement associated with the given 8570b57cec5SDimitry Andric /// ordered region. 8580b57cec5SDimitry Andric virtual void emitOrderedRegion(CodeGenFunction &CGF, 8590b57cec5SDimitry Andric const RegionCodeGenTy &OrderedOpGen, 8600b57cec5SDimitry Andric SourceLocation Loc, bool IsThreads); 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric /// Emit an implicit/explicit barrier for OpenMP threads. 8630b57cec5SDimitry Andric /// \param Kind Directive for which this implicit barrier call must be 8640b57cec5SDimitry Andric /// generated. Must be OMPD_barrier for explicit barrier generation. 8650b57cec5SDimitry Andric /// \param EmitChecks true if need to emit checks for cancellation barriers. 8660b57cec5SDimitry Andric /// \param ForceSimpleCall true simple barrier call must be emitted, false if 8670b57cec5SDimitry Andric /// runtime class decides which one to emit (simple or with cancellation 8680b57cec5SDimitry Andric /// checks). 8690b57cec5SDimitry Andric /// 8700b57cec5SDimitry Andric virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 8710b57cec5SDimitry Andric OpenMPDirectiveKind Kind, 8720b57cec5SDimitry Andric bool EmitChecks = true, 8730b57cec5SDimitry Andric bool ForceSimpleCall = false); 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric /// Check if the specified \a ScheduleKind is static non-chunked. 8760b57cec5SDimitry Andric /// This kind of worksharing directive is emitted without outer loop. 8770b57cec5SDimitry Andric /// \param ScheduleKind Schedule kind specified in the 'schedule' clause. 8780b57cec5SDimitry Andric /// \param Chunked True if chunk is specified in the clause. 8790b57cec5SDimitry Andric /// 8800b57cec5SDimitry Andric virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 8810b57cec5SDimitry Andric bool Chunked) const; 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric /// Check if the specified \a ScheduleKind is static non-chunked. 8840b57cec5SDimitry Andric /// This kind of distribute directive is emitted without outer loop. 8850b57cec5SDimitry Andric /// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause. 8860b57cec5SDimitry Andric /// \param Chunked True if chunk is specified in the clause. 8870b57cec5SDimitry Andric /// 8880b57cec5SDimitry Andric virtual bool isStaticNonchunked(OpenMPDistScheduleClauseKind ScheduleKind, 8890b57cec5SDimitry Andric bool Chunked) const; 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric /// Check if the specified \a ScheduleKind is static chunked. 8920b57cec5SDimitry Andric /// \param ScheduleKind Schedule kind specified in the 'schedule' clause. 8930b57cec5SDimitry Andric /// \param Chunked True if chunk is specified in the clause. 8940b57cec5SDimitry Andric /// 8950b57cec5SDimitry Andric virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 8960b57cec5SDimitry Andric bool Chunked) const; 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric /// Check if the specified \a ScheduleKind is static non-chunked. 8990b57cec5SDimitry Andric /// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause. 9000b57cec5SDimitry Andric /// \param Chunked True if chunk is specified in the clause. 9010b57cec5SDimitry Andric /// 9020b57cec5SDimitry Andric virtual bool isStaticChunked(OpenMPDistScheduleClauseKind ScheduleKind, 9030b57cec5SDimitry Andric bool Chunked) const; 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric /// Check if the specified \a ScheduleKind is dynamic. 9060b57cec5SDimitry Andric /// This kind of worksharing directive is emitted without outer loop. 9070b57cec5SDimitry Andric /// \param ScheduleKind Schedule Kind specified in the 'schedule' clause. 9080b57cec5SDimitry Andric /// 9090b57cec5SDimitry Andric virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const; 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric /// struct with the values to be passed to the dispatch runtime function 9120b57cec5SDimitry Andric struct DispatchRTInput { 9130b57cec5SDimitry Andric /// Loop lower bound 9140b57cec5SDimitry Andric llvm::Value *LB = nullptr; 9150b57cec5SDimitry Andric /// Loop upper bound 9160b57cec5SDimitry Andric llvm::Value *UB = nullptr; 9170b57cec5SDimitry Andric /// Chunk size specified using 'schedule' clause (nullptr if chunk 9180b57cec5SDimitry Andric /// was not specified) 9190b57cec5SDimitry Andric llvm::Value *Chunk = nullptr; 9200b57cec5SDimitry Andric DispatchRTInput() = default; DispatchRTInputDispatchRTInput9210b57cec5SDimitry Andric DispatchRTInput(llvm::Value *LB, llvm::Value *UB, llvm::Value *Chunk) 9220b57cec5SDimitry Andric : LB(LB), UB(UB), Chunk(Chunk) {} 9230b57cec5SDimitry Andric }; 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric /// Call the appropriate runtime routine to initialize it before start 9260b57cec5SDimitry Andric /// of loop. 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric /// This is used for non static scheduled types and when the ordered 9290b57cec5SDimitry Andric /// clause is present on the loop construct. 9300b57cec5SDimitry Andric /// Depending on the loop schedule, it is necessary to call some runtime 9310b57cec5SDimitry Andric /// routine before start of the OpenMP loop to get the loop upper / lower 9320b57cec5SDimitry Andric /// bounds \a LB and \a UB and stride \a ST. 9330b57cec5SDimitry Andric /// 9340b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 9350b57cec5SDimitry Andric /// \param Loc Clang source location. 9360b57cec5SDimitry Andric /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. 9370b57cec5SDimitry Andric /// \param IVSize Size of the iteration variable in bits. 9380b57cec5SDimitry Andric /// \param IVSigned Sign of the iteration variable. 9390b57cec5SDimitry Andric /// \param Ordered true if loop is ordered, false otherwise. 9400b57cec5SDimitry Andric /// \param DispatchValues struct containing llvm values for lower bound, upper 9410b57cec5SDimitry Andric /// bound, and chunk expression. 9420b57cec5SDimitry Andric /// For the default (nullptr) value, the chunk 1 will be used. 9430b57cec5SDimitry Andric /// 9440b57cec5SDimitry Andric virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, 9450b57cec5SDimitry Andric const OpenMPScheduleTy &ScheduleKind, 9460b57cec5SDimitry Andric unsigned IVSize, bool IVSigned, bool Ordered, 9470b57cec5SDimitry Andric const DispatchRTInput &DispatchValues); 9480b57cec5SDimitry Andric 949*0fca6ea1SDimitry Andric /// This is used for non static scheduled types and when the ordered 950*0fca6ea1SDimitry Andric /// clause is present on the loop construct. 951*0fca6ea1SDimitry Andric /// 952*0fca6ea1SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 953*0fca6ea1SDimitry Andric /// \param Loc Clang source location. 954*0fca6ea1SDimitry Andric /// 955*0fca6ea1SDimitry Andric virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc); 956*0fca6ea1SDimitry Andric 9570b57cec5SDimitry Andric /// Struct with the values to be passed to the static runtime function 9580b57cec5SDimitry Andric struct StaticRTInput { 9590b57cec5SDimitry Andric /// Size of the iteration variable in bits. 9600b57cec5SDimitry Andric unsigned IVSize = 0; 9610b57cec5SDimitry Andric /// Sign of the iteration variable. 9620b57cec5SDimitry Andric bool IVSigned = false; 9630b57cec5SDimitry Andric /// true if loop is ordered, false otherwise. 9640b57cec5SDimitry Andric bool Ordered = false; 9650b57cec5SDimitry Andric /// Address of the output variable in which the flag of the last iteration 9660b57cec5SDimitry Andric /// is returned. 9670b57cec5SDimitry Andric Address IL = Address::invalid(); 9680b57cec5SDimitry Andric /// Address of the output variable in which the lower iteration number is 9690b57cec5SDimitry Andric /// returned. 9700b57cec5SDimitry Andric Address LB = Address::invalid(); 9710b57cec5SDimitry Andric /// Address of the output variable in which the upper iteration number is 9720b57cec5SDimitry Andric /// returned. 9730b57cec5SDimitry Andric Address UB = Address::invalid(); 9740b57cec5SDimitry Andric /// Address of the output variable in which the stride value is returned 9750b57cec5SDimitry Andric /// necessary to generated the static_chunked scheduled loop. 9760b57cec5SDimitry Andric Address ST = Address::invalid(); 9770b57cec5SDimitry Andric /// Value of the chunk for the static_chunked scheduled loop. For the 9780b57cec5SDimitry Andric /// default (nullptr) value, the chunk 1 will be used. 9790b57cec5SDimitry Andric llvm::Value *Chunk = nullptr; 9800b57cec5SDimitry Andric StaticRTInput(unsigned IVSize, bool IVSigned, bool Ordered, Address IL, 9810b57cec5SDimitry Andric Address LB, Address UB, Address ST, 9820b57cec5SDimitry Andric llvm::Value *Chunk = nullptr) IVSizeStaticRTInput9830b57cec5SDimitry Andric : IVSize(IVSize), IVSigned(IVSigned), Ordered(Ordered), IL(IL), LB(LB), 9840b57cec5SDimitry Andric UB(UB), ST(ST), Chunk(Chunk) {} 9850b57cec5SDimitry Andric }; 9860b57cec5SDimitry Andric /// Call the appropriate runtime routine to initialize it before start 9870b57cec5SDimitry Andric /// of loop. 9880b57cec5SDimitry Andric /// 9890b57cec5SDimitry Andric /// This is used only in case of static schedule, when the user did not 9900b57cec5SDimitry Andric /// specify a ordered clause on the loop construct. 9910b57cec5SDimitry Andric /// Depending on the loop schedule, it is necessary to call some runtime 9920b57cec5SDimitry Andric /// routine before start of the OpenMP loop to get the loop upper / lower 9930b57cec5SDimitry Andric /// bounds LB and UB and stride ST. 9940b57cec5SDimitry Andric /// 9950b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 9960b57cec5SDimitry Andric /// \param Loc Clang source location. 9970b57cec5SDimitry Andric /// \param DKind Kind of the directive. 9980b57cec5SDimitry Andric /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. 9990b57cec5SDimitry Andric /// \param Values Input arguments for the construct. 10000b57cec5SDimitry Andric /// 10010b57cec5SDimitry Andric virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, 10020b57cec5SDimitry Andric OpenMPDirectiveKind DKind, 10030b57cec5SDimitry Andric const OpenMPScheduleTy &ScheduleKind, 10040b57cec5SDimitry Andric const StaticRTInput &Values); 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric /// 10070b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 10080b57cec5SDimitry Andric /// \param Loc Clang source location. 10090b57cec5SDimitry Andric /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause. 10100b57cec5SDimitry Andric /// \param Values Input arguments for the construct. 10110b57cec5SDimitry Andric /// 10120b57cec5SDimitry Andric virtual void emitDistributeStaticInit(CodeGenFunction &CGF, 10130b57cec5SDimitry Andric SourceLocation Loc, 10140b57cec5SDimitry Andric OpenMPDistScheduleClauseKind SchedKind, 10150b57cec5SDimitry Andric const StaticRTInput &Values); 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric /// Call the appropriate runtime routine to notify that we finished 10180b57cec5SDimitry Andric /// iteration of the ordered loop with the dynamic scheduling. 10190b57cec5SDimitry Andric /// 10200b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 10210b57cec5SDimitry Andric /// \param Loc Clang source location. 10220b57cec5SDimitry Andric /// \param IVSize Size of the iteration variable in bits. 10230b57cec5SDimitry Andric /// \param IVSigned Sign of the iteration variable. 10240b57cec5SDimitry Andric /// 10250b57cec5SDimitry Andric virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, 10260b57cec5SDimitry Andric SourceLocation Loc, unsigned IVSize, 10270b57cec5SDimitry Andric bool IVSigned); 10280b57cec5SDimitry Andric 10290b57cec5SDimitry Andric /// Call the appropriate runtime routine to notify that we finished 10300b57cec5SDimitry Andric /// all the work with current loop. 10310b57cec5SDimitry Andric /// 10320b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 10330b57cec5SDimitry Andric /// \param Loc Clang source location. 10340b57cec5SDimitry Andric /// \param DKind Kind of the directive for which the static finish is emitted. 10350b57cec5SDimitry Andric /// 10360b57cec5SDimitry Andric virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, 10370b57cec5SDimitry Andric OpenMPDirectiveKind DKind); 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric /// Call __kmpc_dispatch_next( 10400b57cec5SDimitry Andric /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 10410b57cec5SDimitry Andric /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 10420b57cec5SDimitry Andric /// kmp_int[32|64] *p_stride); 10430b57cec5SDimitry Andric /// \param IVSize Size of the iteration variable in bits. 10440b57cec5SDimitry Andric /// \param IVSigned Sign of the iteration variable. 10450b57cec5SDimitry Andric /// \param IL Address of the output variable in which the flag of the 10460b57cec5SDimitry Andric /// last iteration is returned. 10470b57cec5SDimitry Andric /// \param LB Address of the output variable in which the lower iteration 10480b57cec5SDimitry Andric /// number is returned. 10490b57cec5SDimitry Andric /// \param UB Address of the output variable in which the upper iteration 10500b57cec5SDimitry Andric /// number is returned. 10510b57cec5SDimitry Andric /// \param ST Address of the output variable in which the stride value is 10520b57cec5SDimitry Andric /// returned. 10530b57cec5SDimitry Andric virtual llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc, 10540b57cec5SDimitry Andric unsigned IVSize, bool IVSigned, 10550b57cec5SDimitry Andric Address IL, Address LB, 10560b57cec5SDimitry Andric Address UB, Address ST); 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 10590b57cec5SDimitry Andric /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' 10600b57cec5SDimitry Andric /// clause. 10610b57cec5SDimitry Andric /// \param NumThreads An integer value of threads. 10620b57cec5SDimitry Andric virtual void emitNumThreadsClause(CodeGenFunction &CGF, 10630b57cec5SDimitry Andric llvm::Value *NumThreads, 10640b57cec5SDimitry Andric SourceLocation Loc); 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 10670b57cec5SDimitry Andric /// global_tid, int proc_bind) to generate code for 'proc_bind' clause. 10680b57cec5SDimitry Andric virtual void emitProcBindClause(CodeGenFunction &CGF, 1069480093f4SDimitry Andric llvm::omp::ProcBindKind ProcBind, 10700b57cec5SDimitry Andric SourceLocation Loc); 10710b57cec5SDimitry Andric 10720b57cec5SDimitry Andric /// Returns address of the threadprivate variable for the current 10730b57cec5SDimitry Andric /// thread. 10740b57cec5SDimitry Andric /// \param VD Threadprivate variable. 10750b57cec5SDimitry Andric /// \param VDAddr Address of the global variable \a VD. 10760b57cec5SDimitry Andric /// \param Loc Location of the reference to threadprivate var. 10770b57cec5SDimitry Andric /// \return Address of the threadprivate variable for the current thread. 10780b57cec5SDimitry Andric virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, 1079*0fca6ea1SDimitry Andric const VarDecl *VD, Address VDAddr, 10800b57cec5SDimitry Andric SourceLocation Loc); 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric /// Returns the address of the variable marked as declare target with link 10830b57cec5SDimitry Andric /// clause OR as declare target with to clause and unified memory. 1084*0fca6ea1SDimitry Andric virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD); 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric /// Emit a code for initialization of threadprivate variable. It emits 10870b57cec5SDimitry Andric /// a call to runtime library which adds initial value to the newly created 10880b57cec5SDimitry Andric /// threadprivate variable (if it is not constant) and registers destructor 10890b57cec5SDimitry Andric /// for the variable (if any). 10900b57cec5SDimitry Andric /// \param VD Threadprivate variable. 10910b57cec5SDimitry Andric /// \param VDAddr Address of the global variable \a VD. 10920b57cec5SDimitry Andric /// \param Loc Location of threadprivate declaration. 10930b57cec5SDimitry Andric /// \param PerformInit true if initialization expression is not constant. 10940b57cec5SDimitry Andric virtual llvm::Function * 10950b57cec5SDimitry Andric emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, 10960b57cec5SDimitry Andric SourceLocation Loc, bool PerformInit, 10970b57cec5SDimitry Andric CodeGenFunction *CGF = nullptr); 10980b57cec5SDimitry Andric 10995f757f3fSDimitry Andric /// Emit code for handling declare target functions in the runtime. 11005f757f3fSDimitry Andric /// \param FD Declare target function. 11015f757f3fSDimitry Andric /// \param Addr Address of the global \a FD. 11020b57cec5SDimitry Andric /// \param PerformInit true if initialization expression is not constant. 11035f757f3fSDimitry Andric virtual void emitDeclareTargetFunction(const FunctionDecl *FD, 11045f757f3fSDimitry Andric llvm::GlobalValue *GV); 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric /// Creates artificial threadprivate variable with name \p Name and type \p 11070b57cec5SDimitry Andric /// VarType. 11080b57cec5SDimitry Andric /// \param VarType Type of the artificial threadprivate variable. 11090b57cec5SDimitry Andric /// \param Name Name of the artificial threadprivate variable. 11100b57cec5SDimitry Andric virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 11110b57cec5SDimitry Andric QualType VarType, 11120b57cec5SDimitry Andric StringRef Name); 11130b57cec5SDimitry Andric 11140b57cec5SDimitry Andric /// Emit flush of the variables specified in 'omp flush' directive. 11150b57cec5SDimitry Andric /// \param Vars List of variables to flush. 11160b57cec5SDimitry Andric virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars, 11175ffd83dbSDimitry Andric SourceLocation Loc, llvm::AtomicOrdering AO); 11180b57cec5SDimitry Andric 11190b57cec5SDimitry Andric /// Emit task region for the task directive. The task region is 11200b57cec5SDimitry Andric /// emitted in several steps: 11210b57cec5SDimitry Andric /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 11220b57cec5SDimitry Andric /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 11230b57cec5SDimitry Andric /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the 11240b57cec5SDimitry Andric /// function: 11250b57cec5SDimitry Andric /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 11260b57cec5SDimitry Andric /// TaskFunction(gtid, tt->part_id, tt->shareds); 11270b57cec5SDimitry Andric /// return 0; 11280b57cec5SDimitry Andric /// } 11290b57cec5SDimitry Andric /// 2. Copy a list of shared variables to field shareds of the resulting 11300b57cec5SDimitry Andric /// structure kmp_task_t returned by the previous call (if any). 11310b57cec5SDimitry Andric /// 3. Copy a pointer to destructions function to field destructions of the 11320b57cec5SDimitry Andric /// resulting structure kmp_task_t. 11330b57cec5SDimitry Andric /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, 11340b57cec5SDimitry Andric /// kmp_task_t *new_task), where new_task is a resulting structure from 11350b57cec5SDimitry Andric /// previous items. 11360b57cec5SDimitry Andric /// \param D Current task directive. 11370b57cec5SDimitry Andric /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 11380b57cec5SDimitry Andric /// /*part_id*/, captured_struct */*__context*/); 11390b57cec5SDimitry Andric /// \param SharedsTy A type which contains references the shared variables. 11400b57cec5SDimitry Andric /// \param Shareds Context with the list of shared variables from the \p 11410b57cec5SDimitry Andric /// TaskFunction. 11420b57cec5SDimitry Andric /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr 11430b57cec5SDimitry Andric /// otherwise. 11440b57cec5SDimitry Andric /// \param Data Additional data for task generation like tiednsee, final 11450b57cec5SDimitry Andric /// state, list of privates etc. 11460b57cec5SDimitry Andric virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11470b57cec5SDimitry Andric const OMPExecutableDirective &D, 11480b57cec5SDimitry Andric llvm::Function *TaskFunction, QualType SharedsTy, 11490b57cec5SDimitry Andric Address Shareds, const Expr *IfCond, 11500b57cec5SDimitry Andric const OMPTaskDataTy &Data); 11510b57cec5SDimitry Andric 11520b57cec5SDimitry Andric /// Emit task region for the taskloop directive. The taskloop region is 11530b57cec5SDimitry Andric /// emitted in several steps: 11540b57cec5SDimitry Andric /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 11550b57cec5SDimitry Andric /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 11560b57cec5SDimitry Andric /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the 11570b57cec5SDimitry Andric /// function: 11580b57cec5SDimitry Andric /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 11590b57cec5SDimitry Andric /// TaskFunction(gtid, tt->part_id, tt->shareds); 11600b57cec5SDimitry Andric /// return 0; 11610b57cec5SDimitry Andric /// } 11620b57cec5SDimitry Andric /// 2. Copy a list of shared variables to field shareds of the resulting 11630b57cec5SDimitry Andric /// structure kmp_task_t returned by the previous call (if any). 11640b57cec5SDimitry Andric /// 3. Copy a pointer to destructions function to field destructions of the 11650b57cec5SDimitry Andric /// resulting structure kmp_task_t. 11660b57cec5SDimitry Andric /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t 11670b57cec5SDimitry Andric /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int 11680b57cec5SDimitry Andric /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task 11690b57cec5SDimitry Andric /// is a resulting structure from 11700b57cec5SDimitry Andric /// previous items. 11710b57cec5SDimitry Andric /// \param D Current task directive. 11720b57cec5SDimitry Andric /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 11730b57cec5SDimitry Andric /// /*part_id*/, captured_struct */*__context*/); 11740b57cec5SDimitry Andric /// \param SharedsTy A type which contains references the shared variables. 11750b57cec5SDimitry Andric /// \param Shareds Context with the list of shared variables from the \p 11760b57cec5SDimitry Andric /// TaskFunction. 11770b57cec5SDimitry Andric /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr 11780b57cec5SDimitry Andric /// otherwise. 11790b57cec5SDimitry Andric /// \param Data Additional data for task generation like tiednsee, final 11800b57cec5SDimitry Andric /// state, list of privates etc. 11810b57cec5SDimitry Andric virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 11820b57cec5SDimitry Andric const OMPLoopDirective &D, 11830b57cec5SDimitry Andric llvm::Function *TaskFunction, 11840b57cec5SDimitry Andric QualType SharedsTy, Address Shareds, 11850b57cec5SDimitry Andric const Expr *IfCond, const OMPTaskDataTy &Data); 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric /// Emit code for the directive that does not require outlining. 11880b57cec5SDimitry Andric /// 11890b57cec5SDimitry Andric /// \param InnermostKind Kind of innermost directive (for simple directives it 11900b57cec5SDimitry Andric /// is a directive itself, for combined - its innermost directive). 11910b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 11920b57cec5SDimitry Andric /// \param HasCancel true if region has inner cancel directive, false 11930b57cec5SDimitry Andric /// otherwise. 11940b57cec5SDimitry Andric virtual void emitInlinedDirective(CodeGenFunction &CGF, 11950b57cec5SDimitry Andric OpenMPDirectiveKind InnermostKind, 11960b57cec5SDimitry Andric const RegionCodeGenTy &CodeGen, 11970b57cec5SDimitry Andric bool HasCancel = false); 11980b57cec5SDimitry Andric 11990b57cec5SDimitry Andric /// Emits reduction function. 120006c3fb27SDimitry Andric /// \param ReducerName Name of the function calling the reduction. 120181ad6265SDimitry Andric /// \param ArgsElemType Array type containing pointers to reduction variables. 12020b57cec5SDimitry Andric /// \param Privates List of private copies for original reduction arguments. 12030b57cec5SDimitry Andric /// \param LHSExprs List of LHS in \a ReductionOps reduction operations. 12040b57cec5SDimitry Andric /// \param RHSExprs List of RHS in \a ReductionOps reduction operations. 12050b57cec5SDimitry Andric /// \param ReductionOps List of reduction operations in form 'LHS binop RHS' 12060b57cec5SDimitry Andric /// or 'operator binop(LHS, RHS)'. 120706c3fb27SDimitry Andric llvm::Function *emitReductionFunction( 120806c3fb27SDimitry Andric StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, 120906c3fb27SDimitry Andric ArrayRef<const Expr *> Privates, ArrayRef<const Expr *> LHSExprs, 121006c3fb27SDimitry Andric ArrayRef<const Expr *> RHSExprs, ArrayRef<const Expr *> ReductionOps); 12110b57cec5SDimitry Andric 12120b57cec5SDimitry Andric /// Emits single reduction combiner 12130b57cec5SDimitry Andric void emitSingleReductionCombiner(CodeGenFunction &CGF, 12140b57cec5SDimitry Andric const Expr *ReductionOp, 12150b57cec5SDimitry Andric const Expr *PrivateRef, 12160b57cec5SDimitry Andric const DeclRefExpr *LHS, 12170b57cec5SDimitry Andric const DeclRefExpr *RHS); 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric struct ReductionOptionsTy { 12200b57cec5SDimitry Andric bool WithNowait; 12210b57cec5SDimitry Andric bool SimpleReduction; 12220b57cec5SDimitry Andric OpenMPDirectiveKind ReductionKind; 12230b57cec5SDimitry Andric }; 12240b57cec5SDimitry Andric /// Emit a code for reduction clause. Next code should be emitted for 12250b57cec5SDimitry Andric /// reduction: 12260b57cec5SDimitry Andric /// \code 12270b57cec5SDimitry Andric /// 12280b57cec5SDimitry Andric /// static kmp_critical_name lock = { 0 }; 12290b57cec5SDimitry Andric /// 12300b57cec5SDimitry Andric /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 12310b57cec5SDimitry Andric /// ... 12320b57cec5SDimitry Andric /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 12330b57cec5SDimitry Andric /// ... 12340b57cec5SDimitry Andric /// } 12350b57cec5SDimitry Andric /// 12360b57cec5SDimitry Andric /// ... 12370b57cec5SDimitry Andric /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 12380b57cec5SDimitry Andric /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 12390b57cec5SDimitry Andric /// RedList, reduce_func, &<lock>)) { 12400b57cec5SDimitry Andric /// case 1: 12410b57cec5SDimitry Andric /// ... 12420b57cec5SDimitry Andric /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 12430b57cec5SDimitry Andric /// ... 12440b57cec5SDimitry Andric /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 12450b57cec5SDimitry Andric /// break; 12460b57cec5SDimitry Andric /// case 2: 12470b57cec5SDimitry Andric /// ... 12480b57cec5SDimitry Andric /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 12490b57cec5SDimitry Andric /// ... 12500b57cec5SDimitry Andric /// break; 12510b57cec5SDimitry Andric /// default:; 12520b57cec5SDimitry Andric /// } 12530b57cec5SDimitry Andric /// \endcode 12540b57cec5SDimitry Andric /// 12550b57cec5SDimitry Andric /// \param Privates List of private copies for original reduction arguments. 12560b57cec5SDimitry Andric /// \param LHSExprs List of LHS in \a ReductionOps reduction operations. 12570b57cec5SDimitry Andric /// \param RHSExprs List of RHS in \a ReductionOps reduction operations. 12580b57cec5SDimitry Andric /// \param ReductionOps List of reduction operations in form 'LHS binop RHS' 12590b57cec5SDimitry Andric /// or 'operator binop(LHS, RHS)'. 12600b57cec5SDimitry Andric /// \param Options List of options for reduction codegen: 12610b57cec5SDimitry Andric /// WithNowait true if parent directive has also nowait clause, false 12620b57cec5SDimitry Andric /// otherwise. 12630b57cec5SDimitry Andric /// SimpleReduction Emit reduction operation only. Used for omp simd 12640b57cec5SDimitry Andric /// directive on the host. 12650b57cec5SDimitry Andric /// ReductionKind The kind of reduction to perform. 12660b57cec5SDimitry Andric virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 12670b57cec5SDimitry Andric ArrayRef<const Expr *> Privates, 12680b57cec5SDimitry Andric ArrayRef<const Expr *> LHSExprs, 12690b57cec5SDimitry Andric ArrayRef<const Expr *> RHSExprs, 12700b57cec5SDimitry Andric ArrayRef<const Expr *> ReductionOps, 12710b57cec5SDimitry Andric ReductionOptionsTy Options); 12720b57cec5SDimitry Andric 12730b57cec5SDimitry Andric /// Emit a code for initialization of task reduction clause. Next code 12740b57cec5SDimitry Andric /// should be emitted for reduction: 12750b57cec5SDimitry Andric /// \code 12760b57cec5SDimitry Andric /// 12775ffd83dbSDimitry Andric /// _taskred_item_t red_data[n]; 12780b57cec5SDimitry Andric /// ... 12795ffd83dbSDimitry Andric /// red_data[i].shar = &shareds[i]; 12805ffd83dbSDimitry Andric /// red_data[i].orig = &origs[i]; 12810b57cec5SDimitry Andric /// red_data[i].size = sizeof(origs[i]); 12820b57cec5SDimitry Andric /// red_data[i].f_init = (void*)RedInit<i>; 12830b57cec5SDimitry Andric /// red_data[i].f_fini = (void*)RedDest<i>; 12840b57cec5SDimitry Andric /// red_data[i].f_comb = (void*)RedOp<i>; 12850b57cec5SDimitry Andric /// red_data[i].flags = <Flag_i>; 12860b57cec5SDimitry Andric /// ... 12875ffd83dbSDimitry Andric /// void* tg1 = __kmpc_taskred_init(gtid, n, red_data); 12880b57cec5SDimitry Andric /// \endcode 12895ffd83dbSDimitry Andric /// For reduction clause with task modifier it emits the next call: 12905ffd83dbSDimitry Andric /// \code 12910b57cec5SDimitry Andric /// 12925ffd83dbSDimitry Andric /// _taskred_item_t red_data[n]; 12935ffd83dbSDimitry Andric /// ... 12945ffd83dbSDimitry Andric /// red_data[i].shar = &shareds[i]; 12955ffd83dbSDimitry Andric /// red_data[i].orig = &origs[i]; 12965ffd83dbSDimitry Andric /// red_data[i].size = sizeof(origs[i]); 12975ffd83dbSDimitry Andric /// red_data[i].f_init = (void*)RedInit<i>; 12985ffd83dbSDimitry Andric /// red_data[i].f_fini = (void*)RedDest<i>; 12995ffd83dbSDimitry Andric /// red_data[i].f_comb = (void*)RedOp<i>; 13005ffd83dbSDimitry Andric /// red_data[i].flags = <Flag_i>; 13015ffd83dbSDimitry Andric /// ... 13025ffd83dbSDimitry Andric /// void* tg1 = __kmpc_taskred_modifier_init(loc, gtid, is_worksharing, n, 13035ffd83dbSDimitry Andric /// red_data); 13045ffd83dbSDimitry Andric /// \endcode 13050b57cec5SDimitry Andric /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations. 13060b57cec5SDimitry Andric /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations. 13070b57cec5SDimitry Andric /// \param Data Additional data for task generation like tiedness, final 13080b57cec5SDimitry Andric /// state, list of privates, reductions etc. 13090b57cec5SDimitry Andric virtual llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, 13100b57cec5SDimitry Andric SourceLocation Loc, 13110b57cec5SDimitry Andric ArrayRef<const Expr *> LHSExprs, 13120b57cec5SDimitry Andric ArrayRef<const Expr *> RHSExprs, 13130b57cec5SDimitry Andric const OMPTaskDataTy &Data); 13140b57cec5SDimitry Andric 13155ffd83dbSDimitry Andric /// Emits the following code for reduction clause with task modifier: 13165ffd83dbSDimitry Andric /// \code 13175ffd83dbSDimitry Andric /// __kmpc_task_reduction_modifier_fini(loc, gtid, is_worksharing); 13185ffd83dbSDimitry Andric /// \endcode 13195ffd83dbSDimitry Andric virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, 13205ffd83dbSDimitry Andric bool IsWorksharingReduction); 13215ffd83dbSDimitry Andric 13220b57cec5SDimitry Andric /// Required to resolve existing problems in the runtime. Emits threadprivate 13230b57cec5SDimitry Andric /// variables to store the size of the VLAs/array sections for 13245ffd83dbSDimitry Andric /// initializer/combiner/finalizer functions. 13250b57cec5SDimitry Andric /// \param RCG Allows to reuse an existing data for the reductions. 13260b57cec5SDimitry Andric /// \param N Reduction item for which fixups must be emitted. 13270b57cec5SDimitry Andric virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, 13280b57cec5SDimitry Andric ReductionCodeGen &RCG, unsigned N); 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andric /// Get the address of `void *` type of the privatue copy of the reduction 13310b57cec5SDimitry Andric /// item specified by the \p SharedLVal. 13320b57cec5SDimitry Andric /// \param ReductionsPtr Pointer to the reduction data returned by the 13330b57cec5SDimitry Andric /// emitTaskReductionInit function. 13340b57cec5SDimitry Andric /// \param SharedLVal Address of the original reduction item. 13350b57cec5SDimitry Andric virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, 13360b57cec5SDimitry Andric llvm::Value *ReductionsPtr, 13370b57cec5SDimitry Andric LValue SharedLVal); 13380b57cec5SDimitry Andric 13390b57cec5SDimitry Andric /// Emit code for 'taskwait' directive. 1340349cc55cSDimitry Andric virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, 1341349cc55cSDimitry Andric const OMPTaskDataTy &Data); 13420b57cec5SDimitry Andric 13430b57cec5SDimitry Andric /// Emit code for 'cancellation point' construct. 13440b57cec5SDimitry Andric /// \param CancelRegion Region kind for which the cancellation point must be 13450b57cec5SDimitry Andric /// emitted. 13460b57cec5SDimitry Andric /// 13470b57cec5SDimitry Andric virtual void emitCancellationPointCall(CodeGenFunction &CGF, 13480b57cec5SDimitry Andric SourceLocation Loc, 13490b57cec5SDimitry Andric OpenMPDirectiveKind CancelRegion); 13500b57cec5SDimitry Andric 13510b57cec5SDimitry Andric /// Emit code for 'cancel' construct. 13520b57cec5SDimitry Andric /// \param IfCond Condition in the associated 'if' clause, if it was 13530b57cec5SDimitry Andric /// specified, nullptr otherwise. 13540b57cec5SDimitry Andric /// \param CancelRegion Region kind for which the cancel must be emitted. 13550b57cec5SDimitry Andric /// 13560b57cec5SDimitry Andric virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 13570b57cec5SDimitry Andric const Expr *IfCond, 13580b57cec5SDimitry Andric OpenMPDirectiveKind CancelRegion); 13590b57cec5SDimitry Andric 13600b57cec5SDimitry Andric /// Emit outilined function for 'target' directive. 13610b57cec5SDimitry Andric /// \param D Directive to emit. 13620b57cec5SDimitry Andric /// \param ParentName Name of the function that encloses the target region. 13630b57cec5SDimitry Andric /// \param OutlinedFn Outlined function value to be defined by this call. 13640b57cec5SDimitry Andric /// \param OutlinedFnID Outlined function ID value to be defined by this call. 13650b57cec5SDimitry Andric /// \param IsOffloadEntry True if the outlined function is an offload entry. 13660b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 13670b57cec5SDimitry Andric /// An outlined function may not be an entry if, e.g. the if clause always 13680b57cec5SDimitry Andric /// evaluates to false. 13690b57cec5SDimitry Andric virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, 13700b57cec5SDimitry Andric StringRef ParentName, 13710b57cec5SDimitry Andric llvm::Function *&OutlinedFn, 13720b57cec5SDimitry Andric llvm::Constant *&OutlinedFnID, 13730b57cec5SDimitry Andric bool IsOffloadEntry, 13740b57cec5SDimitry Andric const RegionCodeGenTy &CodeGen); 13750b57cec5SDimitry Andric 13760b57cec5SDimitry Andric /// Emit the target offloading code associated with \a D. The emitted 13770b57cec5SDimitry Andric /// code attempts offloading the execution to the device, an the event of 13780b57cec5SDimitry Andric /// a failure it executes the host version outlined in \a OutlinedFn. 13790b57cec5SDimitry Andric /// \param D Directive to emit. 13800b57cec5SDimitry Andric /// \param OutlinedFn Host version of the code to be offloaded. 13810b57cec5SDimitry Andric /// \param OutlinedFnID ID of host version of the code to be offloaded. 13820b57cec5SDimitry Andric /// \param IfCond Expression evaluated in if clause associated with the target 13830b57cec5SDimitry Andric /// directive, or null if no if clause is used. 13840b57cec5SDimitry Andric /// \param Device Expression evaluated in device clause associated with the 13855ffd83dbSDimitry Andric /// target directive, or null if no device clause is used and device modifier. 1386a7dea167SDimitry Andric /// \param SizeEmitter Callback to emit number of iterations for loop-based 1387a7dea167SDimitry Andric /// directives. 13885ffd83dbSDimitry Andric virtual void emitTargetCall( 13895ffd83dbSDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 13905ffd83dbSDimitry Andric llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 13915ffd83dbSDimitry Andric llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 1392a7dea167SDimitry Andric llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 1393a7dea167SDimitry Andric const OMPLoopDirective &D)> 1394a7dea167SDimitry Andric SizeEmitter); 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric /// Emit the target regions enclosed in \a GD function definition or 13970b57cec5SDimitry Andric /// the function itself in case it is a valid device function. Returns true if 13980b57cec5SDimitry Andric /// \a GD was dealt with successfully. 13990b57cec5SDimitry Andric /// \param GD Function to scan. 14000b57cec5SDimitry Andric virtual bool emitTargetFunctions(GlobalDecl GD); 14010b57cec5SDimitry Andric 14020b57cec5SDimitry Andric /// Emit the global variable if it is a valid device global variable. 14030b57cec5SDimitry Andric /// Returns true if \a GD was dealt with successfully. 14040b57cec5SDimitry Andric /// \param GD Variable declaration to emit. 14050b57cec5SDimitry Andric virtual bool emitTargetGlobalVariable(GlobalDecl GD); 14060b57cec5SDimitry Andric 14070b57cec5SDimitry Andric /// Checks if the provided global decl \a GD is a declare target variable and 14080b57cec5SDimitry Andric /// registers it when emitting code for the host. 14090b57cec5SDimitry Andric virtual void registerTargetGlobalVariable(const VarDecl *VD, 14100b57cec5SDimitry Andric llvm::Constant *Addr); 14110b57cec5SDimitry Andric 14120b57cec5SDimitry Andric /// Emit the global \a GD if it is meaningful for the target. Returns 14130b57cec5SDimitry Andric /// if it was emitted successfully. 14140b57cec5SDimitry Andric /// \param GD Global to scan. 14150b57cec5SDimitry Andric virtual bool emitTargetGlobal(GlobalDecl GD); 14160b57cec5SDimitry Andric 1417a7dea167SDimitry Andric /// Creates all the offload entries in the current compilation unit 1418a7dea167SDimitry Andric /// along with the associated metadata. 1419a7dea167SDimitry Andric void createOffloadEntriesAndInfoMetadata(); 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric /// Emits code for teams call of the \a OutlinedFn with 14220b57cec5SDimitry Andric /// variables captured in a record which address is stored in \a 14230b57cec5SDimitry Andric /// CapturedStruct. 14240b57cec5SDimitry Andric /// \param OutlinedFn Outlined function to be run by team masters. Type of 14250b57cec5SDimitry Andric /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). 14260b57cec5SDimitry Andric /// \param CapturedVars A pointer to the record with the references to 14270b57cec5SDimitry Andric /// variables used in \a OutlinedFn function. 14280b57cec5SDimitry Andric /// 14290b57cec5SDimitry Andric virtual void emitTeamsCall(CodeGenFunction &CGF, 14300b57cec5SDimitry Andric const OMPExecutableDirective &D, 14310b57cec5SDimitry Andric SourceLocation Loc, llvm::Function *OutlinedFn, 14320b57cec5SDimitry Andric ArrayRef<llvm::Value *> CapturedVars); 14330b57cec5SDimitry Andric 14340b57cec5SDimitry Andric /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 14350b57cec5SDimitry Andric /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code 14360b57cec5SDimitry Andric /// for num_teams clause. 14370b57cec5SDimitry Andric /// \param NumTeams An integer expression of teams. 14380b57cec5SDimitry Andric /// \param ThreadLimit An integer expression of threads. 14390b57cec5SDimitry Andric virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, 14400b57cec5SDimitry Andric const Expr *ThreadLimit, SourceLocation Loc); 14410b57cec5SDimitry Andric 14425f757f3fSDimitry Andric /// Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32 14435f757f3fSDimitry Andric /// global_tid, kmp_int32 thread_limit) to generate code for 14445f757f3fSDimitry Andric /// thread_limit clause on target directive 14455f757f3fSDimitry Andric /// \param ThreadLimit An integer expression of threads. 14465f757f3fSDimitry Andric virtual void emitThreadLimitClause(CodeGenFunction &CGF, 14475f757f3fSDimitry Andric const Expr *ThreadLimit, 14485f757f3fSDimitry Andric SourceLocation Loc); 14495f757f3fSDimitry Andric 14500b57cec5SDimitry Andric /// Struct that keeps all the relevant information that should be kept 14510b57cec5SDimitry Andric /// throughout a 'target data' region. 1452bdd1243dSDimitry Andric class TargetDataInfo : public llvm::OpenMPIRBuilder::TargetDataInfo { 14530b57cec5SDimitry Andric public: TargetDataInfo()1454bdd1243dSDimitry Andric explicit TargetDataInfo() : llvm::OpenMPIRBuilder::TargetDataInfo() {} TargetDataInfo(bool RequiresDevicePointerInfo,bool SeparateBeginEndCalls)1455bdd1243dSDimitry Andric explicit TargetDataInfo(bool RequiresDevicePointerInfo, 1456bdd1243dSDimitry Andric bool SeparateBeginEndCalls) 1457bdd1243dSDimitry Andric : llvm::OpenMPIRBuilder::TargetDataInfo(RequiresDevicePointerInfo, 1458bdd1243dSDimitry Andric SeparateBeginEndCalls) {} 145906c3fb27SDimitry Andric /// Map between the a declaration of a capture and the corresponding new 146006c3fb27SDimitry Andric /// llvm address where the runtime returns the device pointers. 146106c3fb27SDimitry Andric llvm::DenseMap<const ValueDecl *, llvm::Value *> CaptureDeviceAddrMap; 14620b57cec5SDimitry Andric }; 14630b57cec5SDimitry Andric 14640b57cec5SDimitry Andric /// Emit the target data mapping code associated with \a D. 14650b57cec5SDimitry Andric /// \param D Directive to emit. 14660b57cec5SDimitry Andric /// \param IfCond Expression evaluated in if clause associated with the 14670b57cec5SDimitry Andric /// target directive, or null if no device clause is used. 14680b57cec5SDimitry Andric /// \param Device Expression evaluated in device clause associated with the 14690b57cec5SDimitry Andric /// target directive, or null if no device clause is used. 14700b57cec5SDimitry Andric /// \param Info A record used to store information that needs to be preserved 14710b57cec5SDimitry Andric /// until the region is closed. 14720b57cec5SDimitry Andric virtual void emitTargetDataCalls(CodeGenFunction &CGF, 14730b57cec5SDimitry Andric const OMPExecutableDirective &D, 14740b57cec5SDimitry Andric const Expr *IfCond, const Expr *Device, 14750b57cec5SDimitry Andric const RegionCodeGenTy &CodeGen, 1476bdd1243dSDimitry Andric CGOpenMPRuntime::TargetDataInfo &Info); 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric /// Emit the data mapping/movement code associated with the directive 14790b57cec5SDimitry Andric /// \a D that should be of the form 'target [{enter|exit} data | update]'. 14800b57cec5SDimitry Andric /// \param D Directive to emit. 14810b57cec5SDimitry Andric /// \param IfCond Expression evaluated in if clause associated with the target 14820b57cec5SDimitry Andric /// directive, or null if no if clause is used. 14830b57cec5SDimitry Andric /// \param Device Expression evaluated in device clause associated with the 14840b57cec5SDimitry Andric /// target directive, or null if no device clause is used. 14850b57cec5SDimitry Andric virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, 14860b57cec5SDimitry Andric const OMPExecutableDirective &D, 14870b57cec5SDimitry Andric const Expr *IfCond, 14880b57cec5SDimitry Andric const Expr *Device); 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric /// Marks function \a Fn with properly mangled versions of vector functions. 14910b57cec5SDimitry Andric /// \param FD Function marked as 'declare simd'. 14920b57cec5SDimitry Andric /// \param Fn LLVM function that must be marked with 'declare simd' 14930b57cec5SDimitry Andric /// attributes. 14940b57cec5SDimitry Andric virtual void emitDeclareSimdFunction(const FunctionDecl *FD, 14950b57cec5SDimitry Andric llvm::Function *Fn); 14960b57cec5SDimitry Andric 14970b57cec5SDimitry Andric /// Emit initialization for doacross loop nesting support. 14980b57cec5SDimitry Andric /// \param D Loop-based construct used in doacross nesting construct. 14990b57cec5SDimitry Andric virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, 15000b57cec5SDimitry Andric ArrayRef<Expr *> NumIterations); 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric /// Emit code for doacross ordered directive with 'depend' clause. 15030b57cec5SDimitry Andric /// \param C 'depend' clause with 'sink|source' dependency kind. 15040b57cec5SDimitry Andric virtual void emitDoacrossOrdered(CodeGenFunction &CGF, 15050b57cec5SDimitry Andric const OMPDependClause *C); 15060b57cec5SDimitry Andric 150706c3fb27SDimitry Andric /// Emit code for doacross ordered directive with 'doacross' clause. 150806c3fb27SDimitry Andric /// \param C 'doacross' clause with 'sink|source' dependence type. 150906c3fb27SDimitry Andric virtual void emitDoacrossOrdered(CodeGenFunction &CGF, 151006c3fb27SDimitry Andric const OMPDoacrossClause *C); 151106c3fb27SDimitry Andric 15120b57cec5SDimitry Andric /// Translates the native parameter of outlined function if this is required 15130b57cec5SDimitry Andric /// for target. 15140b57cec5SDimitry Andric /// \param FD Field decl from captured record for the parameter. 15150b57cec5SDimitry Andric /// \param NativeParam Parameter itself. translateParameter(const FieldDecl * FD,const VarDecl * NativeParam)15160b57cec5SDimitry Andric virtual const VarDecl *translateParameter(const FieldDecl *FD, 15170b57cec5SDimitry Andric const VarDecl *NativeParam) const { 15180b57cec5SDimitry Andric return NativeParam; 15190b57cec5SDimitry Andric } 15200b57cec5SDimitry Andric 15210b57cec5SDimitry Andric /// Gets the address of the native argument basing on the address of the 15220b57cec5SDimitry Andric /// target-specific parameter. 15230b57cec5SDimitry Andric /// \param NativeParam Parameter itself. 15240b57cec5SDimitry Andric /// \param TargetParam Corresponding target-specific parameter. 15250b57cec5SDimitry Andric virtual Address getParameterAddress(CodeGenFunction &CGF, 15260b57cec5SDimitry Andric const VarDecl *NativeParam, 15270b57cec5SDimitry Andric const VarDecl *TargetParam) const; 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric /// Choose default schedule type and chunk value for the 15300b57cec5SDimitry Andric /// dist_schedule clause. getDefaultDistScheduleAndChunk(CodeGenFunction & CGF,const OMPLoopDirective & S,OpenMPDistScheduleClauseKind & ScheduleKind,llvm::Value * & Chunk)15310b57cec5SDimitry Andric virtual void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF, 15320b57cec5SDimitry Andric const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind, 15330b57cec5SDimitry Andric llvm::Value *&Chunk) const {} 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric /// Choose default schedule type and chunk value for the 15360b57cec5SDimitry Andric /// schedule clause. 15370b57cec5SDimitry Andric virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, 15380b57cec5SDimitry Andric const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, 15390b57cec5SDimitry Andric const Expr *&ChunkExpr) const; 15400b57cec5SDimitry Andric 15410b57cec5SDimitry Andric /// Emits call of the outlined function with the provided arguments, 15420b57cec5SDimitry Andric /// translating these arguments to correct target-specific arguments. 15430b57cec5SDimitry Andric virtual void 15440b57cec5SDimitry Andric emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, 15450b57cec5SDimitry Andric llvm::FunctionCallee OutlinedFn, 1546bdd1243dSDimitry Andric ArrayRef<llvm::Value *> Args = std::nullopt) const; 15470b57cec5SDimitry Andric 15480b57cec5SDimitry Andric /// Emits OpenMP-specific function prolog. 15490b57cec5SDimitry Andric /// Required for device constructs. 15500b57cec5SDimitry Andric virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D); 15510b57cec5SDimitry Andric 15520b57cec5SDimitry Andric /// Gets the OpenMP-specific address of the local variable. 15530b57cec5SDimitry Andric virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, 15540b57cec5SDimitry Andric const VarDecl *VD); 15550b57cec5SDimitry Andric 15560b57cec5SDimitry Andric /// Marks the declaration as already emitted for the device code and returns 15570b57cec5SDimitry Andric /// true, if it was marked already, and false, otherwise. 15580b57cec5SDimitry Andric bool markAsGlobalTarget(GlobalDecl GD); 15590b57cec5SDimitry Andric 15600b57cec5SDimitry Andric /// Emit deferred declare target variables marked for deferred emission. 15610b57cec5SDimitry Andric void emitDeferredTargetDecls() const; 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric /// Adjust some parameters for the target-based directives, like addresses of 15640b57cec5SDimitry Andric /// the variables captured by reference in lambdas. 15650b57cec5SDimitry Andric virtual void 15660b57cec5SDimitry Andric adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, 15670b57cec5SDimitry Andric const OMPExecutableDirective &D) const; 15680b57cec5SDimitry Andric 15690b57cec5SDimitry Andric /// Perform check on requires decl to ensure that target architecture 15700b57cec5SDimitry Andric /// supports unified addressing 15715ffd83dbSDimitry Andric virtual void processRequiresDirective(const OMPRequiresDecl *D); 15725ffd83dbSDimitry Andric 15735ffd83dbSDimitry Andric /// Gets default memory ordering as specified in requires directive. 15745ffd83dbSDimitry Andric llvm::AtomicOrdering getDefaultMemoryOrdering() const; 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric /// Checks if the variable has associated OMPAllocateDeclAttr attribute with 15770b57cec5SDimitry Andric /// the predefined allocator and translates it into the corresponding address 15780b57cec5SDimitry Andric /// space. 15790b57cec5SDimitry Andric virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS); 15800b57cec5SDimitry Andric 15810b57cec5SDimitry Andric /// Return whether the unified_shared_memory has been specified. 15820b57cec5SDimitry Andric bool hasRequiresUnifiedSharedMemory() const; 1583a7dea167SDimitry Andric 1584480093f4SDimitry Andric /// Checks if the \p VD variable is marked as nontemporal declaration in 1585480093f4SDimitry Andric /// current context. 1586480093f4SDimitry Andric bool isNontemporalDecl(const ValueDecl *VD) const; 1587480093f4SDimitry Andric 15885ffd83dbSDimitry Andric /// Create specialized alloca to handle lastprivate conditionals. 15895ffd83dbSDimitry Andric Address emitLastprivateConditionalInit(CodeGenFunction &CGF, 15905ffd83dbSDimitry Andric const VarDecl *VD); 1591480093f4SDimitry Andric 1592480093f4SDimitry Andric /// Checks if the provided \p LVal is lastprivate conditional and emits the 1593480093f4SDimitry Andric /// code to update the value of the original variable. 1594480093f4SDimitry Andric /// \code 1595480093f4SDimitry Andric /// lastprivate(conditional: a) 1596480093f4SDimitry Andric /// ... 1597480093f4SDimitry Andric /// <type> a; 1598480093f4SDimitry Andric /// lp_a = ...; 1599480093f4SDimitry Andric /// #pragma omp critical(a) 1600480093f4SDimitry Andric /// if (last_iv_a <= iv) { 1601480093f4SDimitry Andric /// last_iv_a = iv; 1602480093f4SDimitry Andric /// global_a = lp_a; 1603480093f4SDimitry Andric /// } 1604480093f4SDimitry Andric /// \endcode 1605480093f4SDimitry Andric virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 1606480093f4SDimitry Andric const Expr *LHS); 1607480093f4SDimitry Andric 16085ffd83dbSDimitry Andric /// Checks if the lastprivate conditional was updated in inner region and 16095ffd83dbSDimitry Andric /// writes the value. 16105ffd83dbSDimitry Andric /// \code 16115ffd83dbSDimitry Andric /// lastprivate(conditional: a) 16125ffd83dbSDimitry Andric /// ... 16135ffd83dbSDimitry Andric /// <type> a;bool Fired = false; 16145ffd83dbSDimitry Andric /// #pragma omp ... shared(a) 16155ffd83dbSDimitry Andric /// { 16165ffd83dbSDimitry Andric /// lp_a = ...; 16175ffd83dbSDimitry Andric /// Fired = true; 16185ffd83dbSDimitry Andric /// } 16195ffd83dbSDimitry Andric /// if (Fired) { 16205ffd83dbSDimitry Andric /// #pragma omp critical(a) 16215ffd83dbSDimitry Andric /// if (last_iv_a <= iv) { 16225ffd83dbSDimitry Andric /// last_iv_a = iv; 16235ffd83dbSDimitry Andric /// global_a = lp_a; 16245ffd83dbSDimitry Andric /// } 16255ffd83dbSDimitry Andric /// Fired = false; 16265ffd83dbSDimitry Andric /// } 16275ffd83dbSDimitry Andric /// \endcode 16285ffd83dbSDimitry Andric virtual void checkAndEmitSharedLastprivateConditional( 16295ffd83dbSDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 16305ffd83dbSDimitry Andric const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls); 16315ffd83dbSDimitry Andric 1632480093f4SDimitry Andric /// Gets the address of the global copy used for lastprivate conditional 1633480093f4SDimitry Andric /// update, if any. 1634480093f4SDimitry Andric /// \param PrivLVal LValue for the private copy. 1635480093f4SDimitry Andric /// \param VD Original lastprivate declaration. 1636480093f4SDimitry Andric virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, 1637480093f4SDimitry Andric LValue PrivLVal, 1638480093f4SDimitry Andric const VarDecl *VD, 1639480093f4SDimitry Andric SourceLocation Loc); 16405ffd83dbSDimitry Andric 16415ffd83dbSDimitry Andric /// Emits list of dependecies based on the provided data (array of 16425ffd83dbSDimitry Andric /// dependence/expression pairs). 16435ffd83dbSDimitry Andric /// \returns Pointer to the first element of the array casted to VoidPtr type. 16445ffd83dbSDimitry Andric std::pair<llvm::Value *, Address> 16455ffd83dbSDimitry Andric emitDependClause(CodeGenFunction &CGF, 16465ffd83dbSDimitry Andric ArrayRef<OMPTaskDataTy::DependData> Dependencies, 16475ffd83dbSDimitry Andric SourceLocation Loc); 16485ffd83dbSDimitry Andric 16495ffd83dbSDimitry Andric /// Emits list of dependecies based on the provided data (array of 16505ffd83dbSDimitry Andric /// dependence/expression pairs) for depobj construct. In this case, the 16515ffd83dbSDimitry Andric /// variable is allocated in dynamically. \returns Pointer to the first 16525ffd83dbSDimitry Andric /// element of the array casted to VoidPtr type. 16535ffd83dbSDimitry Andric Address emitDepobjDependClause(CodeGenFunction &CGF, 16545ffd83dbSDimitry Andric const OMPTaskDataTy::DependData &Dependencies, 16555ffd83dbSDimitry Andric SourceLocation Loc); 16565ffd83dbSDimitry Andric 16575ffd83dbSDimitry Andric /// Emits the code to destroy the dependency object provided in depobj 16585ffd83dbSDimitry Andric /// directive. 16595ffd83dbSDimitry Andric void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 16605ffd83dbSDimitry Andric SourceLocation Loc); 16615ffd83dbSDimitry Andric 16625ffd83dbSDimitry Andric /// Updates the dependency kind in the specified depobj object. 16635ffd83dbSDimitry Andric /// \param DepobjLVal LValue for the main depobj object. 16645ffd83dbSDimitry Andric /// \param NewDepKind New dependency kind. 16655ffd83dbSDimitry Andric void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 16665ffd83dbSDimitry Andric OpenMPDependClauseKind NewDepKind, SourceLocation Loc); 16675ffd83dbSDimitry Andric 16685ffd83dbSDimitry Andric /// Initializes user defined allocators specified in the uses_allocators 16695ffd83dbSDimitry Andric /// clauses. 16705ffd83dbSDimitry Andric void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, 16715ffd83dbSDimitry Andric const Expr *AllocatorTraits); 16725ffd83dbSDimitry Andric 16735ffd83dbSDimitry Andric /// Destroys user defined allocators specified in the uses_allocators clause. 16745ffd83dbSDimitry Andric void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator); 1675e8d8bef9SDimitry Andric 1676e8d8bef9SDimitry Andric /// Returns true if the variable is a local variable in untied task. 1677e8d8bef9SDimitry Andric bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const; 16780b57cec5SDimitry Andric }; 16790b57cec5SDimitry Andric 16800b57cec5SDimitry Andric /// Class supports emissionof SIMD-only code. 16810b57cec5SDimitry Andric class CGOpenMPSIMDRuntime final : public CGOpenMPRuntime { 16820b57cec5SDimitry Andric public: CGOpenMPSIMDRuntime(CodeGenModule & CGM)16830b57cec5SDimitry Andric explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {} ~CGOpenMPSIMDRuntime()16840b57cec5SDimitry Andric ~CGOpenMPSIMDRuntime() override {} 16850b57cec5SDimitry Andric 16860b57cec5SDimitry Andric /// Emits outlined function for the specified OpenMP parallel directive 16870b57cec5SDimitry Andric /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, 16880b57cec5SDimitry Andric /// kmp_int32 BoundID, struct context_vars*). 168906c3fb27SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 16900b57cec5SDimitry Andric /// \param D OpenMP directive. 16910b57cec5SDimitry Andric /// \param ThreadIDVar Variable for thread id in the current OpenMP region. 16920b57cec5SDimitry Andric /// \param InnermostKind Kind of innermost directive (for simple directives it 16930b57cec5SDimitry Andric /// is a directive itself, for combined - its innermost directive). 16940b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 169506c3fb27SDimitry Andric llvm::Function *emitParallelOutlinedFunction( 169606c3fb27SDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 169706c3fb27SDimitry Andric const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 16980b57cec5SDimitry Andric const RegionCodeGenTy &CodeGen) override; 16990b57cec5SDimitry Andric 17000b57cec5SDimitry Andric /// Emits outlined function for the specified OpenMP teams directive 17010b57cec5SDimitry Andric /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, 17020b57cec5SDimitry Andric /// kmp_int32 BoundID, struct context_vars*). 170306c3fb27SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 17040b57cec5SDimitry Andric /// \param D OpenMP directive. 17050b57cec5SDimitry Andric /// \param ThreadIDVar Variable for thread id in the current OpenMP region. 17060b57cec5SDimitry Andric /// \param InnermostKind Kind of innermost directive (for simple directives it 17070b57cec5SDimitry Andric /// is a directive itself, for combined - its innermost directive). 17080b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 170906c3fb27SDimitry Andric llvm::Function *emitTeamsOutlinedFunction( 171006c3fb27SDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 171106c3fb27SDimitry Andric const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 17120b57cec5SDimitry Andric const RegionCodeGenTy &CodeGen) override; 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric /// Emits outlined function for the OpenMP task directive \a D. This 17150b57cec5SDimitry Andric /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t* 17160b57cec5SDimitry Andric /// TaskT). 17170b57cec5SDimitry Andric /// \param D OpenMP directive. 17180b57cec5SDimitry Andric /// \param ThreadIDVar Variable for thread id in the current OpenMP region. 17190b57cec5SDimitry Andric /// \param PartIDVar Variable for partition id in the current OpenMP untied 17200b57cec5SDimitry Andric /// task region. 17210b57cec5SDimitry Andric /// \param TaskTVar Variable for task_t argument. 17220b57cec5SDimitry Andric /// \param InnermostKind Kind of innermost directive (for simple directives it 17230b57cec5SDimitry Andric /// is a directive itself, for combined - its innermost directive). 17240b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 17250b57cec5SDimitry Andric /// \param Tied true if task is generated for tied task, false otherwise. 17260b57cec5SDimitry Andric /// \param NumberOfParts Number of parts in untied task. Ignored for tied 17270b57cec5SDimitry Andric /// tasks. 17280b57cec5SDimitry Andric /// 17290b57cec5SDimitry Andric llvm::Function *emitTaskOutlinedFunction( 17300b57cec5SDimitry Andric const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 17310b57cec5SDimitry Andric const VarDecl *PartIDVar, const VarDecl *TaskTVar, 17320b57cec5SDimitry Andric OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 17330b57cec5SDimitry Andric bool Tied, unsigned &NumberOfParts) override; 17340b57cec5SDimitry Andric 17350b57cec5SDimitry Andric /// Emits code for parallel or serial call of the \a OutlinedFn with 17360b57cec5SDimitry Andric /// variables captured in a record which address is stored in \a 17370b57cec5SDimitry Andric /// CapturedStruct. 17380b57cec5SDimitry Andric /// \param OutlinedFn Outlined function to be run in parallel threads. Type of 17390b57cec5SDimitry Andric /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). 17400b57cec5SDimitry Andric /// \param CapturedVars A pointer to the record with the references to 17410b57cec5SDimitry Andric /// variables used in \a OutlinedFn function. 17420b57cec5SDimitry Andric /// \param IfCond Condition in the associated 'if' clause, if it was 17430b57cec5SDimitry Andric /// specified, nullptr otherwise. 17440eae32dcSDimitry Andric /// \param NumThreads The value corresponding to the num_threads clause, if 17450eae32dcSDimitry Andric /// any, or nullptr. 17460b57cec5SDimitry Andric /// 17470b57cec5SDimitry Andric void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 17480b57cec5SDimitry Andric llvm::Function *OutlinedFn, 17490b57cec5SDimitry Andric ArrayRef<llvm::Value *> CapturedVars, 17500eae32dcSDimitry Andric const Expr *IfCond, llvm::Value *NumThreads) override; 17510b57cec5SDimitry Andric 17520b57cec5SDimitry Andric /// Emits a critical region. 17530b57cec5SDimitry Andric /// \param CriticalName Name of the critical region. 17540b57cec5SDimitry Andric /// \param CriticalOpGen Generator for the statement associated with the given 17550b57cec5SDimitry Andric /// critical region. 17560b57cec5SDimitry Andric /// \param Hint Value of the 'hint' clause (optional). 17570b57cec5SDimitry Andric void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, 17580b57cec5SDimitry Andric const RegionCodeGenTy &CriticalOpGen, 17590b57cec5SDimitry Andric SourceLocation Loc, 17600b57cec5SDimitry Andric const Expr *Hint = nullptr) override; 17610b57cec5SDimitry Andric 17620b57cec5SDimitry Andric /// Emits a master region. 17630b57cec5SDimitry Andric /// \param MasterOpGen Generator for the statement associated with the given 17640b57cec5SDimitry Andric /// master region. 17650b57cec5SDimitry Andric void emitMasterRegion(CodeGenFunction &CGF, 17660b57cec5SDimitry Andric const RegionCodeGenTy &MasterOpGen, 17670b57cec5SDimitry Andric SourceLocation Loc) override; 17680b57cec5SDimitry Andric 1769fe6060f1SDimitry Andric /// Emits a masked region. 1770fe6060f1SDimitry Andric /// \param MaskedOpGen Generator for the statement associated with the given 1771fe6060f1SDimitry Andric /// masked region. 1772fe6060f1SDimitry Andric void emitMaskedRegion(CodeGenFunction &CGF, 1773fe6060f1SDimitry Andric const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, 1774fe6060f1SDimitry Andric const Expr *Filter = nullptr) override; 1775fe6060f1SDimitry Andric 1776fe6060f1SDimitry Andric /// Emits a masked region. 1777fe6060f1SDimitry Andric /// \param MaskedOpGen Generator for the statement associated with the given 1778fe6060f1SDimitry Andric /// masked region. 1779fe6060f1SDimitry Andric 17800b57cec5SDimitry Andric /// Emits code for a taskyield directive. 17810b57cec5SDimitry Andric void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override; 17820b57cec5SDimitry Andric 17830b57cec5SDimitry Andric /// Emit a taskgroup region. 17840b57cec5SDimitry Andric /// \param TaskgroupOpGen Generator for the statement associated with the 17850b57cec5SDimitry Andric /// given taskgroup region. 17860b57cec5SDimitry Andric void emitTaskgroupRegion(CodeGenFunction &CGF, 17870b57cec5SDimitry Andric const RegionCodeGenTy &TaskgroupOpGen, 17880b57cec5SDimitry Andric SourceLocation Loc) override; 17890b57cec5SDimitry Andric 17900b57cec5SDimitry Andric /// Emits a single region. 17910b57cec5SDimitry Andric /// \param SingleOpGen Generator for the statement associated with the given 17920b57cec5SDimitry Andric /// single region. 17930b57cec5SDimitry Andric void emitSingleRegion(CodeGenFunction &CGF, 17940b57cec5SDimitry Andric const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, 17950b57cec5SDimitry Andric ArrayRef<const Expr *> CopyprivateVars, 17960b57cec5SDimitry Andric ArrayRef<const Expr *> DestExprs, 17970b57cec5SDimitry Andric ArrayRef<const Expr *> SrcExprs, 17980b57cec5SDimitry Andric ArrayRef<const Expr *> AssignmentOps) override; 17990b57cec5SDimitry Andric 18000b57cec5SDimitry Andric /// Emit an ordered region. 18010b57cec5SDimitry Andric /// \param OrderedOpGen Generator for the statement associated with the given 18020b57cec5SDimitry Andric /// ordered region. 18030b57cec5SDimitry Andric void emitOrderedRegion(CodeGenFunction &CGF, 18040b57cec5SDimitry Andric const RegionCodeGenTy &OrderedOpGen, 18050b57cec5SDimitry Andric SourceLocation Loc, bool IsThreads) override; 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric /// Emit an implicit/explicit barrier for OpenMP threads. 18080b57cec5SDimitry Andric /// \param Kind Directive for which this implicit barrier call must be 18090b57cec5SDimitry Andric /// generated. Must be OMPD_barrier for explicit barrier generation. 18100b57cec5SDimitry Andric /// \param EmitChecks true if need to emit checks for cancellation barriers. 18110b57cec5SDimitry Andric /// \param ForceSimpleCall true simple barrier call must be emitted, false if 18120b57cec5SDimitry Andric /// runtime class decides which one to emit (simple or with cancellation 18130b57cec5SDimitry Andric /// checks). 18140b57cec5SDimitry Andric /// 18150b57cec5SDimitry Andric void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 18160b57cec5SDimitry Andric OpenMPDirectiveKind Kind, bool EmitChecks = true, 18170b57cec5SDimitry Andric bool ForceSimpleCall = false) override; 18180b57cec5SDimitry Andric 18190b57cec5SDimitry Andric /// This is used for non static scheduled types and when the ordered 18200b57cec5SDimitry Andric /// clause is present on the loop construct. 18210b57cec5SDimitry Andric /// Depending on the loop schedule, it is necessary to call some runtime 18220b57cec5SDimitry Andric /// routine before start of the OpenMP loop to get the loop upper / lower 18230b57cec5SDimitry Andric /// bounds \a LB and \a UB and stride \a ST. 18240b57cec5SDimitry Andric /// 18250b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 18260b57cec5SDimitry Andric /// \param Loc Clang source location. 18270b57cec5SDimitry Andric /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. 18280b57cec5SDimitry Andric /// \param IVSize Size of the iteration variable in bits. 18290b57cec5SDimitry Andric /// \param IVSigned Sign of the iteration variable. 18300b57cec5SDimitry Andric /// \param Ordered true if loop is ordered, false otherwise. 18310b57cec5SDimitry Andric /// \param DispatchValues struct containing llvm values for lower bound, upper 18320b57cec5SDimitry Andric /// bound, and chunk expression. 18330b57cec5SDimitry Andric /// For the default (nullptr) value, the chunk 1 will be used. 18340b57cec5SDimitry Andric /// 18350b57cec5SDimitry Andric void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, 18360b57cec5SDimitry Andric const OpenMPScheduleTy &ScheduleKind, 18370b57cec5SDimitry Andric unsigned IVSize, bool IVSigned, bool Ordered, 18380b57cec5SDimitry Andric const DispatchRTInput &DispatchValues) override; 18390b57cec5SDimitry Andric 1840*0fca6ea1SDimitry Andric /// This is used for non static scheduled types and when the ordered 1841*0fca6ea1SDimitry Andric /// clause is present on the loop construct. 1842*0fca6ea1SDimitry Andric /// 1843*0fca6ea1SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 1844*0fca6ea1SDimitry Andric /// \param Loc Clang source location. 1845*0fca6ea1SDimitry Andric /// 1846*0fca6ea1SDimitry Andric void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override; 1847*0fca6ea1SDimitry Andric 18480b57cec5SDimitry Andric /// Call the appropriate runtime routine to initialize it before start 18490b57cec5SDimitry Andric /// of loop. 18500b57cec5SDimitry Andric /// 18510b57cec5SDimitry Andric /// This is used only in case of static schedule, when the user did not 18520b57cec5SDimitry Andric /// specify a ordered clause on the loop construct. 18530b57cec5SDimitry Andric /// Depending on the loop schedule, it is necessary to call some runtime 18540b57cec5SDimitry Andric /// routine before start of the OpenMP loop to get the loop upper / lower 18550b57cec5SDimitry Andric /// bounds LB and UB and stride ST. 18560b57cec5SDimitry Andric /// 18570b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 18580b57cec5SDimitry Andric /// \param Loc Clang source location. 18590b57cec5SDimitry Andric /// \param DKind Kind of the directive. 18600b57cec5SDimitry Andric /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. 18610b57cec5SDimitry Andric /// \param Values Input arguments for the construct. 18620b57cec5SDimitry Andric /// 18630b57cec5SDimitry Andric void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, 18640b57cec5SDimitry Andric OpenMPDirectiveKind DKind, 18650b57cec5SDimitry Andric const OpenMPScheduleTy &ScheduleKind, 18660b57cec5SDimitry Andric const StaticRTInput &Values) override; 18670b57cec5SDimitry Andric 18680b57cec5SDimitry Andric /// 18690b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 18700b57cec5SDimitry Andric /// \param Loc Clang source location. 18710b57cec5SDimitry Andric /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause. 18720b57cec5SDimitry Andric /// \param Values Input arguments for the construct. 18730b57cec5SDimitry Andric /// 18740b57cec5SDimitry Andric void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, 18750b57cec5SDimitry Andric OpenMPDistScheduleClauseKind SchedKind, 18760b57cec5SDimitry Andric const StaticRTInput &Values) override; 18770b57cec5SDimitry Andric 18780b57cec5SDimitry Andric /// Call the appropriate runtime routine to notify that we finished 18790b57cec5SDimitry Andric /// iteration of the ordered loop with the dynamic scheduling. 18800b57cec5SDimitry Andric /// 18810b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 18820b57cec5SDimitry Andric /// \param Loc Clang source location. 18830b57cec5SDimitry Andric /// \param IVSize Size of the iteration variable in bits. 18840b57cec5SDimitry Andric /// \param IVSigned Sign of the iteration variable. 18850b57cec5SDimitry Andric /// 18860b57cec5SDimitry Andric void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, 18870b57cec5SDimitry Andric unsigned IVSize, bool IVSigned) override; 18880b57cec5SDimitry Andric 18890b57cec5SDimitry Andric /// Call the appropriate runtime routine to notify that we finished 18900b57cec5SDimitry Andric /// all the work with current loop. 18910b57cec5SDimitry Andric /// 18920b57cec5SDimitry Andric /// \param CGF Reference to current CodeGenFunction. 18930b57cec5SDimitry Andric /// \param Loc Clang source location. 18940b57cec5SDimitry Andric /// \param DKind Kind of the directive for which the static finish is emitted. 18950b57cec5SDimitry Andric /// 18960b57cec5SDimitry Andric void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, 18970b57cec5SDimitry Andric OpenMPDirectiveKind DKind) override; 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric /// Call __kmpc_dispatch_next( 19000b57cec5SDimitry Andric /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 19010b57cec5SDimitry Andric /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 19020b57cec5SDimitry Andric /// kmp_int[32|64] *p_stride); 19030b57cec5SDimitry Andric /// \param IVSize Size of the iteration variable in bits. 19040b57cec5SDimitry Andric /// \param IVSigned Sign of the iteration variable. 19050b57cec5SDimitry Andric /// \param IL Address of the output variable in which the flag of the 19060b57cec5SDimitry Andric /// last iteration is returned. 19070b57cec5SDimitry Andric /// \param LB Address of the output variable in which the lower iteration 19080b57cec5SDimitry Andric /// number is returned. 19090b57cec5SDimitry Andric /// \param UB Address of the output variable in which the upper iteration 19100b57cec5SDimitry Andric /// number is returned. 19110b57cec5SDimitry Andric /// \param ST Address of the output variable in which the stride value is 19120b57cec5SDimitry Andric /// returned. 19130b57cec5SDimitry Andric llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc, 19140b57cec5SDimitry Andric unsigned IVSize, bool IVSigned, Address IL, 19150b57cec5SDimitry Andric Address LB, Address UB, Address ST) override; 19160b57cec5SDimitry Andric 19170b57cec5SDimitry Andric /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 19180b57cec5SDimitry Andric /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' 19190b57cec5SDimitry Andric /// clause. 19200b57cec5SDimitry Andric /// \param NumThreads An integer value of threads. 19210b57cec5SDimitry Andric void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, 19220b57cec5SDimitry Andric SourceLocation Loc) override; 19230b57cec5SDimitry Andric 19240b57cec5SDimitry Andric /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 19250b57cec5SDimitry Andric /// global_tid, int proc_bind) to generate code for 'proc_bind' clause. 19260b57cec5SDimitry Andric void emitProcBindClause(CodeGenFunction &CGF, 1927480093f4SDimitry Andric llvm::omp::ProcBindKind ProcBind, 19280b57cec5SDimitry Andric SourceLocation Loc) override; 19290b57cec5SDimitry Andric 19300b57cec5SDimitry Andric /// Returns address of the threadprivate variable for the current 19310b57cec5SDimitry Andric /// thread. 19320b57cec5SDimitry Andric /// \param VD Threadprivate variable. 19330b57cec5SDimitry Andric /// \param VDAddr Address of the global variable \a VD. 19340b57cec5SDimitry Andric /// \param Loc Location of the reference to threadprivate var. 19350b57cec5SDimitry Andric /// \return Address of the threadprivate variable for the current thread. 19360b57cec5SDimitry Andric Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, 19370b57cec5SDimitry Andric Address VDAddr, SourceLocation Loc) override; 19380b57cec5SDimitry Andric 19390b57cec5SDimitry Andric /// Emit a code for initialization of threadprivate variable. It emits 19400b57cec5SDimitry Andric /// a call to runtime library which adds initial value to the newly created 19410b57cec5SDimitry Andric /// threadprivate variable (if it is not constant) and registers destructor 19420b57cec5SDimitry Andric /// for the variable (if any). 19430b57cec5SDimitry Andric /// \param VD Threadprivate variable. 19440b57cec5SDimitry Andric /// \param VDAddr Address of the global variable \a VD. 19450b57cec5SDimitry Andric /// \param Loc Location of threadprivate declaration. 19460b57cec5SDimitry Andric /// \param PerformInit true if initialization expression is not constant. 19470b57cec5SDimitry Andric llvm::Function * 19480b57cec5SDimitry Andric emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, 19490b57cec5SDimitry Andric SourceLocation Loc, bool PerformInit, 19500b57cec5SDimitry Andric CodeGenFunction *CGF = nullptr) override; 19510b57cec5SDimitry Andric 19520b57cec5SDimitry Andric /// Creates artificial threadprivate variable with name \p Name and type \p 19530b57cec5SDimitry Andric /// VarType. 19540b57cec5SDimitry Andric /// \param VarType Type of the artificial threadprivate variable. 19550b57cec5SDimitry Andric /// \param Name Name of the artificial threadprivate variable. 19560b57cec5SDimitry Andric Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 19570b57cec5SDimitry Andric QualType VarType, 19580b57cec5SDimitry Andric StringRef Name) override; 19590b57cec5SDimitry Andric 19600b57cec5SDimitry Andric /// Emit flush of the variables specified in 'omp flush' directive. 19610b57cec5SDimitry Andric /// \param Vars List of variables to flush. 19620b57cec5SDimitry Andric void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars, 19635ffd83dbSDimitry Andric SourceLocation Loc, llvm::AtomicOrdering AO) override; 19640b57cec5SDimitry Andric 19650b57cec5SDimitry Andric /// Emit task region for the task directive. The task region is 19660b57cec5SDimitry Andric /// emitted in several steps: 19670b57cec5SDimitry Andric /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 19680b57cec5SDimitry Andric /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 19690b57cec5SDimitry Andric /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the 19700b57cec5SDimitry Andric /// function: 19710b57cec5SDimitry Andric /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 19720b57cec5SDimitry Andric /// TaskFunction(gtid, tt->part_id, tt->shareds); 19730b57cec5SDimitry Andric /// return 0; 19740b57cec5SDimitry Andric /// } 19750b57cec5SDimitry Andric /// 2. Copy a list of shared variables to field shareds of the resulting 19760b57cec5SDimitry Andric /// structure kmp_task_t returned by the previous call (if any). 19770b57cec5SDimitry Andric /// 3. Copy a pointer to destructions function to field destructions of the 19780b57cec5SDimitry Andric /// resulting structure kmp_task_t. 19790b57cec5SDimitry Andric /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, 19800b57cec5SDimitry Andric /// kmp_task_t *new_task), where new_task is a resulting structure from 19810b57cec5SDimitry Andric /// previous items. 19820b57cec5SDimitry Andric /// \param D Current task directive. 19830b57cec5SDimitry Andric /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 19840b57cec5SDimitry Andric /// /*part_id*/, captured_struct */*__context*/); 19850b57cec5SDimitry Andric /// \param SharedsTy A type which contains references the shared variables. 19860b57cec5SDimitry Andric /// \param Shareds Context with the list of shared variables from the \p 19870b57cec5SDimitry Andric /// TaskFunction. 19880b57cec5SDimitry Andric /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr 19890b57cec5SDimitry Andric /// otherwise. 19900b57cec5SDimitry Andric /// \param Data Additional data for task generation like tiednsee, final 19910b57cec5SDimitry Andric /// state, list of privates etc. 19920b57cec5SDimitry Andric void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 19930b57cec5SDimitry Andric const OMPExecutableDirective &D, 19940b57cec5SDimitry Andric llvm::Function *TaskFunction, QualType SharedsTy, 19950b57cec5SDimitry Andric Address Shareds, const Expr *IfCond, 19960b57cec5SDimitry Andric const OMPTaskDataTy &Data) override; 19970b57cec5SDimitry Andric 19980b57cec5SDimitry Andric /// Emit task region for the taskloop directive. The taskloop region is 19990b57cec5SDimitry Andric /// emitted in several steps: 20000b57cec5SDimitry Andric /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 20010b57cec5SDimitry Andric /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 20020b57cec5SDimitry Andric /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the 20030b57cec5SDimitry Andric /// function: 20040b57cec5SDimitry Andric /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 20050b57cec5SDimitry Andric /// TaskFunction(gtid, tt->part_id, tt->shareds); 20060b57cec5SDimitry Andric /// return 0; 20070b57cec5SDimitry Andric /// } 20080b57cec5SDimitry Andric /// 2. Copy a list of shared variables to field shareds of the resulting 20090b57cec5SDimitry Andric /// structure kmp_task_t returned by the previous call (if any). 20100b57cec5SDimitry Andric /// 3. Copy a pointer to destructions function to field destructions of the 20110b57cec5SDimitry Andric /// resulting structure kmp_task_t. 20120b57cec5SDimitry Andric /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t 20130b57cec5SDimitry Andric /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int 20140b57cec5SDimitry Andric /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task 20150b57cec5SDimitry Andric /// is a resulting structure from 20160b57cec5SDimitry Andric /// previous items. 20170b57cec5SDimitry Andric /// \param D Current task directive. 20180b57cec5SDimitry Andric /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 20190b57cec5SDimitry Andric /// /*part_id*/, captured_struct */*__context*/); 20200b57cec5SDimitry Andric /// \param SharedsTy A type which contains references the shared variables. 20210b57cec5SDimitry Andric /// \param Shareds Context with the list of shared variables from the \p 20220b57cec5SDimitry Andric /// TaskFunction. 20230b57cec5SDimitry Andric /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr 20240b57cec5SDimitry Andric /// otherwise. 20250b57cec5SDimitry Andric /// \param Data Additional data for task generation like tiednsee, final 20260b57cec5SDimitry Andric /// state, list of privates etc. 20270b57cec5SDimitry Andric void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 20280b57cec5SDimitry Andric const OMPLoopDirective &D, llvm::Function *TaskFunction, 20290b57cec5SDimitry Andric QualType SharedsTy, Address Shareds, const Expr *IfCond, 20300b57cec5SDimitry Andric const OMPTaskDataTy &Data) override; 20310b57cec5SDimitry Andric 20320b57cec5SDimitry Andric /// Emit a code for reduction clause. Next code should be emitted for 20330b57cec5SDimitry Andric /// reduction: 20340b57cec5SDimitry Andric /// \code 20350b57cec5SDimitry Andric /// 20360b57cec5SDimitry Andric /// static kmp_critical_name lock = { 0 }; 20370b57cec5SDimitry Andric /// 20380b57cec5SDimitry Andric /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 20390b57cec5SDimitry Andric /// ... 20400b57cec5SDimitry Andric /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 20410b57cec5SDimitry Andric /// ... 20420b57cec5SDimitry Andric /// } 20430b57cec5SDimitry Andric /// 20440b57cec5SDimitry Andric /// ... 20450b57cec5SDimitry Andric /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 20460b57cec5SDimitry Andric /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 20470b57cec5SDimitry Andric /// RedList, reduce_func, &<lock>)) { 20480b57cec5SDimitry Andric /// case 1: 20490b57cec5SDimitry Andric /// ... 20500b57cec5SDimitry Andric /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 20510b57cec5SDimitry Andric /// ... 20520b57cec5SDimitry Andric /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 20530b57cec5SDimitry Andric /// break; 20540b57cec5SDimitry Andric /// case 2: 20550b57cec5SDimitry Andric /// ... 20560b57cec5SDimitry Andric /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 20570b57cec5SDimitry Andric /// ... 20580b57cec5SDimitry Andric /// break; 20590b57cec5SDimitry Andric /// default:; 20600b57cec5SDimitry Andric /// } 20610b57cec5SDimitry Andric /// \endcode 20620b57cec5SDimitry Andric /// 20630b57cec5SDimitry Andric /// \param Privates List of private copies for original reduction arguments. 20640b57cec5SDimitry Andric /// \param LHSExprs List of LHS in \a ReductionOps reduction operations. 20650b57cec5SDimitry Andric /// \param RHSExprs List of RHS in \a ReductionOps reduction operations. 20660b57cec5SDimitry Andric /// \param ReductionOps List of reduction operations in form 'LHS binop RHS' 20670b57cec5SDimitry Andric /// or 'operator binop(LHS, RHS)'. 20680b57cec5SDimitry Andric /// \param Options List of options for reduction codegen: 20690b57cec5SDimitry Andric /// WithNowait true if parent directive has also nowait clause, false 20700b57cec5SDimitry Andric /// otherwise. 20710b57cec5SDimitry Andric /// SimpleReduction Emit reduction operation only. Used for omp simd 20720b57cec5SDimitry Andric /// directive on the host. 20730b57cec5SDimitry Andric /// ReductionKind The kind of reduction to perform. 20740b57cec5SDimitry Andric void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 20750b57cec5SDimitry Andric ArrayRef<const Expr *> Privates, 20760b57cec5SDimitry Andric ArrayRef<const Expr *> LHSExprs, 20770b57cec5SDimitry Andric ArrayRef<const Expr *> RHSExprs, 20780b57cec5SDimitry Andric ArrayRef<const Expr *> ReductionOps, 20790b57cec5SDimitry Andric ReductionOptionsTy Options) override; 20800b57cec5SDimitry Andric 20810b57cec5SDimitry Andric /// Emit a code for initialization of task reduction clause. Next code 20820b57cec5SDimitry Andric /// should be emitted for reduction: 20830b57cec5SDimitry Andric /// \code 20840b57cec5SDimitry Andric /// 20855ffd83dbSDimitry Andric /// _taskred_item_t red_data[n]; 20860b57cec5SDimitry Andric /// ... 20875ffd83dbSDimitry Andric /// red_data[i].shar = &shareds[i]; 20885ffd83dbSDimitry Andric /// red_data[i].orig = &origs[i]; 20890b57cec5SDimitry Andric /// red_data[i].size = sizeof(origs[i]); 20900b57cec5SDimitry Andric /// red_data[i].f_init = (void*)RedInit<i>; 20910b57cec5SDimitry Andric /// red_data[i].f_fini = (void*)RedDest<i>; 20920b57cec5SDimitry Andric /// red_data[i].f_comb = (void*)RedOp<i>; 20930b57cec5SDimitry Andric /// red_data[i].flags = <Flag_i>; 20940b57cec5SDimitry Andric /// ... 20955ffd83dbSDimitry Andric /// void* tg1 = __kmpc_taskred_init(gtid, n, red_data); 20960b57cec5SDimitry Andric /// \endcode 20975ffd83dbSDimitry Andric /// For reduction clause with task modifier it emits the next call: 20985ffd83dbSDimitry Andric /// \code 20990b57cec5SDimitry Andric /// 21005ffd83dbSDimitry Andric /// _taskred_item_t red_data[n]; 21015ffd83dbSDimitry Andric /// ... 21025ffd83dbSDimitry Andric /// red_data[i].shar = &shareds[i]; 21035ffd83dbSDimitry Andric /// red_data[i].orig = &origs[i]; 21045ffd83dbSDimitry Andric /// red_data[i].size = sizeof(origs[i]); 21055ffd83dbSDimitry Andric /// red_data[i].f_init = (void*)RedInit<i>; 21065ffd83dbSDimitry Andric /// red_data[i].f_fini = (void*)RedDest<i>; 21075ffd83dbSDimitry Andric /// red_data[i].f_comb = (void*)RedOp<i>; 21085ffd83dbSDimitry Andric /// red_data[i].flags = <Flag_i>; 21095ffd83dbSDimitry Andric /// ... 21105ffd83dbSDimitry Andric /// void* tg1 = __kmpc_taskred_modifier_init(loc, gtid, is_worksharing, n, 21115ffd83dbSDimitry Andric /// red_data); 21125ffd83dbSDimitry Andric /// \endcode 21130b57cec5SDimitry Andric /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations. 21140b57cec5SDimitry Andric /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations. 21150b57cec5SDimitry Andric /// \param Data Additional data for task generation like tiedness, final 21160b57cec5SDimitry Andric /// state, list of privates, reductions etc. 21170b57cec5SDimitry Andric llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, 21180b57cec5SDimitry Andric ArrayRef<const Expr *> LHSExprs, 21190b57cec5SDimitry Andric ArrayRef<const Expr *> RHSExprs, 21200b57cec5SDimitry Andric const OMPTaskDataTy &Data) override; 21210b57cec5SDimitry Andric 21225ffd83dbSDimitry Andric /// Emits the following code for reduction clause with task modifier: 21235ffd83dbSDimitry Andric /// \code 21245ffd83dbSDimitry Andric /// __kmpc_task_reduction_modifier_fini(loc, gtid, is_worksharing); 21255ffd83dbSDimitry Andric /// \endcode 21265ffd83dbSDimitry Andric void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, 21275ffd83dbSDimitry Andric bool IsWorksharingReduction) override; 21285ffd83dbSDimitry Andric 21290b57cec5SDimitry Andric /// Required to resolve existing problems in the runtime. Emits threadprivate 21300b57cec5SDimitry Andric /// variables to store the size of the VLAs/array sections for 21310b57cec5SDimitry Andric /// initializer/combiner/finalizer functions + emits threadprivate variable to 21320b57cec5SDimitry Andric /// store the pointer to the original reduction item for the custom 21330b57cec5SDimitry Andric /// initializer defined by declare reduction construct. 21340b57cec5SDimitry Andric /// \param RCG Allows to reuse an existing data for the reductions. 21350b57cec5SDimitry Andric /// \param N Reduction item for which fixups must be emitted. 21360b57cec5SDimitry Andric void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, 21370b57cec5SDimitry Andric ReductionCodeGen &RCG, unsigned N) override; 21380b57cec5SDimitry Andric 21390b57cec5SDimitry Andric /// Get the address of `void *` type of the privatue copy of the reduction 21400b57cec5SDimitry Andric /// item specified by the \p SharedLVal. 21410b57cec5SDimitry Andric /// \param ReductionsPtr Pointer to the reduction data returned by the 21420b57cec5SDimitry Andric /// emitTaskReductionInit function. 21430b57cec5SDimitry Andric /// \param SharedLVal Address of the original reduction item. 21440b57cec5SDimitry Andric Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, 21450b57cec5SDimitry Andric llvm::Value *ReductionsPtr, 21460b57cec5SDimitry Andric LValue SharedLVal) override; 21470b57cec5SDimitry Andric 21480b57cec5SDimitry Andric /// Emit code for 'taskwait' directive. 2149349cc55cSDimitry Andric void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, 2150349cc55cSDimitry Andric const OMPTaskDataTy &Data) override; 21510b57cec5SDimitry Andric 21520b57cec5SDimitry Andric /// Emit code for 'cancellation point' construct. 21530b57cec5SDimitry Andric /// \param CancelRegion Region kind for which the cancellation point must be 21540b57cec5SDimitry Andric /// emitted. 21550b57cec5SDimitry Andric /// 21560b57cec5SDimitry Andric void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, 21570b57cec5SDimitry Andric OpenMPDirectiveKind CancelRegion) override; 21580b57cec5SDimitry Andric 21590b57cec5SDimitry Andric /// Emit code for 'cancel' construct. 21600b57cec5SDimitry Andric /// \param IfCond Condition in the associated 'if' clause, if it was 21610b57cec5SDimitry Andric /// specified, nullptr otherwise. 21620b57cec5SDimitry Andric /// \param CancelRegion Region kind for which the cancel must be emitted. 21630b57cec5SDimitry Andric /// 21640b57cec5SDimitry Andric void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 21650b57cec5SDimitry Andric const Expr *IfCond, 21660b57cec5SDimitry Andric OpenMPDirectiveKind CancelRegion) override; 21670b57cec5SDimitry Andric 21680b57cec5SDimitry Andric /// Emit outilined function for 'target' directive. 21690b57cec5SDimitry Andric /// \param D Directive to emit. 21700b57cec5SDimitry Andric /// \param ParentName Name of the function that encloses the target region. 21710b57cec5SDimitry Andric /// \param OutlinedFn Outlined function value to be defined by this call. 21720b57cec5SDimitry Andric /// \param OutlinedFnID Outlined function ID value to be defined by this call. 21730b57cec5SDimitry Andric /// \param IsOffloadEntry True if the outlined function is an offload entry. 21740b57cec5SDimitry Andric /// \param CodeGen Code generation sequence for the \a D directive. 21750b57cec5SDimitry Andric /// An outlined function may not be an entry if, e.g. the if clause always 21760b57cec5SDimitry Andric /// evaluates to false. 21770b57cec5SDimitry Andric void emitTargetOutlinedFunction(const OMPExecutableDirective &D, 21780b57cec5SDimitry Andric StringRef ParentName, 21790b57cec5SDimitry Andric llvm::Function *&OutlinedFn, 21800b57cec5SDimitry Andric llvm::Constant *&OutlinedFnID, 21810b57cec5SDimitry Andric bool IsOffloadEntry, 21820b57cec5SDimitry Andric const RegionCodeGenTy &CodeGen) override; 21830b57cec5SDimitry Andric 21840b57cec5SDimitry Andric /// Emit the target offloading code associated with \a D. The emitted 21850b57cec5SDimitry Andric /// code attempts offloading the execution to the device, an the event of 21860b57cec5SDimitry Andric /// a failure it executes the host version outlined in \a OutlinedFn. 21870b57cec5SDimitry Andric /// \param D Directive to emit. 21880b57cec5SDimitry Andric /// \param OutlinedFn Host version of the code to be offloaded. 21890b57cec5SDimitry Andric /// \param OutlinedFnID ID of host version of the code to be offloaded. 21900b57cec5SDimitry Andric /// \param IfCond Expression evaluated in if clause associated with the target 21910b57cec5SDimitry Andric /// directive, or null if no if clause is used. 21920b57cec5SDimitry Andric /// \param Device Expression evaluated in device clause associated with the 21935ffd83dbSDimitry Andric /// target directive, or null if no device clause is used and device modifier. 21945ffd83dbSDimitry Andric void emitTargetCall( 21955ffd83dbSDimitry Andric CodeGenFunction &CGF, const OMPExecutableDirective &D, 21965ffd83dbSDimitry Andric llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 21975ffd83dbSDimitry Andric llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 2198a7dea167SDimitry Andric llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 2199a7dea167SDimitry Andric const OMPLoopDirective &D)> 2200a7dea167SDimitry Andric SizeEmitter) override; 22010b57cec5SDimitry Andric 22020b57cec5SDimitry Andric /// Emit the target regions enclosed in \a GD function definition or 22030b57cec5SDimitry Andric /// the function itself in case it is a valid device function. Returns true if 22040b57cec5SDimitry Andric /// \a GD was dealt with successfully. 22050b57cec5SDimitry Andric /// \param GD Function to scan. 22060b57cec5SDimitry Andric bool emitTargetFunctions(GlobalDecl GD) override; 22070b57cec5SDimitry Andric 22080b57cec5SDimitry Andric /// Emit the global variable if it is a valid device global variable. 22090b57cec5SDimitry Andric /// Returns true if \a GD was dealt with successfully. 22100b57cec5SDimitry Andric /// \param GD Variable declaration to emit. 22110b57cec5SDimitry Andric bool emitTargetGlobalVariable(GlobalDecl GD) override; 22120b57cec5SDimitry Andric 22130b57cec5SDimitry Andric /// Emit the global \a GD if it is meaningful for the target. Returns 22140b57cec5SDimitry Andric /// if it was emitted successfully. 22150b57cec5SDimitry Andric /// \param GD Global to scan. 22160b57cec5SDimitry Andric bool emitTargetGlobal(GlobalDecl GD) override; 22170b57cec5SDimitry Andric 22180b57cec5SDimitry Andric /// Emits code for teams call of the \a OutlinedFn with 22190b57cec5SDimitry Andric /// variables captured in a record which address is stored in \a 22200b57cec5SDimitry Andric /// CapturedStruct. 22210b57cec5SDimitry Andric /// \param OutlinedFn Outlined function to be run by team masters. Type of 22220b57cec5SDimitry Andric /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). 22230b57cec5SDimitry Andric /// \param CapturedVars A pointer to the record with the references to 22240b57cec5SDimitry Andric /// variables used in \a OutlinedFn function. 22250b57cec5SDimitry Andric /// 22260b57cec5SDimitry Andric void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, 22270b57cec5SDimitry Andric SourceLocation Loc, llvm::Function *OutlinedFn, 22280b57cec5SDimitry Andric ArrayRef<llvm::Value *> CapturedVars) override; 22290b57cec5SDimitry Andric 22300b57cec5SDimitry Andric /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 22310b57cec5SDimitry Andric /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code 22320b57cec5SDimitry Andric /// for num_teams clause. 22330b57cec5SDimitry Andric /// \param NumTeams An integer expression of teams. 22340b57cec5SDimitry Andric /// \param ThreadLimit An integer expression of threads. 22350b57cec5SDimitry Andric void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, 22360b57cec5SDimitry Andric const Expr *ThreadLimit, SourceLocation Loc) override; 22370b57cec5SDimitry Andric 22380b57cec5SDimitry Andric /// Emit the target data mapping code associated with \a D. 22390b57cec5SDimitry Andric /// \param D Directive to emit. 22400b57cec5SDimitry Andric /// \param IfCond Expression evaluated in if clause associated with the 22410b57cec5SDimitry Andric /// target directive, or null if no device clause is used. 22420b57cec5SDimitry Andric /// \param Device Expression evaluated in device clause associated with the 22430b57cec5SDimitry Andric /// target directive, or null if no device clause is used. 22440b57cec5SDimitry Andric /// \param Info A record used to store information that needs to be preserved 22450b57cec5SDimitry Andric /// until the region is closed. 22460b57cec5SDimitry Andric void emitTargetDataCalls(CodeGenFunction &CGF, 22470b57cec5SDimitry Andric const OMPExecutableDirective &D, const Expr *IfCond, 22480b57cec5SDimitry Andric const Expr *Device, const RegionCodeGenTy &CodeGen, 2249bdd1243dSDimitry Andric CGOpenMPRuntime::TargetDataInfo &Info) override; 22500b57cec5SDimitry Andric 22510b57cec5SDimitry Andric /// Emit the data mapping/movement code associated with the directive 22520b57cec5SDimitry Andric /// \a D that should be of the form 'target [{enter|exit} data | update]'. 22530b57cec5SDimitry Andric /// \param D Directive to emit. 22540b57cec5SDimitry Andric /// \param IfCond Expression evaluated in if clause associated with the target 22550b57cec5SDimitry Andric /// directive, or null if no if clause is used. 22560b57cec5SDimitry Andric /// \param Device Expression evaluated in device clause associated with the 22570b57cec5SDimitry Andric /// target directive, or null if no device clause is used. 22580b57cec5SDimitry Andric void emitTargetDataStandAloneCall(CodeGenFunction &CGF, 22590b57cec5SDimitry Andric const OMPExecutableDirective &D, 22600b57cec5SDimitry Andric const Expr *IfCond, 22610b57cec5SDimitry Andric const Expr *Device) override; 22620b57cec5SDimitry Andric 22630b57cec5SDimitry Andric /// Emit initialization for doacross loop nesting support. 22640b57cec5SDimitry Andric /// \param D Loop-based construct used in doacross nesting construct. 22650b57cec5SDimitry Andric void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, 22660b57cec5SDimitry Andric ArrayRef<Expr *> NumIterations) override; 22670b57cec5SDimitry Andric 22680b57cec5SDimitry Andric /// Emit code for doacross ordered directive with 'depend' clause. 22690b57cec5SDimitry Andric /// \param C 'depend' clause with 'sink|source' dependency kind. 22700b57cec5SDimitry Andric void emitDoacrossOrdered(CodeGenFunction &CGF, 22710b57cec5SDimitry Andric const OMPDependClause *C) override; 22720b57cec5SDimitry Andric 227306c3fb27SDimitry Andric /// Emit code for doacross ordered directive with 'doacross' clause. 227406c3fb27SDimitry Andric /// \param C 'doacross' clause with 'sink|source' dependence type. 227506c3fb27SDimitry Andric void emitDoacrossOrdered(CodeGenFunction &CGF, 227606c3fb27SDimitry Andric const OMPDoacrossClause *C) override; 227706c3fb27SDimitry Andric 22780b57cec5SDimitry Andric /// Translates the native parameter of outlined function if this is required 22790b57cec5SDimitry Andric /// for target. 22800b57cec5SDimitry Andric /// \param FD Field decl from captured record for the parameter. 22810b57cec5SDimitry Andric /// \param NativeParam Parameter itself. 22820b57cec5SDimitry Andric const VarDecl *translateParameter(const FieldDecl *FD, 22830b57cec5SDimitry Andric const VarDecl *NativeParam) const override; 22840b57cec5SDimitry Andric 22850b57cec5SDimitry Andric /// Gets the address of the native argument basing on the address of the 22860b57cec5SDimitry Andric /// target-specific parameter. 22870b57cec5SDimitry Andric /// \param NativeParam Parameter itself. 22880b57cec5SDimitry Andric /// \param TargetParam Corresponding target-specific parameter. 22890b57cec5SDimitry Andric Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, 22900b57cec5SDimitry Andric const VarDecl *TargetParam) const override; 22910b57cec5SDimitry Andric 22920b57cec5SDimitry Andric /// Gets the OpenMP-specific address of the local variable. getAddressOfLocalVariable(CodeGenFunction & CGF,const VarDecl * VD)22930b57cec5SDimitry Andric Address getAddressOfLocalVariable(CodeGenFunction &CGF, 22940b57cec5SDimitry Andric const VarDecl *VD) override { 22950b57cec5SDimitry Andric return Address::invalid(); 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric }; 22980b57cec5SDimitry Andric 22990b57cec5SDimitry Andric } // namespace CodeGen 230006c3fb27SDimitry Andric // Utility for openmp doacross clause kind 230106c3fb27SDimitry Andric namespace { 230206c3fb27SDimitry Andric template <typename T> class OMPDoacrossKind { 230306c3fb27SDimitry Andric public: isSink(const T *)230406c3fb27SDimitry Andric bool isSink(const T *) { return false; } isSource(const T *)230506c3fb27SDimitry Andric bool isSource(const T *) { return false; } 230606c3fb27SDimitry Andric }; 230706c3fb27SDimitry Andric template <> class OMPDoacrossKind<OMPDependClause> { 230806c3fb27SDimitry Andric public: isSink(const OMPDependClause * C)230906c3fb27SDimitry Andric bool isSink(const OMPDependClause *C) { 231006c3fb27SDimitry Andric return C->getDependencyKind() == OMPC_DEPEND_sink; 231106c3fb27SDimitry Andric } isSource(const OMPDependClause * C)231206c3fb27SDimitry Andric bool isSource(const OMPDependClause *C) { 231306c3fb27SDimitry Andric return C->getDependencyKind() == OMPC_DEPEND_source; 231406c3fb27SDimitry Andric } 231506c3fb27SDimitry Andric }; 231606c3fb27SDimitry Andric template <> class OMPDoacrossKind<OMPDoacrossClause> { 231706c3fb27SDimitry Andric public: isSource(const OMPDoacrossClause * C)231806c3fb27SDimitry Andric bool isSource(const OMPDoacrossClause *C) { 231906c3fb27SDimitry Andric return C->getDependenceType() == OMPC_DOACROSS_source || 232006c3fb27SDimitry Andric C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration; 232106c3fb27SDimitry Andric } isSink(const OMPDoacrossClause * C)232206c3fb27SDimitry Andric bool isSink(const OMPDoacrossClause *C) { 232306c3fb27SDimitry Andric return C->getDependenceType() == OMPC_DOACROSS_sink || 232406c3fb27SDimitry Andric C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration; 232506c3fb27SDimitry Andric } 232606c3fb27SDimitry Andric }; 232706c3fb27SDimitry Andric } // namespace 23280b57cec5SDimitry Andric } // namespace clang 23290b57cec5SDimitry Andric 23300b57cec5SDimitry Andric #endif 2331