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