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 
9490b57cec5SDimitry Andric   /// Struct with the values to be passed to the static runtime function
9500b57cec5SDimitry Andric   struct StaticRTInput {
9510b57cec5SDimitry Andric     /// Size of the iteration variable in bits.
9520b57cec5SDimitry Andric     unsigned IVSize = 0;
9530b57cec5SDimitry Andric     /// Sign of the iteration variable.
9540b57cec5SDimitry Andric     bool IVSigned = false;
9550b57cec5SDimitry Andric     /// true if loop is ordered, false otherwise.
9560b57cec5SDimitry Andric     bool Ordered = false;
9570b57cec5SDimitry Andric     /// Address of the output variable in which the flag of the last iteration
9580b57cec5SDimitry Andric     /// is returned.
9590b57cec5SDimitry Andric     Address IL = Address::invalid();
9600b57cec5SDimitry Andric     /// Address of the output variable in which the lower iteration number is
9610b57cec5SDimitry Andric     /// returned.
9620b57cec5SDimitry Andric     Address LB = Address::invalid();
9630b57cec5SDimitry Andric     /// Address of the output variable in which the upper iteration number is
9640b57cec5SDimitry Andric     /// returned.
9650b57cec5SDimitry Andric     Address UB = Address::invalid();
9660b57cec5SDimitry Andric     /// Address of the output variable in which the stride value is returned
9670b57cec5SDimitry Andric     /// necessary to generated the static_chunked scheduled loop.
9680b57cec5SDimitry Andric     Address ST = Address::invalid();
9690b57cec5SDimitry Andric     /// Value of the chunk for the static_chunked scheduled loop. For the
9700b57cec5SDimitry Andric     /// default (nullptr) value, the chunk 1 will be used.
9710b57cec5SDimitry Andric     llvm::Value *Chunk = nullptr;
9720b57cec5SDimitry Andric     StaticRTInput(unsigned IVSize, bool IVSigned, bool Ordered, Address IL,
9730b57cec5SDimitry Andric                   Address LB, Address UB, Address ST,
9740b57cec5SDimitry Andric                   llvm::Value *Chunk = nullptr)
IVSizeStaticRTInput9750b57cec5SDimitry Andric         : IVSize(IVSize), IVSigned(IVSigned), Ordered(Ordered), IL(IL), LB(LB),
9760b57cec5SDimitry Andric           UB(UB), ST(ST), Chunk(Chunk) {}
9770b57cec5SDimitry Andric   };
9780b57cec5SDimitry Andric   /// Call the appropriate runtime routine to initialize it before start
9790b57cec5SDimitry Andric   /// of loop.
9800b57cec5SDimitry Andric   ///
9810b57cec5SDimitry Andric   /// This is used only in case of static schedule, when the user did not
9820b57cec5SDimitry Andric   /// specify a ordered clause on the loop construct.
9830b57cec5SDimitry Andric   /// Depending on the loop schedule, it is necessary to call some runtime
9840b57cec5SDimitry Andric   /// routine before start of the OpenMP loop to get the loop upper / lower
9850b57cec5SDimitry Andric   /// bounds LB and UB and stride ST.
9860b57cec5SDimitry Andric   ///
9870b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
9880b57cec5SDimitry Andric   /// \param Loc Clang source location.
9890b57cec5SDimitry Andric   /// \param DKind Kind of the directive.
9900b57cec5SDimitry Andric   /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
9910b57cec5SDimitry Andric   /// \param Values Input arguments for the construct.
9920b57cec5SDimitry Andric   ///
9930b57cec5SDimitry Andric   virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
9940b57cec5SDimitry Andric                                  OpenMPDirectiveKind DKind,
9950b57cec5SDimitry Andric                                  const OpenMPScheduleTy &ScheduleKind,
9960b57cec5SDimitry Andric                                  const StaticRTInput &Values);
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric   ///
9990b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
10000b57cec5SDimitry Andric   /// \param Loc Clang source location.
10010b57cec5SDimitry Andric   /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause.
10020b57cec5SDimitry Andric   /// \param Values Input arguments for the construct.
10030b57cec5SDimitry Andric   ///
10040b57cec5SDimitry Andric   virtual void emitDistributeStaticInit(CodeGenFunction &CGF,
10050b57cec5SDimitry Andric                                         SourceLocation Loc,
10060b57cec5SDimitry Andric                                         OpenMPDistScheduleClauseKind SchedKind,
10070b57cec5SDimitry Andric                                         const StaticRTInput &Values);
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   /// Call the appropriate runtime routine to notify that we finished
10100b57cec5SDimitry Andric   /// iteration of the ordered loop with the dynamic scheduling.
10110b57cec5SDimitry Andric   ///
10120b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
10130b57cec5SDimitry Andric   /// \param Loc Clang source location.
10140b57cec5SDimitry Andric   /// \param IVSize Size of the iteration variable in bits.
10150b57cec5SDimitry Andric   /// \param IVSigned Sign of the iteration variable.
10160b57cec5SDimitry Andric   ///
10170b57cec5SDimitry Andric   virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF,
10180b57cec5SDimitry Andric                                           SourceLocation Loc, unsigned IVSize,
10190b57cec5SDimitry Andric                                           bool IVSigned);
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric   /// Call the appropriate runtime routine to notify that we finished
10220b57cec5SDimitry Andric   /// all the work with current loop.
10230b57cec5SDimitry Andric   ///
10240b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
10250b57cec5SDimitry Andric   /// \param Loc Clang source location.
10260b57cec5SDimitry Andric   /// \param DKind Kind of the directive for which the static finish is emitted.
10270b57cec5SDimitry Andric   ///
10280b57cec5SDimitry Andric   virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc,
10290b57cec5SDimitry Andric                                    OpenMPDirectiveKind DKind);
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric   /// Call __kmpc_dispatch_next(
10320b57cec5SDimitry Andric   ///          ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
10330b57cec5SDimitry Andric   ///          kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
10340b57cec5SDimitry Andric   ///          kmp_int[32|64] *p_stride);
10350b57cec5SDimitry Andric   /// \param IVSize Size of the iteration variable in bits.
10360b57cec5SDimitry Andric   /// \param IVSigned Sign of the iteration variable.
10370b57cec5SDimitry Andric   /// \param IL Address of the output variable in which the flag of the
10380b57cec5SDimitry Andric   /// last iteration is returned.
10390b57cec5SDimitry Andric   /// \param LB Address of the output variable in which the lower iteration
10400b57cec5SDimitry Andric   /// number is returned.
10410b57cec5SDimitry Andric   /// \param UB Address of the output variable in which the upper iteration
10420b57cec5SDimitry Andric   /// number is returned.
10430b57cec5SDimitry Andric   /// \param ST Address of the output variable in which the stride value is
10440b57cec5SDimitry Andric   /// returned.
10450b57cec5SDimitry Andric   virtual llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
10460b57cec5SDimitry Andric                                    unsigned IVSize, bool IVSigned,
10470b57cec5SDimitry Andric                                    Address IL, Address LB,
10480b57cec5SDimitry Andric                                    Address UB, Address ST);
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
10510b57cec5SDimitry Andric   /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
10520b57cec5SDimitry Andric   /// clause.
10530b57cec5SDimitry Andric   /// \param NumThreads An integer value of threads.
10540b57cec5SDimitry Andric   virtual void emitNumThreadsClause(CodeGenFunction &CGF,
10550b57cec5SDimitry Andric                                     llvm::Value *NumThreads,
10560b57cec5SDimitry Andric                                     SourceLocation Loc);
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric   /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
10590b57cec5SDimitry Andric   /// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
10600b57cec5SDimitry Andric   virtual void emitProcBindClause(CodeGenFunction &CGF,
1061480093f4SDimitry Andric                                   llvm::omp::ProcBindKind ProcBind,
10620b57cec5SDimitry Andric                                   SourceLocation Loc);
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric   /// Returns address of the threadprivate variable for the current
10650b57cec5SDimitry Andric   /// thread.
10660b57cec5SDimitry Andric   /// \param VD Threadprivate variable.
10670b57cec5SDimitry Andric   /// \param VDAddr Address of the global variable \a VD.
10680b57cec5SDimitry Andric   /// \param Loc Location of the reference to threadprivate var.
10690b57cec5SDimitry Andric   /// \return Address of the threadprivate variable for the current thread.
10700b57cec5SDimitry Andric   virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF,
10710b57cec5SDimitry Andric                                          const VarDecl *VD,
10720b57cec5SDimitry Andric                                          Address VDAddr,
10730b57cec5SDimitry Andric                                          SourceLocation Loc);
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric   /// Returns the address of the variable marked as declare target with link
10760b57cec5SDimitry Andric   /// clause OR as declare target with to clause and unified memory.
10770b57cec5SDimitry Andric   virtual Address getAddrOfDeclareTargetVar(const VarDecl *VD);
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric   /// Emit a code for initialization of threadprivate variable. It emits
10800b57cec5SDimitry Andric   /// a call to runtime library which adds initial value to the newly created
10810b57cec5SDimitry Andric   /// threadprivate variable (if it is not constant) and registers destructor
10820b57cec5SDimitry Andric   /// for the variable (if any).
10830b57cec5SDimitry Andric   /// \param VD Threadprivate variable.
10840b57cec5SDimitry Andric   /// \param VDAddr Address of the global variable \a VD.
10850b57cec5SDimitry Andric   /// \param Loc Location of threadprivate declaration.
10860b57cec5SDimitry Andric   /// \param PerformInit true if initialization expression is not constant.
10870b57cec5SDimitry Andric   virtual llvm::Function *
10880b57cec5SDimitry Andric   emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
10890b57cec5SDimitry Andric                                  SourceLocation Loc, bool PerformInit,
10900b57cec5SDimitry Andric                                  CodeGenFunction *CGF = nullptr);
10910b57cec5SDimitry Andric 
10925f757f3fSDimitry Andric   /// Emit code for handling declare target functions in the runtime.
10935f757f3fSDimitry Andric   /// \param FD Declare target function.
10945f757f3fSDimitry Andric   /// \param Addr Address of the global \a FD.
10950b57cec5SDimitry Andric   /// \param PerformInit true if initialization expression is not constant.
10965f757f3fSDimitry Andric   virtual void emitDeclareTargetFunction(const FunctionDecl *FD,
10975f757f3fSDimitry Andric                                          llvm::GlobalValue *GV);
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   /// Creates artificial threadprivate variable with name \p Name and type \p
11000b57cec5SDimitry Andric   /// VarType.
11010b57cec5SDimitry Andric   /// \param VarType Type of the artificial threadprivate variable.
11020b57cec5SDimitry Andric   /// \param Name Name of the artificial threadprivate variable.
11030b57cec5SDimitry Andric   virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
11040b57cec5SDimitry Andric                                                    QualType VarType,
11050b57cec5SDimitry Andric                                                    StringRef Name);
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   /// Emit flush of the variables specified in 'omp flush' directive.
11080b57cec5SDimitry Andric   /// \param Vars List of variables to flush.
11090b57cec5SDimitry Andric   virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
11105ffd83dbSDimitry Andric                          SourceLocation Loc, llvm::AtomicOrdering AO);
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric   /// Emit task region for the task directive. The task region is
11130b57cec5SDimitry Andric   /// emitted in several steps:
11140b57cec5SDimitry Andric   /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
11150b57cec5SDimitry Andric   /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
11160b57cec5SDimitry Andric   /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
11170b57cec5SDimitry Andric   /// function:
11180b57cec5SDimitry Andric   /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
11190b57cec5SDimitry Andric   ///   TaskFunction(gtid, tt->part_id, tt->shareds);
11200b57cec5SDimitry Andric   ///   return 0;
11210b57cec5SDimitry Andric   /// }
11220b57cec5SDimitry Andric   /// 2. Copy a list of shared variables to field shareds of the resulting
11230b57cec5SDimitry Andric   /// structure kmp_task_t returned by the previous call (if any).
11240b57cec5SDimitry Andric   /// 3. Copy a pointer to destructions function to field destructions of the
11250b57cec5SDimitry Andric   /// resulting structure kmp_task_t.
11260b57cec5SDimitry Andric   /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
11270b57cec5SDimitry Andric   /// kmp_task_t *new_task), where new_task is a resulting structure from
11280b57cec5SDimitry Andric   /// previous items.
11290b57cec5SDimitry Andric   /// \param D Current task directive.
11300b57cec5SDimitry Andric   /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
11310b57cec5SDimitry Andric   /// /*part_id*/, captured_struct */*__context*/);
11320b57cec5SDimitry Andric   /// \param SharedsTy A type which contains references the shared variables.
11330b57cec5SDimitry Andric   /// \param Shareds Context with the list of shared variables from the \p
11340b57cec5SDimitry Andric   /// TaskFunction.
11350b57cec5SDimitry Andric   /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
11360b57cec5SDimitry Andric   /// otherwise.
11370b57cec5SDimitry Andric   /// \param Data Additional data for task generation like tiednsee, final
11380b57cec5SDimitry Andric   /// state, list of privates etc.
11390b57cec5SDimitry Andric   virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11400b57cec5SDimitry Andric                             const OMPExecutableDirective &D,
11410b57cec5SDimitry Andric                             llvm::Function *TaskFunction, QualType SharedsTy,
11420b57cec5SDimitry Andric                             Address Shareds, const Expr *IfCond,
11430b57cec5SDimitry Andric                             const OMPTaskDataTy &Data);
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric   /// Emit task region for the taskloop directive. The taskloop region is
11460b57cec5SDimitry Andric   /// emitted in several steps:
11470b57cec5SDimitry Andric   /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
11480b57cec5SDimitry Andric   /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
11490b57cec5SDimitry Andric   /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
11500b57cec5SDimitry Andric   /// function:
11510b57cec5SDimitry Andric   /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
11520b57cec5SDimitry Andric   ///   TaskFunction(gtid, tt->part_id, tt->shareds);
11530b57cec5SDimitry Andric   ///   return 0;
11540b57cec5SDimitry Andric   /// }
11550b57cec5SDimitry Andric   /// 2. Copy a list of shared variables to field shareds of the resulting
11560b57cec5SDimitry Andric   /// structure kmp_task_t returned by the previous call (if any).
11570b57cec5SDimitry Andric   /// 3. Copy a pointer to destructions function to field destructions of the
11580b57cec5SDimitry Andric   /// resulting structure kmp_task_t.
11590b57cec5SDimitry Andric   /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t
11600b57cec5SDimitry Andric   /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int
11610b57cec5SDimitry Andric   /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task
11620b57cec5SDimitry Andric   /// is a resulting structure from
11630b57cec5SDimitry Andric   /// previous items.
11640b57cec5SDimitry Andric   /// \param D Current task directive.
11650b57cec5SDimitry Andric   /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
11660b57cec5SDimitry Andric   /// /*part_id*/, captured_struct */*__context*/);
11670b57cec5SDimitry Andric   /// \param SharedsTy A type which contains references the shared variables.
11680b57cec5SDimitry Andric   /// \param Shareds Context with the list of shared variables from the \p
11690b57cec5SDimitry Andric   /// TaskFunction.
11700b57cec5SDimitry Andric   /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
11710b57cec5SDimitry Andric   /// otherwise.
11720b57cec5SDimitry Andric   /// \param Data Additional data for task generation like tiednsee, final
11730b57cec5SDimitry Andric   /// state, list of privates etc.
11740b57cec5SDimitry Andric   virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
11750b57cec5SDimitry Andric                                 const OMPLoopDirective &D,
11760b57cec5SDimitry Andric                                 llvm::Function *TaskFunction,
11770b57cec5SDimitry Andric                                 QualType SharedsTy, Address Shareds,
11780b57cec5SDimitry Andric                                 const Expr *IfCond, const OMPTaskDataTy &Data);
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric   /// Emit code for the directive that does not require outlining.
11810b57cec5SDimitry Andric   ///
11820b57cec5SDimitry Andric   /// \param InnermostKind Kind of innermost directive (for simple directives it
11830b57cec5SDimitry Andric   /// is a directive itself, for combined - its innermost directive).
11840b57cec5SDimitry Andric   /// \param CodeGen Code generation sequence for the \a D directive.
11850b57cec5SDimitry Andric   /// \param HasCancel true if region has inner cancel directive, false
11860b57cec5SDimitry Andric   /// otherwise.
11870b57cec5SDimitry Andric   virtual void emitInlinedDirective(CodeGenFunction &CGF,
11880b57cec5SDimitry Andric                                     OpenMPDirectiveKind InnermostKind,
11890b57cec5SDimitry Andric                                     const RegionCodeGenTy &CodeGen,
11900b57cec5SDimitry Andric                                     bool HasCancel = false);
11910b57cec5SDimitry Andric 
11920b57cec5SDimitry Andric   /// Emits reduction function.
119306c3fb27SDimitry Andric   /// \param ReducerName Name of the function calling the reduction.
119481ad6265SDimitry Andric   /// \param ArgsElemType Array type containing pointers to reduction variables.
11950b57cec5SDimitry Andric   /// \param Privates List of private copies for original reduction arguments.
11960b57cec5SDimitry Andric   /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
11970b57cec5SDimitry Andric   /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
11980b57cec5SDimitry Andric   /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
11990b57cec5SDimitry Andric   /// or 'operator binop(LHS, RHS)'.
120006c3fb27SDimitry Andric   llvm::Function *emitReductionFunction(
120106c3fb27SDimitry Andric       StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType,
120206c3fb27SDimitry Andric       ArrayRef<const Expr *> Privates, ArrayRef<const Expr *> LHSExprs,
120306c3fb27SDimitry Andric       ArrayRef<const Expr *> RHSExprs, ArrayRef<const Expr *> ReductionOps);
12040b57cec5SDimitry Andric 
12050b57cec5SDimitry Andric   /// Emits single reduction combiner
12060b57cec5SDimitry Andric   void emitSingleReductionCombiner(CodeGenFunction &CGF,
12070b57cec5SDimitry Andric                                    const Expr *ReductionOp,
12080b57cec5SDimitry Andric                                    const Expr *PrivateRef,
12090b57cec5SDimitry Andric                                    const DeclRefExpr *LHS,
12100b57cec5SDimitry Andric                                    const DeclRefExpr *RHS);
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric   struct ReductionOptionsTy {
12130b57cec5SDimitry Andric     bool WithNowait;
12140b57cec5SDimitry Andric     bool SimpleReduction;
12150b57cec5SDimitry Andric     OpenMPDirectiveKind ReductionKind;
12160b57cec5SDimitry Andric   };
12170b57cec5SDimitry Andric   /// Emit a code for reduction clause. Next code should be emitted for
12180b57cec5SDimitry Andric   /// reduction:
12190b57cec5SDimitry Andric   /// \code
12200b57cec5SDimitry Andric   ///
12210b57cec5SDimitry Andric   /// static kmp_critical_name lock = { 0 };
12220b57cec5SDimitry Andric   ///
12230b57cec5SDimitry Andric   /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
12240b57cec5SDimitry Andric   ///  ...
12250b57cec5SDimitry Andric   ///  *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
12260b57cec5SDimitry Andric   ///  ...
12270b57cec5SDimitry Andric   /// }
12280b57cec5SDimitry Andric   ///
12290b57cec5SDimitry Andric   /// ...
12300b57cec5SDimitry Andric   /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
12310b57cec5SDimitry Andric   /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
12320b57cec5SDimitry Andric   /// RedList, reduce_func, &<lock>)) {
12330b57cec5SDimitry Andric   /// case 1:
12340b57cec5SDimitry Andric   ///  ...
12350b57cec5SDimitry Andric   ///  <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
12360b57cec5SDimitry Andric   ///  ...
12370b57cec5SDimitry Andric   /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
12380b57cec5SDimitry Andric   /// break;
12390b57cec5SDimitry Andric   /// case 2:
12400b57cec5SDimitry Andric   ///  ...
12410b57cec5SDimitry Andric   ///  Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
12420b57cec5SDimitry Andric   ///  ...
12430b57cec5SDimitry Andric   /// break;
12440b57cec5SDimitry Andric   /// default:;
12450b57cec5SDimitry Andric   /// }
12460b57cec5SDimitry Andric   /// \endcode
12470b57cec5SDimitry Andric   ///
12480b57cec5SDimitry Andric   /// \param Privates List of private copies for original reduction arguments.
12490b57cec5SDimitry Andric   /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
12500b57cec5SDimitry Andric   /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
12510b57cec5SDimitry Andric   /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
12520b57cec5SDimitry Andric   /// or 'operator binop(LHS, RHS)'.
12530b57cec5SDimitry Andric   /// \param Options List of options for reduction codegen:
12540b57cec5SDimitry Andric   ///     WithNowait true if parent directive has also nowait clause, false
12550b57cec5SDimitry Andric   ///     otherwise.
12560b57cec5SDimitry Andric   ///     SimpleReduction Emit reduction operation only. Used for omp simd
12570b57cec5SDimitry Andric   ///     directive on the host.
12580b57cec5SDimitry Andric   ///     ReductionKind The kind of reduction to perform.
12590b57cec5SDimitry Andric   virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
12600b57cec5SDimitry Andric                              ArrayRef<const Expr *> Privates,
12610b57cec5SDimitry Andric                              ArrayRef<const Expr *> LHSExprs,
12620b57cec5SDimitry Andric                              ArrayRef<const Expr *> RHSExprs,
12630b57cec5SDimitry Andric                              ArrayRef<const Expr *> ReductionOps,
12640b57cec5SDimitry Andric                              ReductionOptionsTy Options);
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric   /// Emit a code for initialization of task reduction clause. Next code
12670b57cec5SDimitry Andric   /// should be emitted for reduction:
12680b57cec5SDimitry Andric   /// \code
12690b57cec5SDimitry Andric   ///
12705ffd83dbSDimitry Andric   /// _taskred_item_t red_data[n];
12710b57cec5SDimitry Andric   /// ...
12725ffd83dbSDimitry Andric   /// red_data[i].shar = &shareds[i];
12735ffd83dbSDimitry Andric   /// red_data[i].orig = &origs[i];
12740b57cec5SDimitry Andric   /// red_data[i].size = sizeof(origs[i]);
12750b57cec5SDimitry Andric   /// red_data[i].f_init = (void*)RedInit<i>;
12760b57cec5SDimitry Andric   /// red_data[i].f_fini = (void*)RedDest<i>;
12770b57cec5SDimitry Andric   /// red_data[i].f_comb = (void*)RedOp<i>;
12780b57cec5SDimitry Andric   /// red_data[i].flags = <Flag_i>;
12790b57cec5SDimitry Andric   /// ...
12805ffd83dbSDimitry Andric   /// void* tg1 = __kmpc_taskred_init(gtid, n, red_data);
12810b57cec5SDimitry Andric   /// \endcode
12825ffd83dbSDimitry Andric   /// For reduction clause with task modifier it emits the next call:
12835ffd83dbSDimitry Andric   /// \code
12840b57cec5SDimitry Andric   ///
12855ffd83dbSDimitry Andric   /// _taskred_item_t red_data[n];
12865ffd83dbSDimitry Andric   /// ...
12875ffd83dbSDimitry Andric   /// red_data[i].shar = &shareds[i];
12885ffd83dbSDimitry Andric   /// red_data[i].orig = &origs[i];
12895ffd83dbSDimitry Andric   /// red_data[i].size = sizeof(origs[i]);
12905ffd83dbSDimitry Andric   /// red_data[i].f_init = (void*)RedInit<i>;
12915ffd83dbSDimitry Andric   /// red_data[i].f_fini = (void*)RedDest<i>;
12925ffd83dbSDimitry Andric   /// red_data[i].f_comb = (void*)RedOp<i>;
12935ffd83dbSDimitry Andric   /// red_data[i].flags = <Flag_i>;
12945ffd83dbSDimitry Andric   /// ...
12955ffd83dbSDimitry Andric   /// void* tg1 = __kmpc_taskred_modifier_init(loc, gtid, is_worksharing, n,
12965ffd83dbSDimitry Andric   /// red_data);
12975ffd83dbSDimitry Andric   /// \endcode
12980b57cec5SDimitry Andric   /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations.
12990b57cec5SDimitry Andric   /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations.
13000b57cec5SDimitry Andric   /// \param Data Additional data for task generation like tiedness, final
13010b57cec5SDimitry Andric   /// state, list of privates, reductions etc.
13020b57cec5SDimitry Andric   virtual llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF,
13030b57cec5SDimitry Andric                                              SourceLocation Loc,
13040b57cec5SDimitry Andric                                              ArrayRef<const Expr *> LHSExprs,
13050b57cec5SDimitry Andric                                              ArrayRef<const Expr *> RHSExprs,
13060b57cec5SDimitry Andric                                              const OMPTaskDataTy &Data);
13070b57cec5SDimitry Andric 
13085ffd83dbSDimitry Andric   /// Emits the following code for reduction clause with task modifier:
13095ffd83dbSDimitry Andric   /// \code
13105ffd83dbSDimitry Andric   /// __kmpc_task_reduction_modifier_fini(loc, gtid, is_worksharing);
13115ffd83dbSDimitry Andric   /// \endcode
13125ffd83dbSDimitry Andric   virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc,
13135ffd83dbSDimitry Andric                                      bool IsWorksharingReduction);
13145ffd83dbSDimitry Andric 
13150b57cec5SDimitry Andric   /// Required to resolve existing problems in the runtime. Emits threadprivate
13160b57cec5SDimitry Andric   /// variables to store the size of the VLAs/array sections for
13175ffd83dbSDimitry Andric   /// initializer/combiner/finalizer functions.
13180b57cec5SDimitry Andric   /// \param RCG Allows to reuse an existing data for the reductions.
13190b57cec5SDimitry Andric   /// \param N Reduction item for which fixups must be emitted.
13200b57cec5SDimitry Andric   virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc,
13210b57cec5SDimitry Andric                                        ReductionCodeGen &RCG, unsigned N);
13220b57cec5SDimitry Andric 
13230b57cec5SDimitry Andric   /// Get the address of `void *` type of the privatue copy of the reduction
13240b57cec5SDimitry Andric   /// item specified by the \p SharedLVal.
13250b57cec5SDimitry Andric   /// \param ReductionsPtr Pointer to the reduction data returned by the
13260b57cec5SDimitry Andric   /// emitTaskReductionInit function.
13270b57cec5SDimitry Andric   /// \param SharedLVal Address of the original reduction item.
13280b57cec5SDimitry Andric   virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc,
13290b57cec5SDimitry Andric                                        llvm::Value *ReductionsPtr,
13300b57cec5SDimitry Andric                                        LValue SharedLVal);
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric   /// Emit code for 'taskwait' directive.
1333349cc55cSDimitry Andric   virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
1334349cc55cSDimitry Andric                                 const OMPTaskDataTy &Data);
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   /// Emit code for 'cancellation point' construct.
13370b57cec5SDimitry Andric   /// \param CancelRegion Region kind for which the cancellation point must be
13380b57cec5SDimitry Andric   /// emitted.
13390b57cec5SDimitry Andric   ///
13400b57cec5SDimitry Andric   virtual void emitCancellationPointCall(CodeGenFunction &CGF,
13410b57cec5SDimitry Andric                                          SourceLocation Loc,
13420b57cec5SDimitry Andric                                          OpenMPDirectiveKind CancelRegion);
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric   /// Emit code for 'cancel' construct.
13450b57cec5SDimitry Andric   /// \param IfCond Condition in the associated 'if' clause, if it was
13460b57cec5SDimitry Andric   /// specified, nullptr otherwise.
13470b57cec5SDimitry Andric   /// \param CancelRegion Region kind for which the cancel must be emitted.
13480b57cec5SDimitry Andric   ///
13490b57cec5SDimitry Andric   virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
13500b57cec5SDimitry Andric                               const Expr *IfCond,
13510b57cec5SDimitry Andric                               OpenMPDirectiveKind CancelRegion);
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric   /// Emit outilined function for 'target' directive.
13540b57cec5SDimitry Andric   /// \param D Directive to emit.
13550b57cec5SDimitry Andric   /// \param ParentName Name of the function that encloses the target region.
13560b57cec5SDimitry Andric   /// \param OutlinedFn Outlined function value to be defined by this call.
13570b57cec5SDimitry Andric   /// \param OutlinedFnID Outlined function ID value to be defined by this call.
13580b57cec5SDimitry Andric   /// \param IsOffloadEntry True if the outlined function is an offload entry.
13590b57cec5SDimitry Andric   /// \param CodeGen Code generation sequence for the \a D directive.
13600b57cec5SDimitry Andric   /// An outlined function may not be an entry if, e.g. the if clause always
13610b57cec5SDimitry Andric   /// evaluates to false.
13620b57cec5SDimitry Andric   virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
13630b57cec5SDimitry Andric                                           StringRef ParentName,
13640b57cec5SDimitry Andric                                           llvm::Function *&OutlinedFn,
13650b57cec5SDimitry Andric                                           llvm::Constant *&OutlinedFnID,
13660b57cec5SDimitry Andric                                           bool IsOffloadEntry,
13670b57cec5SDimitry Andric                                           const RegionCodeGenTy &CodeGen);
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric   /// Emit the target offloading code associated with \a D. The emitted
13700b57cec5SDimitry Andric   /// code attempts offloading the execution to the device, an the event of
13710b57cec5SDimitry Andric   /// a failure it executes the host version outlined in \a OutlinedFn.
13720b57cec5SDimitry Andric   /// \param D Directive to emit.
13730b57cec5SDimitry Andric   /// \param OutlinedFn Host version of the code to be offloaded.
13740b57cec5SDimitry Andric   /// \param OutlinedFnID ID of host version of the code to be offloaded.
13750b57cec5SDimitry Andric   /// \param IfCond Expression evaluated in if clause associated with the target
13760b57cec5SDimitry Andric   /// directive, or null if no if clause is used.
13770b57cec5SDimitry Andric   /// \param Device Expression evaluated in device clause associated with the
13785ffd83dbSDimitry Andric   /// target directive, or null if no device clause is used and device modifier.
1379a7dea167SDimitry Andric   /// \param SizeEmitter Callback to emit number of iterations for loop-based
1380a7dea167SDimitry Andric   /// directives.
13815ffd83dbSDimitry Andric   virtual void emitTargetCall(
13825ffd83dbSDimitry Andric       CodeGenFunction &CGF, const OMPExecutableDirective &D,
13835ffd83dbSDimitry Andric       llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
13845ffd83dbSDimitry Andric       llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
1385a7dea167SDimitry Andric       llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
1386a7dea167SDimitry Andric                                        const OMPLoopDirective &D)>
1387a7dea167SDimitry Andric           SizeEmitter);
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   /// Emit the target regions enclosed in \a GD function definition or
13900b57cec5SDimitry Andric   /// the function itself in case it is a valid device function. Returns true if
13910b57cec5SDimitry Andric   /// \a GD was dealt with successfully.
13920b57cec5SDimitry Andric   /// \param GD Function to scan.
13930b57cec5SDimitry Andric   virtual bool emitTargetFunctions(GlobalDecl GD);
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric   /// Emit the global variable if it is a valid device global variable.
13960b57cec5SDimitry Andric   /// Returns true if \a GD was dealt with successfully.
13970b57cec5SDimitry Andric   /// \param GD Variable declaration to emit.
13980b57cec5SDimitry Andric   virtual bool emitTargetGlobalVariable(GlobalDecl GD);
13990b57cec5SDimitry Andric 
14000b57cec5SDimitry Andric   /// Checks if the provided global decl \a GD is a declare target variable and
14010b57cec5SDimitry Andric   /// registers it when emitting code for the host.
14020b57cec5SDimitry Andric   virtual void registerTargetGlobalVariable(const VarDecl *VD,
14030b57cec5SDimitry Andric                                             llvm::Constant *Addr);
14040b57cec5SDimitry Andric 
14050b57cec5SDimitry Andric   /// Emit the global \a GD if it is meaningful for the target. Returns
14060b57cec5SDimitry Andric   /// if it was emitted successfully.
14070b57cec5SDimitry Andric   /// \param GD Global to scan.
14080b57cec5SDimitry Andric   virtual bool emitTargetGlobal(GlobalDecl GD);
14090b57cec5SDimitry Andric 
14100b57cec5SDimitry Andric   /// Creates and returns a registration function for when at least one
14110b57cec5SDimitry Andric   /// requires directives was used in the current module.
14120b57cec5SDimitry Andric   llvm::Function *emitRequiresDirectiveRegFun();
14130b57cec5SDimitry Andric 
1414a7dea167SDimitry Andric   /// Creates all the offload entries in the current compilation unit
1415a7dea167SDimitry Andric   /// along with the associated metadata.
1416a7dea167SDimitry Andric   void createOffloadEntriesAndInfoMetadata();
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric   /// Emits code for teams call of the \a OutlinedFn with
14190b57cec5SDimitry Andric   /// variables captured in a record which address is stored in \a
14200b57cec5SDimitry Andric   /// CapturedStruct.
14210b57cec5SDimitry Andric   /// \param OutlinedFn Outlined function to be run by team masters. Type of
14220b57cec5SDimitry Andric   /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
14230b57cec5SDimitry Andric   /// \param CapturedVars A pointer to the record with the references to
14240b57cec5SDimitry Andric   /// variables used in \a OutlinedFn function.
14250b57cec5SDimitry Andric   ///
14260b57cec5SDimitry Andric   virtual void emitTeamsCall(CodeGenFunction &CGF,
14270b57cec5SDimitry Andric                              const OMPExecutableDirective &D,
14280b57cec5SDimitry Andric                              SourceLocation Loc, llvm::Function *OutlinedFn,
14290b57cec5SDimitry Andric                              ArrayRef<llvm::Value *> CapturedVars);
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric   /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
14320b57cec5SDimitry Andric   /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code
14330b57cec5SDimitry Andric   /// for num_teams clause.
14340b57cec5SDimitry Andric   /// \param NumTeams An integer expression of teams.
14350b57cec5SDimitry Andric   /// \param ThreadLimit An integer expression of threads.
14360b57cec5SDimitry Andric   virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
14370b57cec5SDimitry Andric                                   const Expr *ThreadLimit, SourceLocation Loc);
14380b57cec5SDimitry Andric 
14395f757f3fSDimitry Andric   /// Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32
14405f757f3fSDimitry Andric   /// global_tid, kmp_int32 thread_limit) to generate code for
14415f757f3fSDimitry Andric   /// thread_limit clause on target directive
14425f757f3fSDimitry Andric   /// \param ThreadLimit An integer expression of threads.
14435f757f3fSDimitry Andric   virtual void emitThreadLimitClause(CodeGenFunction &CGF,
14445f757f3fSDimitry Andric                                      const Expr *ThreadLimit,
14455f757f3fSDimitry Andric                                      SourceLocation Loc);
14465f757f3fSDimitry Andric 
14470b57cec5SDimitry Andric   /// Struct that keeps all the relevant information that should be kept
14480b57cec5SDimitry Andric   /// throughout a 'target data' region.
1449bdd1243dSDimitry Andric   class TargetDataInfo : public llvm::OpenMPIRBuilder::TargetDataInfo {
14500b57cec5SDimitry Andric   public:
TargetDataInfo()1451bdd1243dSDimitry Andric     explicit TargetDataInfo() : llvm::OpenMPIRBuilder::TargetDataInfo() {}
TargetDataInfo(bool RequiresDevicePointerInfo,bool SeparateBeginEndCalls)1452bdd1243dSDimitry Andric     explicit TargetDataInfo(bool RequiresDevicePointerInfo,
1453bdd1243dSDimitry Andric                             bool SeparateBeginEndCalls)
1454bdd1243dSDimitry Andric         : llvm::OpenMPIRBuilder::TargetDataInfo(RequiresDevicePointerInfo,
1455bdd1243dSDimitry Andric                                                 SeparateBeginEndCalls) {}
145606c3fb27SDimitry Andric     /// Map between the a declaration of a capture and the corresponding new
145706c3fb27SDimitry Andric     /// llvm address where the runtime returns the device pointers.
145806c3fb27SDimitry Andric     llvm::DenseMap<const ValueDecl *, llvm::Value *> CaptureDeviceAddrMap;
14590b57cec5SDimitry Andric   };
14600b57cec5SDimitry Andric 
14610b57cec5SDimitry Andric   /// Emit the target data mapping code associated with \a D.
14620b57cec5SDimitry Andric   /// \param D Directive to emit.
14630b57cec5SDimitry Andric   /// \param IfCond Expression evaluated in if clause associated with the
14640b57cec5SDimitry Andric   /// target directive, or null if no device clause is used.
14650b57cec5SDimitry Andric   /// \param Device Expression evaluated in device clause associated with the
14660b57cec5SDimitry Andric   /// target directive, or null if no device clause is used.
14670b57cec5SDimitry Andric   /// \param Info A record used to store information that needs to be preserved
14680b57cec5SDimitry Andric   /// until the region is closed.
14690b57cec5SDimitry Andric   virtual void emitTargetDataCalls(CodeGenFunction &CGF,
14700b57cec5SDimitry Andric                                    const OMPExecutableDirective &D,
14710b57cec5SDimitry Andric                                    const Expr *IfCond, const Expr *Device,
14720b57cec5SDimitry Andric                                    const RegionCodeGenTy &CodeGen,
1473bdd1243dSDimitry Andric                                    CGOpenMPRuntime::TargetDataInfo &Info);
14740b57cec5SDimitry Andric 
14750b57cec5SDimitry Andric   /// Emit the data mapping/movement code associated with the directive
14760b57cec5SDimitry Andric   /// \a D that should be of the form 'target [{enter|exit} data | update]'.
14770b57cec5SDimitry Andric   /// \param D Directive to emit.
14780b57cec5SDimitry Andric   /// \param IfCond Expression evaluated in if clause associated with the target
14790b57cec5SDimitry Andric   /// directive, or null if no if clause is used.
14800b57cec5SDimitry Andric   /// \param Device Expression evaluated in device clause associated with the
14810b57cec5SDimitry Andric   /// target directive, or null if no device clause is used.
14820b57cec5SDimitry Andric   virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF,
14830b57cec5SDimitry Andric                                             const OMPExecutableDirective &D,
14840b57cec5SDimitry Andric                                             const Expr *IfCond,
14850b57cec5SDimitry Andric                                             const Expr *Device);
14860b57cec5SDimitry Andric 
14870b57cec5SDimitry Andric   /// Marks function \a Fn with properly mangled versions of vector functions.
14880b57cec5SDimitry Andric   /// \param FD Function marked as 'declare simd'.
14890b57cec5SDimitry Andric   /// \param Fn LLVM function that must be marked with 'declare simd'
14900b57cec5SDimitry Andric   /// attributes.
14910b57cec5SDimitry Andric   virtual void emitDeclareSimdFunction(const FunctionDecl *FD,
14920b57cec5SDimitry Andric                                        llvm::Function *Fn);
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric   /// Emit initialization for doacross loop nesting support.
14950b57cec5SDimitry Andric   /// \param D Loop-based construct used in doacross nesting construct.
14960b57cec5SDimitry Andric   virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
14970b57cec5SDimitry Andric                                 ArrayRef<Expr *> NumIterations);
14980b57cec5SDimitry Andric 
14990b57cec5SDimitry Andric   /// Emit code for doacross ordered directive with 'depend' clause.
15000b57cec5SDimitry Andric   /// \param C 'depend' clause with 'sink|source' dependency kind.
15010b57cec5SDimitry Andric   virtual void emitDoacrossOrdered(CodeGenFunction &CGF,
15020b57cec5SDimitry Andric                                    const OMPDependClause *C);
15030b57cec5SDimitry Andric 
150406c3fb27SDimitry Andric   /// Emit code for doacross ordered directive with 'doacross' clause.
150506c3fb27SDimitry Andric   /// \param C 'doacross' clause with 'sink|source' dependence type.
150606c3fb27SDimitry Andric   virtual void emitDoacrossOrdered(CodeGenFunction &CGF,
150706c3fb27SDimitry Andric                                    const OMPDoacrossClause *C);
150806c3fb27SDimitry Andric 
15090b57cec5SDimitry Andric   /// Translates the native parameter of outlined function if this is required
15100b57cec5SDimitry Andric   /// for target.
15110b57cec5SDimitry Andric   /// \param FD Field decl from captured record for the parameter.
15120b57cec5SDimitry Andric   /// \param NativeParam Parameter itself.
translateParameter(const FieldDecl * FD,const VarDecl * NativeParam)15130b57cec5SDimitry Andric   virtual const VarDecl *translateParameter(const FieldDecl *FD,
15140b57cec5SDimitry Andric                                             const VarDecl *NativeParam) const {
15150b57cec5SDimitry Andric     return NativeParam;
15160b57cec5SDimitry Andric   }
15170b57cec5SDimitry Andric 
15180b57cec5SDimitry Andric   /// Gets the address of the native argument basing on the address of the
15190b57cec5SDimitry Andric   /// target-specific parameter.
15200b57cec5SDimitry Andric   /// \param NativeParam Parameter itself.
15210b57cec5SDimitry Andric   /// \param TargetParam Corresponding target-specific parameter.
15220b57cec5SDimitry Andric   virtual Address getParameterAddress(CodeGenFunction &CGF,
15230b57cec5SDimitry Andric                                       const VarDecl *NativeParam,
15240b57cec5SDimitry Andric                                       const VarDecl *TargetParam) const;
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric   /// Choose default schedule type and chunk value for the
15270b57cec5SDimitry Andric   /// dist_schedule clause.
getDefaultDistScheduleAndChunk(CodeGenFunction & CGF,const OMPLoopDirective & S,OpenMPDistScheduleClauseKind & ScheduleKind,llvm::Value * & Chunk)15280b57cec5SDimitry Andric   virtual void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF,
15290b57cec5SDimitry Andric       const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind,
15300b57cec5SDimitry Andric       llvm::Value *&Chunk) const {}
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric   /// Choose default schedule type and chunk value for the
15330b57cec5SDimitry Andric   /// schedule clause.
15340b57cec5SDimitry Andric   virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF,
15350b57cec5SDimitry Andric       const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind,
15360b57cec5SDimitry Andric       const Expr *&ChunkExpr) const;
15370b57cec5SDimitry Andric 
15380b57cec5SDimitry Andric   /// Emits call of the outlined function with the provided arguments,
15390b57cec5SDimitry Andric   /// translating these arguments to correct target-specific arguments.
15400b57cec5SDimitry Andric   virtual void
15410b57cec5SDimitry Andric   emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc,
15420b57cec5SDimitry Andric                            llvm::FunctionCallee OutlinedFn,
1543bdd1243dSDimitry Andric                            ArrayRef<llvm::Value *> Args = std::nullopt) const;
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric   /// Emits OpenMP-specific function prolog.
15460b57cec5SDimitry Andric   /// Required for device constructs.
15470b57cec5SDimitry Andric   virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D);
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric   /// Gets the OpenMP-specific address of the local variable.
15500b57cec5SDimitry Andric   virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF,
15510b57cec5SDimitry Andric                                             const VarDecl *VD);
15520b57cec5SDimitry Andric 
15530b57cec5SDimitry Andric   /// Marks the declaration as already emitted for the device code and returns
15540b57cec5SDimitry Andric   /// true, if it was marked already, and false, otherwise.
15550b57cec5SDimitry Andric   bool markAsGlobalTarget(GlobalDecl GD);
15560b57cec5SDimitry Andric 
15570b57cec5SDimitry Andric   /// Emit deferred declare target variables marked for deferred emission.
15580b57cec5SDimitry Andric   void emitDeferredTargetDecls() const;
15590b57cec5SDimitry Andric 
15600b57cec5SDimitry Andric   /// Adjust some parameters for the target-based directives, like addresses of
15610b57cec5SDimitry Andric   /// the variables captured by reference in lambdas.
15620b57cec5SDimitry Andric   virtual void
15630b57cec5SDimitry Andric   adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF,
15640b57cec5SDimitry Andric                                      const OMPExecutableDirective &D) const;
15650b57cec5SDimitry Andric 
15660b57cec5SDimitry Andric   /// Perform check on requires decl to ensure that target architecture
15670b57cec5SDimitry Andric   /// supports unified addressing
15685ffd83dbSDimitry Andric   virtual void processRequiresDirective(const OMPRequiresDecl *D);
15695ffd83dbSDimitry Andric 
15705ffd83dbSDimitry Andric   /// Gets default memory ordering as specified in requires directive.
15715ffd83dbSDimitry Andric   llvm::AtomicOrdering getDefaultMemoryOrdering() const;
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric   /// Checks if the variable has associated OMPAllocateDeclAttr attribute with
15740b57cec5SDimitry Andric   /// the predefined allocator and translates it into the corresponding address
15750b57cec5SDimitry Andric   /// space.
15760b57cec5SDimitry Andric   virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS);
15770b57cec5SDimitry Andric 
15780b57cec5SDimitry Andric   /// Return whether the unified_shared_memory has been specified.
15790b57cec5SDimitry Andric   bool hasRequiresUnifiedSharedMemory() const;
1580a7dea167SDimitry Andric 
1581480093f4SDimitry Andric   /// Checks if the \p VD variable is marked as nontemporal declaration in
1582480093f4SDimitry Andric   /// current context.
1583480093f4SDimitry Andric   bool isNontemporalDecl(const ValueDecl *VD) const;
1584480093f4SDimitry Andric 
15855ffd83dbSDimitry Andric   /// Create specialized alloca to handle lastprivate conditionals.
15865ffd83dbSDimitry Andric   Address emitLastprivateConditionalInit(CodeGenFunction &CGF,
15875ffd83dbSDimitry Andric                                          const VarDecl *VD);
1588480093f4SDimitry Andric 
1589480093f4SDimitry Andric   /// Checks if the provided \p LVal is lastprivate conditional and emits the
1590480093f4SDimitry Andric   /// code to update the value of the original variable.
1591480093f4SDimitry Andric   /// \code
1592480093f4SDimitry Andric   /// lastprivate(conditional: a)
1593480093f4SDimitry Andric   /// ...
1594480093f4SDimitry Andric   /// <type> a;
1595480093f4SDimitry Andric   /// lp_a = ...;
1596480093f4SDimitry Andric   /// #pragma omp critical(a)
1597480093f4SDimitry Andric   /// if (last_iv_a <= iv) {
1598480093f4SDimitry Andric   ///   last_iv_a = iv;
1599480093f4SDimitry Andric   ///   global_a = lp_a;
1600480093f4SDimitry Andric   /// }
1601480093f4SDimitry Andric   /// \endcode
1602480093f4SDimitry Andric   virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
1603480093f4SDimitry Andric                                                   const Expr *LHS);
1604480093f4SDimitry Andric 
16055ffd83dbSDimitry Andric   /// Checks if the lastprivate conditional was updated in inner region and
16065ffd83dbSDimitry Andric   /// writes the value.
16075ffd83dbSDimitry Andric   /// \code
16085ffd83dbSDimitry Andric   /// lastprivate(conditional: a)
16095ffd83dbSDimitry Andric   /// ...
16105ffd83dbSDimitry Andric   /// <type> a;bool Fired = false;
16115ffd83dbSDimitry Andric   /// #pragma omp ... shared(a)
16125ffd83dbSDimitry Andric   /// {
16135ffd83dbSDimitry Andric   ///   lp_a = ...;
16145ffd83dbSDimitry Andric   ///   Fired = true;
16155ffd83dbSDimitry Andric   /// }
16165ffd83dbSDimitry Andric   /// if (Fired) {
16175ffd83dbSDimitry Andric   ///   #pragma omp critical(a)
16185ffd83dbSDimitry Andric   ///   if (last_iv_a <= iv) {
16195ffd83dbSDimitry Andric   ///     last_iv_a = iv;
16205ffd83dbSDimitry Andric   ///     global_a = lp_a;
16215ffd83dbSDimitry Andric   ///   }
16225ffd83dbSDimitry Andric   ///   Fired = false;
16235ffd83dbSDimitry Andric   /// }
16245ffd83dbSDimitry Andric   /// \endcode
16255ffd83dbSDimitry Andric   virtual void checkAndEmitSharedLastprivateConditional(
16265ffd83dbSDimitry Andric       CodeGenFunction &CGF, const OMPExecutableDirective &D,
16275ffd83dbSDimitry Andric       const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls);
16285ffd83dbSDimitry Andric 
1629480093f4SDimitry Andric   /// Gets the address of the global copy used for lastprivate conditional
1630480093f4SDimitry Andric   /// update, if any.
1631480093f4SDimitry Andric   /// \param PrivLVal LValue for the private copy.
1632480093f4SDimitry Andric   /// \param VD Original lastprivate declaration.
1633480093f4SDimitry Andric   virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF,
1634480093f4SDimitry Andric                                                      LValue PrivLVal,
1635480093f4SDimitry Andric                                                      const VarDecl *VD,
1636480093f4SDimitry Andric                                                      SourceLocation Loc);
16375ffd83dbSDimitry Andric 
16385ffd83dbSDimitry Andric   /// Emits list of dependecies based on the provided data (array of
16395ffd83dbSDimitry Andric   /// dependence/expression pairs).
16405ffd83dbSDimitry Andric   /// \returns Pointer to the first element of the array casted to VoidPtr type.
16415ffd83dbSDimitry Andric   std::pair<llvm::Value *, Address>
16425ffd83dbSDimitry Andric   emitDependClause(CodeGenFunction &CGF,
16435ffd83dbSDimitry Andric                    ArrayRef<OMPTaskDataTy::DependData> Dependencies,
16445ffd83dbSDimitry Andric                    SourceLocation Loc);
16455ffd83dbSDimitry Andric 
16465ffd83dbSDimitry Andric   /// Emits list of dependecies based on the provided data (array of
16475ffd83dbSDimitry Andric   /// dependence/expression pairs) for depobj construct. In this case, the
16485ffd83dbSDimitry Andric   /// variable is allocated in dynamically. \returns Pointer to the first
16495ffd83dbSDimitry Andric   /// element of the array casted to VoidPtr type.
16505ffd83dbSDimitry Andric   Address emitDepobjDependClause(CodeGenFunction &CGF,
16515ffd83dbSDimitry Andric                                  const OMPTaskDataTy::DependData &Dependencies,
16525ffd83dbSDimitry Andric                                  SourceLocation Loc);
16535ffd83dbSDimitry Andric 
16545ffd83dbSDimitry Andric   /// Emits the code to destroy the dependency object provided in depobj
16555ffd83dbSDimitry Andric   /// directive.
16565ffd83dbSDimitry Andric   void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
16575ffd83dbSDimitry Andric                          SourceLocation Loc);
16585ffd83dbSDimitry Andric 
16595ffd83dbSDimitry Andric   /// Updates the dependency kind in the specified depobj object.
16605ffd83dbSDimitry Andric   /// \param DepobjLVal LValue for the main depobj object.
16615ffd83dbSDimitry Andric   /// \param NewDepKind New dependency kind.
16625ffd83dbSDimitry Andric   void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
16635ffd83dbSDimitry Andric                         OpenMPDependClauseKind NewDepKind, SourceLocation Loc);
16645ffd83dbSDimitry Andric 
16655ffd83dbSDimitry Andric   /// Initializes user defined allocators specified in the uses_allocators
16665ffd83dbSDimitry Andric   /// clauses.
16675ffd83dbSDimitry Andric   void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator,
16685ffd83dbSDimitry Andric                               const Expr *AllocatorTraits);
16695ffd83dbSDimitry Andric 
16705ffd83dbSDimitry Andric   /// Destroys user defined allocators specified in the uses_allocators clause.
16715ffd83dbSDimitry Andric   void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator);
1672e8d8bef9SDimitry Andric 
1673e8d8bef9SDimitry Andric   /// Returns true if the variable is a local variable in untied task.
1674e8d8bef9SDimitry Andric   bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const;
16750b57cec5SDimitry Andric };
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric /// Class supports emissionof SIMD-only code.
16780b57cec5SDimitry Andric class CGOpenMPSIMDRuntime final : public CGOpenMPRuntime {
16790b57cec5SDimitry Andric public:
CGOpenMPSIMDRuntime(CodeGenModule & CGM)16800b57cec5SDimitry Andric   explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {}
~CGOpenMPSIMDRuntime()16810b57cec5SDimitry Andric   ~CGOpenMPSIMDRuntime() override {}
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric   /// Emits outlined function for the specified OpenMP parallel directive
16840b57cec5SDimitry Andric   /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
16850b57cec5SDimitry Andric   /// kmp_int32 BoundID, struct context_vars*).
168606c3fb27SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
16870b57cec5SDimitry Andric   /// \param D OpenMP directive.
16880b57cec5SDimitry Andric   /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
16890b57cec5SDimitry Andric   /// \param InnermostKind Kind of innermost directive (for simple directives it
16900b57cec5SDimitry Andric   /// is a directive itself, for combined - its innermost directive).
16910b57cec5SDimitry Andric   /// \param CodeGen Code generation sequence for the \a D directive.
169206c3fb27SDimitry Andric   llvm::Function *emitParallelOutlinedFunction(
169306c3fb27SDimitry Andric       CodeGenFunction &CGF, const OMPExecutableDirective &D,
169406c3fb27SDimitry Andric       const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
16950b57cec5SDimitry Andric       const RegionCodeGenTy &CodeGen) override;
16960b57cec5SDimitry Andric 
16970b57cec5SDimitry Andric   /// Emits outlined function for the specified OpenMP teams directive
16980b57cec5SDimitry Andric   /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
16990b57cec5SDimitry Andric   /// kmp_int32 BoundID, struct context_vars*).
170006c3fb27SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
17010b57cec5SDimitry Andric   /// \param D OpenMP directive.
17020b57cec5SDimitry Andric   /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
17030b57cec5SDimitry Andric   /// \param InnermostKind Kind of innermost directive (for simple directives it
17040b57cec5SDimitry Andric   /// is a directive itself, for combined - its innermost directive).
17050b57cec5SDimitry Andric   /// \param CodeGen Code generation sequence for the \a D directive.
170606c3fb27SDimitry Andric   llvm::Function *emitTeamsOutlinedFunction(
170706c3fb27SDimitry Andric       CodeGenFunction &CGF, const OMPExecutableDirective &D,
170806c3fb27SDimitry Andric       const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
17090b57cec5SDimitry Andric       const RegionCodeGenTy &CodeGen) override;
17100b57cec5SDimitry Andric 
17110b57cec5SDimitry Andric   /// Emits outlined function for the OpenMP task directive \a D. This
17120b57cec5SDimitry Andric   /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t*
17130b57cec5SDimitry Andric   /// TaskT).
17140b57cec5SDimitry Andric   /// \param D OpenMP directive.
17150b57cec5SDimitry Andric   /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
17160b57cec5SDimitry Andric   /// \param PartIDVar Variable for partition id in the current OpenMP untied
17170b57cec5SDimitry Andric   /// task region.
17180b57cec5SDimitry Andric   /// \param TaskTVar Variable for task_t argument.
17190b57cec5SDimitry Andric   /// \param InnermostKind Kind of innermost directive (for simple directives it
17200b57cec5SDimitry Andric   /// is a directive itself, for combined - its innermost directive).
17210b57cec5SDimitry Andric   /// \param CodeGen Code generation sequence for the \a D directive.
17220b57cec5SDimitry Andric   /// \param Tied true if task is generated for tied task, false otherwise.
17230b57cec5SDimitry Andric   /// \param NumberOfParts Number of parts in untied task. Ignored for tied
17240b57cec5SDimitry Andric   /// tasks.
17250b57cec5SDimitry Andric   ///
17260b57cec5SDimitry Andric   llvm::Function *emitTaskOutlinedFunction(
17270b57cec5SDimitry Andric       const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
17280b57cec5SDimitry Andric       const VarDecl *PartIDVar, const VarDecl *TaskTVar,
17290b57cec5SDimitry Andric       OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
17300b57cec5SDimitry Andric       bool Tied, unsigned &NumberOfParts) override;
17310b57cec5SDimitry Andric 
17320b57cec5SDimitry Andric   /// Emits code for parallel or serial call of the \a OutlinedFn with
17330b57cec5SDimitry Andric   /// variables captured in a record which address is stored in \a
17340b57cec5SDimitry Andric   /// CapturedStruct.
17350b57cec5SDimitry Andric   /// \param OutlinedFn Outlined function to be run in parallel threads. Type of
17360b57cec5SDimitry Andric   /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
17370b57cec5SDimitry Andric   /// \param CapturedVars A pointer to the record with the references to
17380b57cec5SDimitry Andric   /// variables used in \a OutlinedFn function.
17390b57cec5SDimitry Andric   /// \param IfCond Condition in the associated 'if' clause, if it was
17400b57cec5SDimitry Andric   /// specified, nullptr otherwise.
17410eae32dcSDimitry Andric   /// \param NumThreads The value corresponding to the num_threads clause, if
17420eae32dcSDimitry Andric   /// any, or nullptr.
17430b57cec5SDimitry Andric   ///
17440b57cec5SDimitry Andric   void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
17450b57cec5SDimitry Andric                         llvm::Function *OutlinedFn,
17460b57cec5SDimitry Andric                         ArrayRef<llvm::Value *> CapturedVars,
17470eae32dcSDimitry Andric                         const Expr *IfCond, llvm::Value *NumThreads) override;
17480b57cec5SDimitry Andric 
17490b57cec5SDimitry Andric   /// Emits a critical region.
17500b57cec5SDimitry Andric   /// \param CriticalName Name of the critical region.
17510b57cec5SDimitry Andric   /// \param CriticalOpGen Generator for the statement associated with the given
17520b57cec5SDimitry Andric   /// critical region.
17530b57cec5SDimitry Andric   /// \param Hint Value of the 'hint' clause (optional).
17540b57cec5SDimitry Andric   void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
17550b57cec5SDimitry Andric                           const RegionCodeGenTy &CriticalOpGen,
17560b57cec5SDimitry Andric                           SourceLocation Loc,
17570b57cec5SDimitry Andric                           const Expr *Hint = nullptr) override;
17580b57cec5SDimitry Andric 
17590b57cec5SDimitry Andric   /// Emits a master region.
17600b57cec5SDimitry Andric   /// \param MasterOpGen Generator for the statement associated with the given
17610b57cec5SDimitry Andric   /// master region.
17620b57cec5SDimitry Andric   void emitMasterRegion(CodeGenFunction &CGF,
17630b57cec5SDimitry Andric                         const RegionCodeGenTy &MasterOpGen,
17640b57cec5SDimitry Andric                         SourceLocation Loc) override;
17650b57cec5SDimitry Andric 
1766fe6060f1SDimitry Andric   /// Emits a masked region.
1767fe6060f1SDimitry Andric   /// \param MaskedOpGen Generator for the statement associated with the given
1768fe6060f1SDimitry Andric   /// masked region.
1769fe6060f1SDimitry Andric   void emitMaskedRegion(CodeGenFunction &CGF,
1770fe6060f1SDimitry Andric                         const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc,
1771fe6060f1SDimitry Andric                         const Expr *Filter = nullptr) override;
1772fe6060f1SDimitry Andric 
1773fe6060f1SDimitry Andric   /// Emits a masked region.
1774fe6060f1SDimitry Andric   /// \param MaskedOpGen Generator for the statement associated with the given
1775fe6060f1SDimitry Andric   /// masked region.
1776fe6060f1SDimitry Andric 
17770b57cec5SDimitry Andric   /// Emits code for a taskyield directive.
17780b57cec5SDimitry Andric   void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override;
17790b57cec5SDimitry Andric 
17800b57cec5SDimitry Andric   /// Emit a taskgroup region.
17810b57cec5SDimitry Andric   /// \param TaskgroupOpGen Generator for the statement associated with the
17820b57cec5SDimitry Andric   /// given taskgroup region.
17830b57cec5SDimitry Andric   void emitTaskgroupRegion(CodeGenFunction &CGF,
17840b57cec5SDimitry Andric                            const RegionCodeGenTy &TaskgroupOpGen,
17850b57cec5SDimitry Andric                            SourceLocation Loc) override;
17860b57cec5SDimitry Andric 
17870b57cec5SDimitry Andric   /// Emits a single region.
17880b57cec5SDimitry Andric   /// \param SingleOpGen Generator for the statement associated with the given
17890b57cec5SDimitry Andric   /// single region.
17900b57cec5SDimitry Andric   void emitSingleRegion(CodeGenFunction &CGF,
17910b57cec5SDimitry Andric                         const RegionCodeGenTy &SingleOpGen, SourceLocation Loc,
17920b57cec5SDimitry Andric                         ArrayRef<const Expr *> CopyprivateVars,
17930b57cec5SDimitry Andric                         ArrayRef<const Expr *> DestExprs,
17940b57cec5SDimitry Andric                         ArrayRef<const Expr *> SrcExprs,
17950b57cec5SDimitry Andric                         ArrayRef<const Expr *> AssignmentOps) override;
17960b57cec5SDimitry Andric 
17970b57cec5SDimitry Andric   /// Emit an ordered region.
17980b57cec5SDimitry Andric   /// \param OrderedOpGen Generator for the statement associated with the given
17990b57cec5SDimitry Andric   /// ordered region.
18000b57cec5SDimitry Andric   void emitOrderedRegion(CodeGenFunction &CGF,
18010b57cec5SDimitry Andric                          const RegionCodeGenTy &OrderedOpGen,
18020b57cec5SDimitry Andric                          SourceLocation Loc, bool IsThreads) override;
18030b57cec5SDimitry Andric 
18040b57cec5SDimitry Andric   /// Emit an implicit/explicit barrier for OpenMP threads.
18050b57cec5SDimitry Andric   /// \param Kind Directive for which this implicit barrier call must be
18060b57cec5SDimitry Andric   /// generated. Must be OMPD_barrier for explicit barrier generation.
18070b57cec5SDimitry Andric   /// \param EmitChecks true if need to emit checks for cancellation barriers.
18080b57cec5SDimitry Andric   /// \param ForceSimpleCall true simple barrier call must be emitted, false if
18090b57cec5SDimitry Andric   /// runtime class decides which one to emit (simple or with cancellation
18100b57cec5SDimitry Andric   /// checks).
18110b57cec5SDimitry Andric   ///
18120b57cec5SDimitry Andric   void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
18130b57cec5SDimitry Andric                        OpenMPDirectiveKind Kind, bool EmitChecks = true,
18140b57cec5SDimitry Andric                        bool ForceSimpleCall = false) override;
18150b57cec5SDimitry Andric 
18160b57cec5SDimitry Andric   /// This is used for non static scheduled types and when the ordered
18170b57cec5SDimitry Andric   /// clause is present on the loop construct.
18180b57cec5SDimitry Andric   /// Depending on the loop schedule, it is necessary to call some runtime
18190b57cec5SDimitry Andric   /// routine before start of the OpenMP loop to get the loop upper / lower
18200b57cec5SDimitry Andric   /// bounds \a LB and \a UB and stride \a ST.
18210b57cec5SDimitry Andric   ///
18220b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
18230b57cec5SDimitry Andric   /// \param Loc Clang source location.
18240b57cec5SDimitry Andric   /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
18250b57cec5SDimitry Andric   /// \param IVSize Size of the iteration variable in bits.
18260b57cec5SDimitry Andric   /// \param IVSigned Sign of the iteration variable.
18270b57cec5SDimitry Andric   /// \param Ordered true if loop is ordered, false otherwise.
18280b57cec5SDimitry Andric   /// \param DispatchValues struct containing llvm values for lower bound, upper
18290b57cec5SDimitry Andric   /// bound, and chunk expression.
18300b57cec5SDimitry Andric   /// For the default (nullptr) value, the chunk 1 will be used.
18310b57cec5SDimitry Andric   ///
18320b57cec5SDimitry Andric   void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc,
18330b57cec5SDimitry Andric                            const OpenMPScheduleTy &ScheduleKind,
18340b57cec5SDimitry Andric                            unsigned IVSize, bool IVSigned, bool Ordered,
18350b57cec5SDimitry Andric                            const DispatchRTInput &DispatchValues) override;
18360b57cec5SDimitry Andric 
18370b57cec5SDimitry Andric   /// Call the appropriate runtime routine to initialize it before start
18380b57cec5SDimitry Andric   /// of loop.
18390b57cec5SDimitry Andric   ///
18400b57cec5SDimitry Andric   /// This is used only in case of static schedule, when the user did not
18410b57cec5SDimitry Andric   /// specify a ordered clause on the loop construct.
18420b57cec5SDimitry Andric   /// Depending on the loop schedule, it is necessary to call some runtime
18430b57cec5SDimitry Andric   /// routine before start of the OpenMP loop to get the loop upper / lower
18440b57cec5SDimitry Andric   /// bounds LB and UB and stride ST.
18450b57cec5SDimitry Andric   ///
18460b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
18470b57cec5SDimitry Andric   /// \param Loc Clang source location.
18480b57cec5SDimitry Andric   /// \param DKind Kind of the directive.
18490b57cec5SDimitry Andric   /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
18500b57cec5SDimitry Andric   /// \param Values Input arguments for the construct.
18510b57cec5SDimitry Andric   ///
18520b57cec5SDimitry Andric   void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
18530b57cec5SDimitry Andric                          OpenMPDirectiveKind DKind,
18540b57cec5SDimitry Andric                          const OpenMPScheduleTy &ScheduleKind,
18550b57cec5SDimitry Andric                          const StaticRTInput &Values) override;
18560b57cec5SDimitry Andric 
18570b57cec5SDimitry Andric   ///
18580b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
18590b57cec5SDimitry Andric   /// \param Loc Clang source location.
18600b57cec5SDimitry Andric   /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause.
18610b57cec5SDimitry Andric   /// \param Values Input arguments for the construct.
18620b57cec5SDimitry Andric   ///
18630b57cec5SDimitry Andric   void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
18640b57cec5SDimitry Andric                                 OpenMPDistScheduleClauseKind SchedKind,
18650b57cec5SDimitry Andric                                 const StaticRTInput &Values) override;
18660b57cec5SDimitry Andric 
18670b57cec5SDimitry Andric   /// Call the appropriate runtime routine to notify that we finished
18680b57cec5SDimitry Andric   /// iteration of the ordered loop with the dynamic scheduling.
18690b57cec5SDimitry Andric   ///
18700b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
18710b57cec5SDimitry Andric   /// \param Loc Clang source location.
18720b57cec5SDimitry Andric   /// \param IVSize Size of the iteration variable in bits.
18730b57cec5SDimitry Andric   /// \param IVSigned Sign of the iteration variable.
18740b57cec5SDimitry Andric   ///
18750b57cec5SDimitry Andric   void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc,
18760b57cec5SDimitry Andric                                   unsigned IVSize, bool IVSigned) override;
18770b57cec5SDimitry Andric 
18780b57cec5SDimitry Andric   /// Call the appropriate runtime routine to notify that we finished
18790b57cec5SDimitry Andric   /// all the work with current loop.
18800b57cec5SDimitry Andric   ///
18810b57cec5SDimitry Andric   /// \param CGF Reference to current CodeGenFunction.
18820b57cec5SDimitry Andric   /// \param Loc Clang source location.
18830b57cec5SDimitry Andric   /// \param DKind Kind of the directive for which the static finish is emitted.
18840b57cec5SDimitry Andric   ///
18850b57cec5SDimitry Andric   void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc,
18860b57cec5SDimitry Andric                            OpenMPDirectiveKind DKind) override;
18870b57cec5SDimitry Andric 
18880b57cec5SDimitry Andric   /// Call __kmpc_dispatch_next(
18890b57cec5SDimitry Andric   ///          ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
18900b57cec5SDimitry Andric   ///          kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
18910b57cec5SDimitry Andric   ///          kmp_int[32|64] *p_stride);
18920b57cec5SDimitry Andric   /// \param IVSize Size of the iteration variable in bits.
18930b57cec5SDimitry Andric   /// \param IVSigned Sign of the iteration variable.
18940b57cec5SDimitry Andric   /// \param IL Address of the output variable in which the flag of the
18950b57cec5SDimitry Andric   /// last iteration is returned.
18960b57cec5SDimitry Andric   /// \param LB Address of the output variable in which the lower iteration
18970b57cec5SDimitry Andric   /// number is returned.
18980b57cec5SDimitry Andric   /// \param UB Address of the output variable in which the upper iteration
18990b57cec5SDimitry Andric   /// number is returned.
19000b57cec5SDimitry Andric   /// \param ST Address of the output variable in which the stride value is
19010b57cec5SDimitry Andric   /// returned.
19020b57cec5SDimitry Andric   llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
19030b57cec5SDimitry Andric                            unsigned IVSize, bool IVSigned, Address IL,
19040b57cec5SDimitry Andric                            Address LB, Address UB, Address ST) override;
19050b57cec5SDimitry Andric 
19060b57cec5SDimitry Andric   /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
19070b57cec5SDimitry Andric   /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
19080b57cec5SDimitry Andric   /// clause.
19090b57cec5SDimitry Andric   /// \param NumThreads An integer value of threads.
19100b57cec5SDimitry Andric   void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads,
19110b57cec5SDimitry Andric                             SourceLocation Loc) override;
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric   /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
19140b57cec5SDimitry Andric   /// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
19150b57cec5SDimitry Andric   void emitProcBindClause(CodeGenFunction &CGF,
1916480093f4SDimitry Andric                           llvm::omp::ProcBindKind ProcBind,
19170b57cec5SDimitry Andric                           SourceLocation Loc) override;
19180b57cec5SDimitry Andric 
19190b57cec5SDimitry Andric   /// Returns address of the threadprivate variable for the current
19200b57cec5SDimitry Andric   /// thread.
19210b57cec5SDimitry Andric   /// \param VD Threadprivate variable.
19220b57cec5SDimitry Andric   /// \param VDAddr Address of the global variable \a VD.
19230b57cec5SDimitry Andric   /// \param Loc Location of the reference to threadprivate var.
19240b57cec5SDimitry Andric   /// \return Address of the threadprivate variable for the current thread.
19250b57cec5SDimitry Andric   Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD,
19260b57cec5SDimitry Andric                                  Address VDAddr, SourceLocation Loc) override;
19270b57cec5SDimitry Andric 
19280b57cec5SDimitry Andric   /// Emit a code for initialization of threadprivate variable. It emits
19290b57cec5SDimitry Andric   /// a call to runtime library which adds initial value to the newly created
19300b57cec5SDimitry Andric   /// threadprivate variable (if it is not constant) and registers destructor
19310b57cec5SDimitry Andric   /// for the variable (if any).
19320b57cec5SDimitry Andric   /// \param VD Threadprivate variable.
19330b57cec5SDimitry Andric   /// \param VDAddr Address of the global variable \a VD.
19340b57cec5SDimitry Andric   /// \param Loc Location of threadprivate declaration.
19350b57cec5SDimitry Andric   /// \param PerformInit true if initialization expression is not constant.
19360b57cec5SDimitry Andric   llvm::Function *
19370b57cec5SDimitry Andric   emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
19380b57cec5SDimitry Andric                                  SourceLocation Loc, bool PerformInit,
19390b57cec5SDimitry Andric                                  CodeGenFunction *CGF = nullptr) override;
19400b57cec5SDimitry Andric 
19410b57cec5SDimitry Andric   /// Creates artificial threadprivate variable with name \p Name and type \p
19420b57cec5SDimitry Andric   /// VarType.
19430b57cec5SDimitry Andric   /// \param VarType Type of the artificial threadprivate variable.
19440b57cec5SDimitry Andric   /// \param Name Name of the artificial threadprivate variable.
19450b57cec5SDimitry Andric   Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
19460b57cec5SDimitry Andric                                            QualType VarType,
19470b57cec5SDimitry Andric                                            StringRef Name) override;
19480b57cec5SDimitry Andric 
19490b57cec5SDimitry Andric   /// Emit flush of the variables specified in 'omp flush' directive.
19500b57cec5SDimitry Andric   /// \param Vars List of variables to flush.
19510b57cec5SDimitry Andric   void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
19525ffd83dbSDimitry Andric                  SourceLocation Loc, llvm::AtomicOrdering AO) override;
19530b57cec5SDimitry Andric 
19540b57cec5SDimitry Andric   /// Emit task region for the task directive. The task region is
19550b57cec5SDimitry Andric   /// emitted in several steps:
19560b57cec5SDimitry Andric   /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
19570b57cec5SDimitry Andric   /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
19580b57cec5SDimitry Andric   /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
19590b57cec5SDimitry Andric   /// function:
19600b57cec5SDimitry Andric   /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
19610b57cec5SDimitry Andric   ///   TaskFunction(gtid, tt->part_id, tt->shareds);
19620b57cec5SDimitry Andric   ///   return 0;
19630b57cec5SDimitry Andric   /// }
19640b57cec5SDimitry Andric   /// 2. Copy a list of shared variables to field shareds of the resulting
19650b57cec5SDimitry Andric   /// structure kmp_task_t returned by the previous call (if any).
19660b57cec5SDimitry Andric   /// 3. Copy a pointer to destructions function to field destructions of the
19670b57cec5SDimitry Andric   /// resulting structure kmp_task_t.
19680b57cec5SDimitry Andric   /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
19690b57cec5SDimitry Andric   /// kmp_task_t *new_task), where new_task is a resulting structure from
19700b57cec5SDimitry Andric   /// previous items.
19710b57cec5SDimitry Andric   /// \param D Current task directive.
19720b57cec5SDimitry Andric   /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
19730b57cec5SDimitry Andric   /// /*part_id*/, captured_struct */*__context*/);
19740b57cec5SDimitry Andric   /// \param SharedsTy A type which contains references the shared variables.
19750b57cec5SDimitry Andric   /// \param Shareds Context with the list of shared variables from the \p
19760b57cec5SDimitry Andric   /// TaskFunction.
19770b57cec5SDimitry Andric   /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
19780b57cec5SDimitry Andric   /// otherwise.
19790b57cec5SDimitry Andric   /// \param Data Additional data for task generation like tiednsee, final
19800b57cec5SDimitry Andric   /// state, list of privates etc.
19810b57cec5SDimitry Andric   void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
19820b57cec5SDimitry Andric                     const OMPExecutableDirective &D,
19830b57cec5SDimitry Andric                     llvm::Function *TaskFunction, QualType SharedsTy,
19840b57cec5SDimitry Andric                     Address Shareds, const Expr *IfCond,
19850b57cec5SDimitry Andric                     const OMPTaskDataTy &Data) override;
19860b57cec5SDimitry Andric 
19870b57cec5SDimitry Andric   /// Emit task region for the taskloop directive. The taskloop region is
19880b57cec5SDimitry Andric   /// emitted in several steps:
19890b57cec5SDimitry Andric   /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
19900b57cec5SDimitry Andric   /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
19910b57cec5SDimitry Andric   /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
19920b57cec5SDimitry Andric   /// function:
19930b57cec5SDimitry Andric   /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
19940b57cec5SDimitry Andric   ///   TaskFunction(gtid, tt->part_id, tt->shareds);
19950b57cec5SDimitry Andric   ///   return 0;
19960b57cec5SDimitry Andric   /// }
19970b57cec5SDimitry Andric   /// 2. Copy a list of shared variables to field shareds of the resulting
19980b57cec5SDimitry Andric   /// structure kmp_task_t returned by the previous call (if any).
19990b57cec5SDimitry Andric   /// 3. Copy a pointer to destructions function to field destructions of the
20000b57cec5SDimitry Andric   /// resulting structure kmp_task_t.
20010b57cec5SDimitry Andric   /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t
20020b57cec5SDimitry Andric   /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int
20030b57cec5SDimitry Andric   /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task
20040b57cec5SDimitry Andric   /// is a resulting structure from
20050b57cec5SDimitry Andric   /// previous items.
20060b57cec5SDimitry Andric   /// \param D Current task directive.
20070b57cec5SDimitry Andric   /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
20080b57cec5SDimitry Andric   /// /*part_id*/, captured_struct */*__context*/);
20090b57cec5SDimitry Andric   /// \param SharedsTy A type which contains references the shared variables.
20100b57cec5SDimitry Andric   /// \param Shareds Context with the list of shared variables from the \p
20110b57cec5SDimitry Andric   /// TaskFunction.
20120b57cec5SDimitry Andric   /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
20130b57cec5SDimitry Andric   /// otherwise.
20140b57cec5SDimitry Andric   /// \param Data Additional data for task generation like tiednsee, final
20150b57cec5SDimitry Andric   /// state, list of privates etc.
20160b57cec5SDimitry Andric   void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
20170b57cec5SDimitry Andric                         const OMPLoopDirective &D, llvm::Function *TaskFunction,
20180b57cec5SDimitry Andric                         QualType SharedsTy, Address Shareds, const Expr *IfCond,
20190b57cec5SDimitry Andric                         const OMPTaskDataTy &Data) override;
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric   /// Emit a code for reduction clause. Next code should be emitted for
20220b57cec5SDimitry Andric   /// reduction:
20230b57cec5SDimitry Andric   /// \code
20240b57cec5SDimitry Andric   ///
20250b57cec5SDimitry Andric   /// static kmp_critical_name lock = { 0 };
20260b57cec5SDimitry Andric   ///
20270b57cec5SDimitry Andric   /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
20280b57cec5SDimitry Andric   ///  ...
20290b57cec5SDimitry Andric   ///  *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
20300b57cec5SDimitry Andric   ///  ...
20310b57cec5SDimitry Andric   /// }
20320b57cec5SDimitry Andric   ///
20330b57cec5SDimitry Andric   /// ...
20340b57cec5SDimitry Andric   /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
20350b57cec5SDimitry Andric   /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
20360b57cec5SDimitry Andric   /// RedList, reduce_func, &<lock>)) {
20370b57cec5SDimitry Andric   /// case 1:
20380b57cec5SDimitry Andric   ///  ...
20390b57cec5SDimitry Andric   ///  <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
20400b57cec5SDimitry Andric   ///  ...
20410b57cec5SDimitry Andric   /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
20420b57cec5SDimitry Andric   /// break;
20430b57cec5SDimitry Andric   /// case 2:
20440b57cec5SDimitry Andric   ///  ...
20450b57cec5SDimitry Andric   ///  Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
20460b57cec5SDimitry Andric   ///  ...
20470b57cec5SDimitry Andric   /// break;
20480b57cec5SDimitry Andric   /// default:;
20490b57cec5SDimitry Andric   /// }
20500b57cec5SDimitry Andric   /// \endcode
20510b57cec5SDimitry Andric   ///
20520b57cec5SDimitry Andric   /// \param Privates List of private copies for original reduction arguments.
20530b57cec5SDimitry Andric   /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
20540b57cec5SDimitry Andric   /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
20550b57cec5SDimitry Andric   /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
20560b57cec5SDimitry Andric   /// or 'operator binop(LHS, RHS)'.
20570b57cec5SDimitry Andric   /// \param Options List of options for reduction codegen:
20580b57cec5SDimitry Andric   ///     WithNowait true if parent directive has also nowait clause, false
20590b57cec5SDimitry Andric   ///     otherwise.
20600b57cec5SDimitry Andric   ///     SimpleReduction Emit reduction operation only. Used for omp simd
20610b57cec5SDimitry Andric   ///     directive on the host.
20620b57cec5SDimitry Andric   ///     ReductionKind The kind of reduction to perform.
20630b57cec5SDimitry Andric   void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
20640b57cec5SDimitry Andric                      ArrayRef<const Expr *> Privates,
20650b57cec5SDimitry Andric                      ArrayRef<const Expr *> LHSExprs,
20660b57cec5SDimitry Andric                      ArrayRef<const Expr *> RHSExprs,
20670b57cec5SDimitry Andric                      ArrayRef<const Expr *> ReductionOps,
20680b57cec5SDimitry Andric                      ReductionOptionsTy Options) override;
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric   /// Emit a code for initialization of task reduction clause. Next code
20710b57cec5SDimitry Andric   /// should be emitted for reduction:
20720b57cec5SDimitry Andric   /// \code
20730b57cec5SDimitry Andric   ///
20745ffd83dbSDimitry Andric   /// _taskred_item_t red_data[n];
20750b57cec5SDimitry Andric   /// ...
20765ffd83dbSDimitry Andric   /// red_data[i].shar = &shareds[i];
20775ffd83dbSDimitry Andric   /// red_data[i].orig = &origs[i];
20780b57cec5SDimitry Andric   /// red_data[i].size = sizeof(origs[i]);
20790b57cec5SDimitry Andric   /// red_data[i].f_init = (void*)RedInit<i>;
20800b57cec5SDimitry Andric   /// red_data[i].f_fini = (void*)RedDest<i>;
20810b57cec5SDimitry Andric   /// red_data[i].f_comb = (void*)RedOp<i>;
20820b57cec5SDimitry Andric   /// red_data[i].flags = <Flag_i>;
20830b57cec5SDimitry Andric   /// ...
20845ffd83dbSDimitry Andric   /// void* tg1 = __kmpc_taskred_init(gtid, n, red_data);
20850b57cec5SDimitry Andric   /// \endcode
20865ffd83dbSDimitry Andric   /// For reduction clause with task modifier it emits the next call:
20875ffd83dbSDimitry Andric   /// \code
20880b57cec5SDimitry Andric   ///
20895ffd83dbSDimitry Andric   /// _taskred_item_t red_data[n];
20905ffd83dbSDimitry Andric   /// ...
20915ffd83dbSDimitry Andric   /// red_data[i].shar = &shareds[i];
20925ffd83dbSDimitry Andric   /// red_data[i].orig = &origs[i];
20935ffd83dbSDimitry Andric   /// red_data[i].size = sizeof(origs[i]);
20945ffd83dbSDimitry Andric   /// red_data[i].f_init = (void*)RedInit<i>;
20955ffd83dbSDimitry Andric   /// red_data[i].f_fini = (void*)RedDest<i>;
20965ffd83dbSDimitry Andric   /// red_data[i].f_comb = (void*)RedOp<i>;
20975ffd83dbSDimitry Andric   /// red_data[i].flags = <Flag_i>;
20985ffd83dbSDimitry Andric   /// ...
20995ffd83dbSDimitry Andric   /// void* tg1 = __kmpc_taskred_modifier_init(loc, gtid, is_worksharing, n,
21005ffd83dbSDimitry Andric   /// red_data);
21015ffd83dbSDimitry Andric   /// \endcode
21020b57cec5SDimitry Andric   /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations.
21030b57cec5SDimitry Andric   /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations.
21040b57cec5SDimitry Andric   /// \param Data Additional data for task generation like tiedness, final
21050b57cec5SDimitry Andric   /// state, list of privates, reductions etc.
21060b57cec5SDimitry Andric   llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc,
21070b57cec5SDimitry Andric                                      ArrayRef<const Expr *> LHSExprs,
21080b57cec5SDimitry Andric                                      ArrayRef<const Expr *> RHSExprs,
21090b57cec5SDimitry Andric                                      const OMPTaskDataTy &Data) override;
21100b57cec5SDimitry Andric 
21115ffd83dbSDimitry Andric   /// Emits the following code for reduction clause with task modifier:
21125ffd83dbSDimitry Andric   /// \code
21135ffd83dbSDimitry Andric   /// __kmpc_task_reduction_modifier_fini(loc, gtid, is_worksharing);
21145ffd83dbSDimitry Andric   /// \endcode
21155ffd83dbSDimitry Andric   void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc,
21165ffd83dbSDimitry Andric                              bool IsWorksharingReduction) override;
21175ffd83dbSDimitry Andric 
21180b57cec5SDimitry Andric   /// Required to resolve existing problems in the runtime. Emits threadprivate
21190b57cec5SDimitry Andric   /// variables to store the size of the VLAs/array sections for
21200b57cec5SDimitry Andric   /// initializer/combiner/finalizer functions + emits threadprivate variable to
21210b57cec5SDimitry Andric   /// store the pointer to the original reduction item for the custom
21220b57cec5SDimitry Andric   /// initializer defined by declare reduction construct.
21230b57cec5SDimitry Andric   /// \param RCG Allows to reuse an existing data for the reductions.
21240b57cec5SDimitry Andric   /// \param N Reduction item for which fixups must be emitted.
21250b57cec5SDimitry Andric   void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc,
21260b57cec5SDimitry Andric                                ReductionCodeGen &RCG, unsigned N) override;
21270b57cec5SDimitry Andric 
21280b57cec5SDimitry Andric   /// Get the address of `void *` type of the privatue copy of the reduction
21290b57cec5SDimitry Andric   /// item specified by the \p SharedLVal.
21300b57cec5SDimitry Andric   /// \param ReductionsPtr Pointer to the reduction data returned by the
21310b57cec5SDimitry Andric   /// emitTaskReductionInit function.
21320b57cec5SDimitry Andric   /// \param SharedLVal Address of the original reduction item.
21330b57cec5SDimitry Andric   Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc,
21340b57cec5SDimitry Andric                                llvm::Value *ReductionsPtr,
21350b57cec5SDimitry Andric                                LValue SharedLVal) override;
21360b57cec5SDimitry Andric 
21370b57cec5SDimitry Andric   /// Emit code for 'taskwait' directive.
2138349cc55cSDimitry Andric   void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
2139349cc55cSDimitry Andric                         const OMPTaskDataTy &Data) override;
21400b57cec5SDimitry Andric 
21410b57cec5SDimitry Andric   /// Emit code for 'cancellation point' construct.
21420b57cec5SDimitry Andric   /// \param CancelRegion Region kind for which the cancellation point must be
21430b57cec5SDimitry Andric   /// emitted.
21440b57cec5SDimitry Andric   ///
21450b57cec5SDimitry Andric   void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc,
21460b57cec5SDimitry Andric                                  OpenMPDirectiveKind CancelRegion) override;
21470b57cec5SDimitry Andric 
21480b57cec5SDimitry Andric   /// Emit code for 'cancel' construct.
21490b57cec5SDimitry Andric   /// \param IfCond Condition in the associated 'if' clause, if it was
21500b57cec5SDimitry Andric   /// specified, nullptr otherwise.
21510b57cec5SDimitry Andric   /// \param CancelRegion Region kind for which the cancel must be emitted.
21520b57cec5SDimitry Andric   ///
21530b57cec5SDimitry Andric   void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
21540b57cec5SDimitry Andric                       const Expr *IfCond,
21550b57cec5SDimitry Andric                       OpenMPDirectiveKind CancelRegion) override;
21560b57cec5SDimitry Andric 
21570b57cec5SDimitry Andric   /// Emit outilined function for 'target' directive.
21580b57cec5SDimitry Andric   /// \param D Directive to emit.
21590b57cec5SDimitry Andric   /// \param ParentName Name of the function that encloses the target region.
21600b57cec5SDimitry Andric   /// \param OutlinedFn Outlined function value to be defined by this call.
21610b57cec5SDimitry Andric   /// \param OutlinedFnID Outlined function ID value to be defined by this call.
21620b57cec5SDimitry Andric   /// \param IsOffloadEntry True if the outlined function is an offload entry.
21630b57cec5SDimitry Andric   /// \param CodeGen Code generation sequence for the \a D directive.
21640b57cec5SDimitry Andric   /// An outlined function may not be an entry if, e.g. the if clause always
21650b57cec5SDimitry Andric   /// evaluates to false.
21660b57cec5SDimitry Andric   void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
21670b57cec5SDimitry Andric                                   StringRef ParentName,
21680b57cec5SDimitry Andric                                   llvm::Function *&OutlinedFn,
21690b57cec5SDimitry Andric                                   llvm::Constant *&OutlinedFnID,
21700b57cec5SDimitry Andric                                   bool IsOffloadEntry,
21710b57cec5SDimitry Andric                                   const RegionCodeGenTy &CodeGen) override;
21720b57cec5SDimitry Andric 
21730b57cec5SDimitry Andric   /// Emit the target offloading code associated with \a D. The emitted
21740b57cec5SDimitry Andric   /// code attempts offloading the execution to the device, an the event of
21750b57cec5SDimitry Andric   /// a failure it executes the host version outlined in \a OutlinedFn.
21760b57cec5SDimitry Andric   /// \param D Directive to emit.
21770b57cec5SDimitry Andric   /// \param OutlinedFn Host version of the code to be offloaded.
21780b57cec5SDimitry Andric   /// \param OutlinedFnID ID of host version of the code to be offloaded.
21790b57cec5SDimitry Andric   /// \param IfCond Expression evaluated in if clause associated with the target
21800b57cec5SDimitry Andric   /// directive, or null if no if clause is used.
21810b57cec5SDimitry Andric   /// \param Device Expression evaluated in device clause associated with the
21825ffd83dbSDimitry Andric   /// target directive, or null if no device clause is used and device modifier.
21835ffd83dbSDimitry Andric   void emitTargetCall(
21845ffd83dbSDimitry Andric       CodeGenFunction &CGF, const OMPExecutableDirective &D,
21855ffd83dbSDimitry Andric       llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
21865ffd83dbSDimitry Andric       llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
2187a7dea167SDimitry Andric       llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
2188a7dea167SDimitry Andric                                        const OMPLoopDirective &D)>
2189a7dea167SDimitry Andric           SizeEmitter) override;
21900b57cec5SDimitry Andric 
21910b57cec5SDimitry Andric   /// Emit the target regions enclosed in \a GD function definition or
21920b57cec5SDimitry Andric   /// the function itself in case it is a valid device function. Returns true if
21930b57cec5SDimitry Andric   /// \a GD was dealt with successfully.
21940b57cec5SDimitry Andric   /// \param GD Function to scan.
21950b57cec5SDimitry Andric   bool emitTargetFunctions(GlobalDecl GD) override;
21960b57cec5SDimitry Andric 
21970b57cec5SDimitry Andric   /// Emit the global variable if it is a valid device global variable.
21980b57cec5SDimitry Andric   /// Returns true if \a GD was dealt with successfully.
21990b57cec5SDimitry Andric   /// \param GD Variable declaration to emit.
22000b57cec5SDimitry Andric   bool emitTargetGlobalVariable(GlobalDecl GD) override;
22010b57cec5SDimitry Andric 
22020b57cec5SDimitry Andric   /// Emit the global \a GD if it is meaningful for the target. Returns
22030b57cec5SDimitry Andric   /// if it was emitted successfully.
22040b57cec5SDimitry Andric   /// \param GD Global to scan.
22050b57cec5SDimitry Andric   bool emitTargetGlobal(GlobalDecl GD) override;
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric   /// Emits code for teams call of the \a OutlinedFn with
22080b57cec5SDimitry Andric   /// variables captured in a record which address is stored in \a
22090b57cec5SDimitry Andric   /// CapturedStruct.
22100b57cec5SDimitry Andric   /// \param OutlinedFn Outlined function to be run by team masters. Type of
22110b57cec5SDimitry Andric   /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
22120b57cec5SDimitry Andric   /// \param CapturedVars A pointer to the record with the references to
22130b57cec5SDimitry Andric   /// variables used in \a OutlinedFn function.
22140b57cec5SDimitry Andric   ///
22150b57cec5SDimitry Andric   void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
22160b57cec5SDimitry Andric                      SourceLocation Loc, llvm::Function *OutlinedFn,
22170b57cec5SDimitry Andric                      ArrayRef<llvm::Value *> CapturedVars) override;
22180b57cec5SDimitry Andric 
22190b57cec5SDimitry Andric   /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
22200b57cec5SDimitry Andric   /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code
22210b57cec5SDimitry Andric   /// for num_teams clause.
22220b57cec5SDimitry Andric   /// \param NumTeams An integer expression of teams.
22230b57cec5SDimitry Andric   /// \param ThreadLimit An integer expression of threads.
22240b57cec5SDimitry Andric   void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
22250b57cec5SDimitry Andric                           const Expr *ThreadLimit, SourceLocation Loc) override;
22260b57cec5SDimitry Andric 
22270b57cec5SDimitry Andric   /// Emit the target data mapping code associated with \a D.
22280b57cec5SDimitry Andric   /// \param D Directive to emit.
22290b57cec5SDimitry Andric   /// \param IfCond Expression evaluated in if clause associated with the
22300b57cec5SDimitry Andric   /// target directive, or null if no device clause is used.
22310b57cec5SDimitry Andric   /// \param Device Expression evaluated in device clause associated with the
22320b57cec5SDimitry Andric   /// target directive, or null if no device clause is used.
22330b57cec5SDimitry Andric   /// \param Info A record used to store information that needs to be preserved
22340b57cec5SDimitry Andric   /// until the region is closed.
22350b57cec5SDimitry Andric   void emitTargetDataCalls(CodeGenFunction &CGF,
22360b57cec5SDimitry Andric                            const OMPExecutableDirective &D, const Expr *IfCond,
22370b57cec5SDimitry Andric                            const Expr *Device, const RegionCodeGenTy &CodeGen,
2238bdd1243dSDimitry Andric                            CGOpenMPRuntime::TargetDataInfo &Info) override;
22390b57cec5SDimitry Andric 
22400b57cec5SDimitry Andric   /// Emit the data mapping/movement code associated with the directive
22410b57cec5SDimitry Andric   /// \a D that should be of the form 'target [{enter|exit} data | update]'.
22420b57cec5SDimitry Andric   /// \param D Directive to emit.
22430b57cec5SDimitry Andric   /// \param IfCond Expression evaluated in if clause associated with the target
22440b57cec5SDimitry Andric   /// directive, or null if no if clause is used.
22450b57cec5SDimitry Andric   /// \param Device Expression evaluated in device clause associated with the
22460b57cec5SDimitry Andric   /// target directive, or null if no device clause is used.
22470b57cec5SDimitry Andric   void emitTargetDataStandAloneCall(CodeGenFunction &CGF,
22480b57cec5SDimitry Andric                                     const OMPExecutableDirective &D,
22490b57cec5SDimitry Andric                                     const Expr *IfCond,
22500b57cec5SDimitry Andric                                     const Expr *Device) override;
22510b57cec5SDimitry Andric 
22520b57cec5SDimitry Andric   /// Emit initialization for doacross loop nesting support.
22530b57cec5SDimitry Andric   /// \param D Loop-based construct used in doacross nesting construct.
22540b57cec5SDimitry Andric   void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
22550b57cec5SDimitry Andric                         ArrayRef<Expr *> NumIterations) override;
22560b57cec5SDimitry Andric 
22570b57cec5SDimitry Andric   /// Emit code for doacross ordered directive with 'depend' clause.
22580b57cec5SDimitry Andric   /// \param C 'depend' clause with 'sink|source' dependency kind.
22590b57cec5SDimitry Andric   void emitDoacrossOrdered(CodeGenFunction &CGF,
22600b57cec5SDimitry Andric                            const OMPDependClause *C) override;
22610b57cec5SDimitry Andric 
226206c3fb27SDimitry Andric   /// Emit code for doacross ordered directive with 'doacross' clause.
226306c3fb27SDimitry Andric   /// \param C 'doacross' clause with 'sink|source' dependence type.
226406c3fb27SDimitry Andric   void emitDoacrossOrdered(CodeGenFunction &CGF,
226506c3fb27SDimitry Andric                            const OMPDoacrossClause *C) override;
226606c3fb27SDimitry Andric 
22670b57cec5SDimitry Andric   /// Translates the native parameter of outlined function if this is required
22680b57cec5SDimitry Andric   /// for target.
22690b57cec5SDimitry Andric   /// \param FD Field decl from captured record for the parameter.
22700b57cec5SDimitry Andric   /// \param NativeParam Parameter itself.
22710b57cec5SDimitry Andric   const VarDecl *translateParameter(const FieldDecl *FD,
22720b57cec5SDimitry Andric                                     const VarDecl *NativeParam) const override;
22730b57cec5SDimitry Andric 
22740b57cec5SDimitry Andric   /// Gets the address of the native argument basing on the address of the
22750b57cec5SDimitry Andric   /// target-specific parameter.
22760b57cec5SDimitry Andric   /// \param NativeParam Parameter itself.
22770b57cec5SDimitry Andric   /// \param TargetParam Corresponding target-specific parameter.
22780b57cec5SDimitry Andric   Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam,
22790b57cec5SDimitry Andric                               const VarDecl *TargetParam) const override;
22800b57cec5SDimitry Andric 
22810b57cec5SDimitry Andric   /// Gets the OpenMP-specific address of the local variable.
getAddressOfLocalVariable(CodeGenFunction & CGF,const VarDecl * VD)22820b57cec5SDimitry Andric   Address getAddressOfLocalVariable(CodeGenFunction &CGF,
22830b57cec5SDimitry Andric                                     const VarDecl *VD) override {
22840b57cec5SDimitry Andric     return Address::invalid();
22850b57cec5SDimitry Andric   }
22860b57cec5SDimitry Andric };
22870b57cec5SDimitry Andric 
22880b57cec5SDimitry Andric } // namespace CodeGen
228906c3fb27SDimitry Andric // Utility for openmp doacross clause kind
229006c3fb27SDimitry Andric namespace {
229106c3fb27SDimitry Andric template <typename T> class OMPDoacrossKind {
229206c3fb27SDimitry Andric public:
isSink(const T *)229306c3fb27SDimitry Andric   bool isSink(const T *) { return false; }
isSource(const T *)229406c3fb27SDimitry Andric   bool isSource(const T *) { return false; }
229506c3fb27SDimitry Andric };
229606c3fb27SDimitry Andric template <> class OMPDoacrossKind<OMPDependClause> {
229706c3fb27SDimitry Andric public:
isSink(const OMPDependClause * C)229806c3fb27SDimitry Andric   bool isSink(const OMPDependClause *C) {
229906c3fb27SDimitry Andric     return C->getDependencyKind() == OMPC_DEPEND_sink;
230006c3fb27SDimitry Andric   }
isSource(const OMPDependClause * C)230106c3fb27SDimitry Andric   bool isSource(const OMPDependClause *C) {
230206c3fb27SDimitry Andric     return C->getDependencyKind() == OMPC_DEPEND_source;
230306c3fb27SDimitry Andric   }
230406c3fb27SDimitry Andric };
230506c3fb27SDimitry Andric template <> class OMPDoacrossKind<OMPDoacrossClause> {
230606c3fb27SDimitry Andric public:
isSource(const OMPDoacrossClause * C)230706c3fb27SDimitry Andric   bool isSource(const OMPDoacrossClause *C) {
230806c3fb27SDimitry Andric     return C->getDependenceType() == OMPC_DOACROSS_source ||
230906c3fb27SDimitry Andric            C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
231006c3fb27SDimitry Andric   }
isSink(const OMPDoacrossClause * C)231106c3fb27SDimitry Andric   bool isSink(const OMPDoacrossClause *C) {
231206c3fb27SDimitry Andric     return C->getDependenceType() == OMPC_DOACROSS_sink ||
231306c3fb27SDimitry Andric            C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
231406c3fb27SDimitry Andric   }
231506c3fb27SDimitry Andric };
231606c3fb27SDimitry Andric } // namespace
23170b57cec5SDimitry Andric } // namespace clang
23180b57cec5SDimitry Andric 
23190b57cec5SDimitry Andric #endif
2320