16bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
26bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
36bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//                     The LLVM Compiler Infrastructure
46bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
56bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// This file is distributed under the University of Illinois Open Source
66bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// License. See LICENSE.TXT for details.
76bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
86bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//===----------------------------------------------------------------------===//
96bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// This provides a class for OpenMP runtime code generation.
116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//===----------------------------------------------------------------------===//
136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "CGOpenMPRuntime.h"
156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "CodeGenFunction.h"
163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar#include "CGCleanup.h"
176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/AST/Decl.h"
180e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/AST/StmtOpenMP.h"
196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/ADT/ArrayRef.h"
20176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "llvm/IR/CallSite.h"
216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/IR/DerivedTypes.h"
226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/IR/GlobalValue.h"
236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/IR/Value.h"
246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/Support/raw_ostream.h"
25c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include <cassert>
266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesusing namespace clang;
286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesusing namespace CodeGen;
296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
30176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesnamespace {
310e2c34f92f00628d48968dfea096d36381f494cbStephen Hines/// \brief Base class for handling code generation inside OpenMP regions.
32176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesclass CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
33176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinespublic:
3433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  /// \brief Kinds of OpenMP regions used in codegen.
3533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  enum CGOpenMPRegionKind {
3633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    /// \brief Region with outlined function for standalone 'parallel'
3733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    /// directive.
3833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    ParallelOutlinedRegion,
3933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    /// \brief Region with outlined function for standalone 'task' directive.
4033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    TaskOutlinedRegion,
4133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    /// \brief Region for constructs that do not require function outlining,
4233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    /// like 'for', 'sections', 'atomic' etc. directives.
4333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    InlinedRegion,
4433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  };
4533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
4633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPRegionInfo(const CapturedStmt &CS,
4733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                     const CGOpenMPRegionKind RegionKind,
4833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                     const RegionCodeGenTy &CodeGen)
4933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
5033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CodeGen(CodeGen) {}
510e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
5233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
5333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                     const RegionCodeGenTy &CodeGen)
5433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind),
5533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CodeGen(CodeGen) {}
56176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
570e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Get a variable or parameter for storing global thread id
58176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  /// inside OpenMP construct.
590e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  virtual const VarDecl *getThreadIDVariable() const = 0;
60176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
6133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  /// \brief Emit the captured statement body.
6233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
6333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
640e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Get an LValue for the current ThreadID variable.
653ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \return LValue for thread id variable. This LValue always has type int32*.
663ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
67176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
6833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
690e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
70176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  static bool classof(const CGCapturedStmtInfo *Info) {
71176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return Info->getKind() == CR_OpenMP;
72176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
7333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
740e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesprotected:
7533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPRegionKind RegionKind;
7633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  const RegionCodeGenTy &CodeGen;
770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines};
78176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines/// \brief API for captured statement code generation in OpenMP constructs.
800e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesclass CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
810e2c34f92f00628d48968dfea096d36381f494cbStephen Hinespublic:
8233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
8333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                             const RegionCodeGenTy &CodeGen)
8433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen),
8533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        ThreadIDVar(ThreadIDVar) {
860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Get a variable or parameter for storing global thread id
890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// inside OpenMP construct.
9033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
9133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
92176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  /// \brief Get the name of the capture helper.
93176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  StringRef getHelperName() const override { return ".omp_outlined."; }
94176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
9533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  static bool classof(const CGCapturedStmtInfo *Info) {
9633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    return CGOpenMPRegionInfo::classof(Info) &&
9733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar           cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
9833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar               ParallelOutlinedRegion;
9933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
10033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
101176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesprivate:
102176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  /// \brief A variable or parameter storing global thread id for OpenMP
103176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  /// constructs.
104176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  const VarDecl *ThreadIDVar;
1050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines};
1060e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
1073ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/// \brief API for captured statement code generation in OpenMP constructs.
1083ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarclass CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
1093ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarpublic:
11033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
1113ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                 const VarDecl *ThreadIDVar,
11233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                 const RegionCodeGenTy &CodeGen)
11333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen),
11433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        ThreadIDVar(ThreadIDVar) {
1153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
1163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
1173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \brief Get a variable or parameter for storing global thread id
1183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// inside OpenMP construct.
11933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
1203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
1213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \brief Get an LValue for the current ThreadID variable.
12233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
1233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
1243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \brief Get the name of the capture helper.
1253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  StringRef getHelperName() const override { return ".omp_outlined."; }
1263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
12733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  static bool classof(const CGCapturedStmtInfo *Info) {
12833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    return CGOpenMPRegionInfo::classof(Info) &&
12933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar           cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
13033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar               TaskOutlinedRegion;
13133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
13233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
1333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarprivate:
1343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \brief A variable or parameter storing global thread id for OpenMP
1353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// constructs.
1363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  const VarDecl *ThreadIDVar;
1373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar};
1383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
1390e2c34f92f00628d48968dfea096d36381f494cbStephen Hines/// \brief API for inlined captured statement code generation in OpenMP
1400e2c34f92f00628d48968dfea096d36381f494cbStephen Hines/// constructs.
1410e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesclass CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
1420e2c34f92f00628d48968dfea096d36381f494cbStephen Hinespublic:
14333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
14433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                            const RegionCodeGenTy &CodeGen)
14533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      : CGOpenMPRegionInfo(InlinedRegion, CodeGen), OldCSI(OldCSI),
1460e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
1470e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // \brief Retrieve the value of the context parameter.
14833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  llvm::Value *getContextValue() const override {
1490e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    if (OuterRegionInfo)
1500e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      return OuterRegionInfo->getContextValue();
1510e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm_unreachable("No context value for inlined OpenMP region");
1520e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
15333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  virtual void setContextValue(llvm::Value *V) override {
15433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    if (OuterRegionInfo) {
15533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      OuterRegionInfo->setContextValue(V);
15633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      return;
15733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    }
15833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm_unreachable("No context value for inlined OpenMP region");
15933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
1600e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Lookup the captured field decl for a variable.
16133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  const FieldDecl *lookup(const VarDecl *VD) const override {
1620e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    if (OuterRegionInfo)
1630e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      return OuterRegionInfo->lookup(VD);
16433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // If there is no outer outlined region,no need to lookup in a list of
16533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // captured variables, we can use the original one.
16633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    return nullptr;
1670e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
16833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  FieldDecl *getThisFieldDecl() const override {
1690e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    if (OuterRegionInfo)
1700e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      return OuterRegionInfo->getThisFieldDecl();
1710e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return nullptr;
1720e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
1730e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Get a variable or parameter for storing global thread id
1740e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// inside OpenMP construct.
17533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  const VarDecl *getThreadIDVariable() const override {
1760e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    if (OuterRegionInfo)
1770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      return OuterRegionInfo->getThreadIDVariable();
1780e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return nullptr;
1790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
1803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
1810e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Get the name of the capture helper.
18233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  StringRef getHelperName() const override {
18333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    if (auto *OuterRegionInfo = getOldCSI())
18433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      return OuterRegionInfo->getHelperName();
1850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm_unreachable("No helper name for inlined OpenMP construct");
1860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
1870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
1880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
1890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
19033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  static bool classof(const CGCapturedStmtInfo *Info) {
19133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    return CGOpenMPRegionInfo::classof(Info) &&
19233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar           cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
19333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
19433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
1950e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesprivate:
1960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief CodeGen info about outer OpenMP region.
1970e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CodeGenFunction::CGCapturedStmtInfo *OldCSI;
1980e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGOpenMPRegionInfo *OuterRegionInfo;
199176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines};
20033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
20133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar/// \brief RAII for emitting code of OpenMP constructs.
20233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarclass InlinedOpenMPRegionRAII {
20333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CodeGenFunction &CGF;
20433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
20533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarpublic:
20633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  /// \brief Constructs region for combined constructs.
20733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  /// \param CodeGen Code generation sequence for combined directives. Includes
20833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  /// a list of functions used for code generation of implicitly inlined
20933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  /// regions.
21033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen)
21133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      : CGF(CGF) {
21233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // Start emission for the construct.
21333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.CapturedStmtInfo =
21433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen);
21533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
21633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ~InlinedOpenMPRegionRAII() {
21733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // Restore original CapturedStmtInfo only if we're done with code emission.
21833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    auto *OldCSI =
21933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
22033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    delete CGF.CapturedStmtInfo;
22133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.CapturedStmtInfo = OldCSI;
22233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
22333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar};
22433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
225176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} // namespace
226176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
227176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesLValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
228176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return CGF.MakeNaturalAlignAddrLValue(
2293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.Builder.CreateAlignedLoad(
2303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          CGF.GetAddrOfLocalVar(getThreadIDVariable()),
2313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          CGF.PointerAlignInBytes),
2323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      getThreadIDVariable()
2333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          ->getType()
2343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          ->castAs<PointerType>()
2353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          ->getPointeeType());
236176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
237176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
23833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarvoid CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
23933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // 1.2.2 OpenMP Language Terminology
24033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // Structured block - An executable statement with a single entry at the
24133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // top and a single exit at the bottom.
24233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // The point of exit cannot be a branch out of the structured block.
24333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // longjmp() and throw() must not violate the entry/exit criteria.
24433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.EHStack.pushTerminate();
24533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  {
24633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CodeGenFunction::RunCleanupsScope Scope(CGF);
24733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CodeGen(CGF);
24833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
24933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.EHStack.popTerminate();
250176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
251176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
2523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga NainarLValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
2533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CodeGenFunction &CGF) {
2543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return CGF.MakeNaturalAlignAddrLValue(
2553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.GetAddrOfLocalVar(getThreadIDVariable()),
2563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      getThreadIDVariable()->getType());
2573ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
2583ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
2596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesCGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
2603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) {
2616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  IdentTy = llvm::StructType::create(
2626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
2636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
264176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CGM.Int8PtrTy /* psource */, nullptr);
2656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
266c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
267c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                               llvm::PointerType::getUnqual(CGM.Int32Ty)};
2686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
269176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
270176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
271176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
2723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarvoid CGOpenMPRuntime::clear() {
2733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  InternalVars.clear();
2743ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
2753ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
276176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesllvm::Value *
27733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga NainarCGOpenMPRuntime::emitParallelOutlinedFunction(const OMPExecutableDirective &D,
27833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                              const VarDecl *ThreadIDVar,
27933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                              const RegionCodeGenTy &CodeGen) {
2803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  assert(ThreadIDVar->getType()->isPointerType() &&
2813ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar         "thread id variable must be of type kmp_int32 *");
282176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
283176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CodeGenFunction CGF(CGM, true);
28433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen);
285176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CGF.CapturedStmtInfo = &CGInfo;
286176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return CGF.GenerateCapturedStmtFunction(*CS);
2876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
2886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesllvm::Value *
2903ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga NainarCGOpenMPRuntime::emitTaskOutlinedFunction(const OMPExecutableDirective &D,
2913ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                          const VarDecl *ThreadIDVar,
29233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          const RegionCodeGenTy &CodeGen) {
2933ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  assert(!ThreadIDVar->getType()->isPointerType() &&
2943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar         "thread id variable must be of type kmp_int32 for tasks");
2953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
2963ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CodeGenFunction CGF(CGM, true);
29733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen);
2983ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.CapturedStmtInfo = &CGInfo;
2993ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return CGF.GenerateCapturedStmtFunction(*CS);
3003ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
3013ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
3023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarllvm::Value *
3030e2c34f92f00628d48968dfea096d36381f494cbStephen HinesCGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
3046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
3056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!Entry) {
3066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!DefaultOpenMPPSource) {
3076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // Initialize default location for psource field of ident_t structure of
3086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // all ident_t objects. Format is ";file;function;line;column;;".
3096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // Taken from
3106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
3116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      DefaultOpenMPPSource =
3126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
3136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      DefaultOpenMPPSource =
3146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
3156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
316176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    auto DefaultOpenMPLocation = new llvm::GlobalVariable(
317176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        CGM.getModule(), IdentTy, /*isConstant*/ true,
318176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
3196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    DefaultOpenMPLocation->setUnnamedAddr(true);
3206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
322c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    llvm::Constant *Values[] = {Zero,
323c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                llvm::ConstantInt::get(CGM.Int32Ty, Flags),
324c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                Zero, Zero, DefaultOpenMPPSource};
3256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
3266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    DefaultOpenMPLocation->setInitializer(Init);
327176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation;
3286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return DefaultOpenMPLocation;
3296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return Entry;
3316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
3326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3330e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesllvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
3340e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                                 SourceLocation Loc,
3350e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                                 OpenMPLocationFlags Flags) {
3366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // If no debug info is generated - return global default location.
3376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
3386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Loc.isInvalid())
3390e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return getOrCreateDefaultLocation(Flags);
3406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(CGF.CurFn && "No function in current CodeGenFunction.");
3426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  llvm::Value *LocValue = nullptr;
3440e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
3450e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  if (I != OpenMPLocThreadIDMap.end())
346176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    LocValue = I->second.DebugLoc;
3470e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
3480e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // GetOpenMPThreadID was called before this routine.
3490e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  if (LocValue == nullptr) {
3506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // Generate "ident_t .kmpc_loc.addr;"
3516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr");
3526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
353176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
354176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    Elem.second.DebugLoc = AI;
3556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    LocValue = AI;
3566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
3586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
3590e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
3606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                             llvm::ConstantExpr::getSizeOf(IdentTy),
3616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                             CGM.PointerAlignInBytes);
3626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // char **psource = &.kmpc_loc_<flags>.addr.psource;
36533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *PSource = CGF.Builder.CreateConstInBoundsGEP2_32(IdentTy, LocValue, 0,
36633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                                         IdentField_PSource);
3676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
368c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
369c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (OMPDebugLoc == nullptr) {
370c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    SmallString<128> Buffer2;
371c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    llvm::raw_svector_ostream OS2(Buffer2);
372c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    // Build debug location
373c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
374c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS2 << ";" << PLoc.getFilename() << ";";
375c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (const FunctionDecl *FD =
376c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines            dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
377c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      OS2 << FD->getQualifiedNameAsString();
378c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
379c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
380c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
381c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
3826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // *psource = ";<File>;<Function>;<Line>;<Column>;;";
384c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  CGF.Builder.CreateStore(OMPDebugLoc, PSource);
385c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
3866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return LocValue;
3876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
3886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3890e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesllvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
3900e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                          SourceLocation Loc) {
3916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(CGF.CurFn && "No function in current CodeGenFunction.");
3926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
393176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::Value *ThreadID = nullptr;
394176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Check whether we've already cached a load of the thread id in this
395176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // function.
3960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
397176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (I != OpenMPLocThreadIDMap.end()) {
398176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ThreadID = I->second.ThreadID;
399176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (ThreadID != nullptr)
400176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return ThreadID;
401176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
402176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (auto OMPRegionInfo =
4030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines          dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
4043ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    if (OMPRegionInfo->getThreadIDVariable()) {
4050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      // Check if this an outlined function with thread id passed as argument.
4060e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
4070e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
4080e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      // If value loaded in entry block, cache it and use it everywhere in
4090e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      // function.
4100e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
4110e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
4120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        Elem.second.ThreadID = ThreadID;
4130e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      }
4140e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      return ThreadID;
415176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
4166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4170e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
4180e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // This is not an outlined function region - need to call __kmpc_int32
4190e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // kmpc_global_thread_num(ident_t *loc).
4200e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Generate thread id value and cache this value for use across the
4210e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // function.
4220e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
4230e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
4240e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  ThreadID =
4250e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
4260e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                          emitUpdateLocation(CGF, Loc));
4270e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
4280e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  Elem.second.ThreadID = ThreadID;
429176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return ThreadID;
4306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
4316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4320e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
4336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(CGF.CurFn && "No function in current CodeGenFunction.");
434176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (OpenMPLocThreadIDMap.count(CGF.CurFn))
435176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    OpenMPLocThreadIDMap.erase(CGF.CurFn);
4366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
4376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesllvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
4396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return llvm::PointerType::getUnqual(IdentTy);
4406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
4416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesllvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
4436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return llvm::PointerType::getUnqual(Kmpc_MicroTy);
4446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
4456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesllvm::Constant *
4470e2c34f92f00628d48968dfea096d36381f494cbStephen HinesCGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
4486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  llvm::Constant *RTLFn = nullptr;
4496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  switch (Function) {
4506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  case OMPRTL__kmpc_fork_call: {
4516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
4526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // microtask, ...);
453c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
454c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                                getKmpc_MicroPointerTy()};
4556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::FunctionType *FnTy =
456176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
4576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
4586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    break;
4596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  case OMPRTL__kmpc_global_thread_num: {
4616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
462c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
4636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    llvm::FunctionType *FnTy =
464176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
4656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
4666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    break;
4676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
468176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  case OMPRTL__kmpc_threadprivate_cached: {
469176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Build void *__kmpc_threadprivate_cached(ident_t *loc,
470176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // kmp_int32 global_tid, void *data, size_t size, void ***cache);
471176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
472176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                CGM.VoidPtrTy, CGM.SizeTy,
473176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
474176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::FunctionType *FnTy =
475176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
476176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
477176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
478176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
479176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  case OMPRTL__kmpc_critical: {
480176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
481176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // kmp_critical_name *crit);
482176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *TypeParams[] = {
483176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        getIdentTyPointerTy(), CGM.Int32Ty,
484176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::PointerType::getUnqual(KmpCriticalNameTy)};
485176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::FunctionType *FnTy =
486176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
487176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
488176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
489176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
490176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  case OMPRTL__kmpc_threadprivate_register: {
491176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Build void __kmpc_threadprivate_register(ident_t *, void *data,
492176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
493176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // typedef void *(*kmpc_ctor)(void *);
494176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    auto KmpcCtorTy =
495176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
496176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                /*isVarArg*/ false)->getPointerTo();
497176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // typedef void *(*kmpc_cctor)(void *, void *);
498176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
499176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    auto KmpcCopyCtorTy =
500176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
501176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                /*isVarArg*/ false)->getPointerTo();
502176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // typedef void (*kmpc_dtor)(void *);
503176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    auto KmpcDtorTy =
504176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
505176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines            ->getPointerTo();
506176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
507176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                              KmpcCopyCtorTy, KmpcDtorTy};
508176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
509176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                        /*isVarArg*/ false);
510176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
511176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
512176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
513176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  case OMPRTL__kmpc_end_critical: {
514176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
515176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // kmp_critical_name *crit);
516176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *TypeParams[] = {
517176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        getIdentTyPointerTy(), CGM.Int32Ty,
518176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::PointerType::getUnqual(KmpCriticalNameTy)};
519176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::FunctionType *FnTy =
520176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
521176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
522176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
523176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
5240e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPRTL__kmpc_cancel_barrier: {
5250e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
5260e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // global_tid);
5270e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
5280e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::FunctionType *FnTy =
5290e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
5300e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
5310e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    break;
5320e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
5330e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPRTL__kmpc_for_static_fini: {
5340e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
535176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
536176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::FunctionType *FnTy =
537176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
5380e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
539176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
540176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
541176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  case OMPRTL__kmpc_push_num_threads: {
542176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
543176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // kmp_int32 num_threads)
544176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
545176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                CGM.Int32Ty};
546176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::FunctionType *FnTy =
547176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
548176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
549176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
550176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
551176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  case OMPRTL__kmpc_serialized_parallel: {
552176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
553176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // global_tid);
554176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
555176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::FunctionType *FnTy =
556176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
557176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
558176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
559176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
560176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  case OMPRTL__kmpc_end_serialized_parallel: {
561176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
562176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // global_tid);
563176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
564176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::FunctionType *FnTy =
565176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
566176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
567176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
568176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
569176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  case OMPRTL__kmpc_flush: {
5700e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // Build void __kmpc_flush(ident_t *loc);
571176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
572176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::FunctionType *FnTy =
5730e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
574176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
575176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    break;
576176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
5770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPRTL__kmpc_master: {
5780e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
5790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
5800e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::FunctionType *FnTy =
5810e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
5820e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
5830e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    break;
5840e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
5850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPRTL__kmpc_end_master: {
5860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
5870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
5880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::FunctionType *FnTy =
5890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
5900e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
5910e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    break;
5920e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
5930e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPRTL__kmpc_omp_taskyield: {
5940e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
5950e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // int end_part);
5960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
5970e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::FunctionType *FnTy =
5980e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
5990e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
6000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    break;
6010e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
6020e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPRTL__kmpc_single: {
6030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
6040e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
6050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::FunctionType *FnTy =
6060e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
6070e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
6080e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    break;
6090e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
6100e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPRTL__kmpc_end_single: {
6110e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
6120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
6130e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    llvm::FunctionType *FnTy =
6140e2c34f92f00628d48968dfea096d36381f494cbStephen Hines        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
6150e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
6160e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    break;
6170e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
6183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  case OMPRTL__kmpc_omp_task_alloc: {
6193ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
6203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
6213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // kmp_routine_entry_t *task_entry);
6223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    assert(KmpRoutineEntryPtrTy != nullptr &&
6233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar           "Type kmp_routine_entry_t must be created.");
6243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
6253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
6263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Return void * and then cast to particular kmp_task_t type.
6273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::FunctionType *FnTy =
6283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
6293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
6303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    break;
6313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
6323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  case OMPRTL__kmpc_omp_task: {
6333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
6343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // *new_task);
6353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
6363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                CGM.VoidPtrTy};
6373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::FunctionType *FnTy =
6383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
6393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
6403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    break;
6413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
6423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  case OMPRTL__kmpc_copyprivate: {
6433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
6443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // kmp_int32 cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
6453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // kmp_int32 didit);
6463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
6473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto *CpyFnTy =
6483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
6493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
6503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
6513ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                CGM.Int32Ty};
6523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::FunctionType *FnTy =
6533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
6543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
6553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    break;
6563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
65733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  case OMPRTL__kmpc_reduce: {
65833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
65933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
66033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
66133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
66233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
66333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                               /*isVarArg=*/false);
66433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::Type *TypeParams[] = {
66533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
66633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
66733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::PointerType::getUnqual(KmpCriticalNameTy)};
66833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::FunctionType *FnTy =
66933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
67033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
67133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    break;
67233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
67333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  case OMPRTL__kmpc_reduce_nowait: {
67433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
67533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
67633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
67733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // *lck);
67833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
67933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
68033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                               /*isVarArg=*/false);
68133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::Type *TypeParams[] = {
68233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
68333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
68433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::PointerType::getUnqual(KmpCriticalNameTy)};
68533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::FunctionType *FnTy =
68633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
68733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
68833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    break;
68933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
69033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  case OMPRTL__kmpc_end_reduce: {
69133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
69233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // kmp_critical_name *lck);
69333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::Type *TypeParams[] = {
69433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        getIdentTyPointerTy(), CGM.Int32Ty,
69533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::PointerType::getUnqual(KmpCriticalNameTy)};
69633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::FunctionType *FnTy =
69733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
69833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
69933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    break;
70033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
70133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  case OMPRTL__kmpc_end_reduce_nowait: {
70233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
70333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // kmp_critical_name *lck);
70433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::Type *TypeParams[] = {
70533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        getIdentTyPointerTy(), CGM.Int32Ty,
70633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::PointerType::getUnqual(KmpCriticalNameTy)};
70733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::FunctionType *FnTy =
70833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
70933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    RTLFn =
71033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
71133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    break;
71233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
7136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return RTLFn;
7156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
716176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
7173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarllvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
7183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                                             bool IVSigned) {
7193ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  assert((IVSize == 32 || IVSize == 64) &&
7203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar         "IV size is not compatible with the omp runtime");
7213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
7223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                       : "__kmpc_for_static_init_4u")
7233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                           : (IVSigned ? "__kmpc_for_static_init_8"
7243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                       : "__kmpc_for_static_init_8u");
7253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
7263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto PtrTy = llvm::PointerType::getUnqual(ITy);
7273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::Type *TypeParams[] = {
7283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    getIdentTyPointerTy(),                     // loc
7293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CGM.Int32Ty,                               // tid
7303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CGM.Int32Ty,                               // schedtype
7313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
7323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    PtrTy,                                     // p_lower
7333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    PtrTy,                                     // p_upper
7343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    PtrTy,                                     // p_stride
7353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    ITy,                                       // incr
7363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    ITy                                        // chunk
7373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  };
7383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::FunctionType *FnTy =
7393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
7403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return CGM.CreateRuntimeFunction(FnTy, Name);
7413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
7423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
7433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarllvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
7443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                                            bool IVSigned) {
7453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  assert((IVSize == 32 || IVSize == 64) &&
7463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar         "IV size is not compatible with the omp runtime");
7473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto Name =
7483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      IVSize == 32
7493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
7503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
7513ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
7523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
7533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                               CGM.Int32Ty,           // tid
7543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                               CGM.Int32Ty,           // schedtype
7553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                               ITy,                   // lower
7563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                               ITy,                   // upper
7573ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                               ITy,                   // stride
7583ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                               ITy                    // chunk
7593ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  };
7603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::FunctionType *FnTy =
7613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
7623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return CGM.CreateRuntimeFunction(FnTy, Name);
7633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
7643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
7653ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarllvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
7663ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                                            bool IVSigned) {
7673ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  assert((IVSize == 32 || IVSize == 64) &&
7683ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar         "IV size is not compatible with the omp runtime");
7693ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto Name =
7703ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      IVSize == 32
7713ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
7723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
7733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
7743ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto PtrTy = llvm::PointerType::getUnqual(ITy);
7753ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::Type *TypeParams[] = {
7763ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    getIdentTyPointerTy(),                     // loc
7773ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CGM.Int32Ty,                               // tid
7783ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
7793ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    PtrTy,                                     // p_lower
7803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    PtrTy,                                     // p_upper
7813ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    PtrTy                                      // p_stride
7823ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  };
7833ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::FunctionType *FnTy =
7843ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
7853ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return CGM.CreateRuntimeFunction(FnTy, Name);
7863ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
7873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
788176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesllvm::Constant *
789176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesCGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
790176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Lookup the entry, lazily creating it if necessary.
7910e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
792176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                     Twine(CGM.getMangledName(VD)) + ".cache.");
793176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
794176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
7950e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesllvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
7960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                                     const VarDecl *VD,
7970e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                                     llvm::Value *VDAddr,
7980e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                                     SourceLocation Loc) {
799176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto VarTy = VDAddr->getType()->getPointerElementType();
8000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
801176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                         CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
802176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                         CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
803176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                         getOrCreateThreadPrivateCache(VD)};
804176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return CGF.EmitRuntimeCall(
8050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args);
806176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
807176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
8080e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitThreadPrivateVarInit(
809176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor,
810176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
811176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
812176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // library.
8130e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto OMPLoc = emitUpdateLocation(CGF, Loc);
8140e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
815176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                      OMPLoc);
816176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
817176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // to register constructor/destructor for variable.
818176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::Value *Args[] = {OMPLoc,
819176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                         CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy),
820176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                         Ctor, CopyCtor, Dtor};
8210e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(
8220e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
823176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
824176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
8250e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesllvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
826176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc,
827176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    bool PerformInit, CodeGenFunction *CGF) {
828176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  VD = VD->getDefinition(CGM.getContext());
829176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
830176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ThreadPrivateWithDefinition.insert(VD);
831176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    QualType ASTTy = VD->getType();
832176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
833176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
834176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    auto Init = VD->getAnyInitializer();
835176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (CGM.getLangOpts().CPlusPlus && PerformInit) {
836176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Generate function that re-emits the declaration's initializer into the
837176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // threadprivate copy of the variable VD
838176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CodeGenFunction CtorCGF(CGM);
839176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      FunctionArgList Args;
840176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
841176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                            /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
842176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Args.push_back(&Dst);
843176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
844176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
845176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
846176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          /*isVariadic=*/false);
847176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto FTy = CGM.getTypes().GetFunctionType(FI);
848176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto Fn = CGM.CreateGlobalInitOrDestructFunction(
849176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          FTy, ".__kmpc_global_ctor_.", Loc);
850176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
851176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                            Args, SourceLocation());
852176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto ArgVal = CtorCGF.EmitLoadOfScalar(
853176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          CtorCGF.GetAddrOfLocalVar(&Dst),
854176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          /*Volatile=*/false, CGM.PointerAlignInBytes,
855176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          CGM.getContext().VoidPtrTy, Dst.getLocation());
856176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto Arg = CtorCGF.Builder.CreatePointerCast(
857176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          ArgVal,
858176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy)));
859176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
860176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                               /*IsInitializer=*/true);
861176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ArgVal = CtorCGF.EmitLoadOfScalar(
862176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          CtorCGF.GetAddrOfLocalVar(&Dst),
863176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          /*Volatile=*/false, CGM.PointerAlignInBytes,
864176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          CGM.getContext().VoidPtrTy, Dst.getLocation());
865176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
866176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CtorCGF.FinishFunction();
867176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Ctor = Fn;
868176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
869176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (VD->getType().isDestructedType() != QualType::DK_none) {
870176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Generate function that emits destructor call for the threadprivate copy
871176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // of the variable VD
872176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CodeGenFunction DtorCGF(CGM);
873176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      FunctionArgList Args;
874176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
875176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                            /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
876176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Args.push_back(&Dst);
877176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
878176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
879176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
880176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          /*isVariadic=*/false);
881176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto FTy = CGM.getTypes().GetFunctionType(FI);
882176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto Fn = CGM.CreateGlobalInitOrDestructFunction(
883176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          FTy, ".__kmpc_global_dtor_.", Loc);
884176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
885176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                            SourceLocation());
886176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto ArgVal = DtorCGF.EmitLoadOfScalar(
887176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          DtorCGF.GetAddrOfLocalVar(&Dst),
888176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          /*Volatile=*/false, CGM.PointerAlignInBytes,
889176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          CGM.getContext().VoidPtrTy, Dst.getLocation());
890176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      DtorCGF.emitDestroy(ArgVal, ASTTy,
891176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                          DtorCGF.getDestroyer(ASTTy.isDestructedType()),
892176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                          DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
893176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      DtorCGF.FinishFunction();
894176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Dtor = Fn;
895176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
896176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Do not emit init function if it is not required.
897176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!Ctor && !Dtor)
898176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return nullptr;
899176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
900176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
901176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    auto CopyCtorTy =
902176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
903176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                /*isVarArg=*/false)->getPointerTo();
904176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Copying constructor for the threadprivate variable.
905176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Must be NULL - reserved by runtime, but currently it requires that this
906176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // parameter is always NULL. Otherwise it fires assertion.
907176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
908176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (Ctor == nullptr) {
909176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
910176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                            /*isVarArg=*/false)->getPointerTo();
911176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Ctor = llvm::Constant::getNullValue(CtorTy);
912176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
913176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (Dtor == nullptr) {
914176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
915176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                            /*isVarArg=*/false)->getPointerTo();
916176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Dtor = llvm::Constant::getNullValue(DtorTy);
917176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
918176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!CGF) {
919176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto InitFunctionTy =
920176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
921176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
922176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          InitFunctionTy, ".__omp_threadprivate_init_.");
923176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CodeGenFunction InitCGF(CGM);
924176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      FunctionArgList ArgList;
925176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
926176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                            CGM.getTypes().arrangeNullaryFunction(), ArgList,
927176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                            Loc);
9280e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
929176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      InitCGF.FinishFunction();
930176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return InitFunction;
931176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
9320e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
933176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
934176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return nullptr;
935176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
936176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
9370e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
9380e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                       llvm::Value *OutlinedFn,
9390e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                       llvm::Value *CapturedStruct) {
940176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
941176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::Value *Args[] = {
9420e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      emitUpdateLocation(CGF, Loc),
943176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CGF.Builder.getInt32(1), // Number of arguments after 'microtask' argument
944176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // (there is only one additional argument - 'context')
945176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
946176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CGF.EmitCastToVoidPtr(CapturedStruct)};
9470e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
948176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CGF.EmitRuntimeCall(RTLFn, Args);
949176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
950176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
9510e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitSerialCall(CodeGenFunction &CGF, SourceLocation Loc,
9520e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                     llvm::Value *OutlinedFn,
9530e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                     llvm::Value *CapturedStruct) {
9540e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto ThreadID = getThreadID(CGF, Loc);
955176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Build calls:
956176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // __kmpc_serialized_parallel(&Loc, GTid);
9570e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), ThreadID};
9580e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
9590e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                      Args);
960176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
961176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // OutlinedFn(&GTid, &zero, CapturedStruct);
9620e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
963176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto Int32Ty =
964176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
965176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr");
966176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
967176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct};
968176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
969176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
970176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // __kmpc_end_serialized_parallel(&Loc, GTid);
9710e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
9720e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(
9730e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
974176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
975176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
976176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// If we're inside an (outlined) parallel region, use the region info's
977176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// thread-ID variable (it is passed in a first argument of the outlined function
978176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
979176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// regular serial code region, get thread ID by calling kmp_int32
980176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
981176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// return the address of that temp.
9820e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesllvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
983176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                                  SourceLocation Loc) {
984176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (auto OMPRegionInfo =
985176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
9860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    if (OMPRegionInfo->getThreadIDVariable())
9873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
9880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
9890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto ThreadID = getThreadID(CGF, Loc);
990176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto Int32Ty =
991176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
992176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
993176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  CGF.EmitStoreOfScalar(ThreadID,
994176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                        CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty));
995176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
996176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return ThreadIDTemp;
997176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
998176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
999176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesllvm::Constant *
10000e2c34f92f00628d48968dfea096d36381f494cbStephen HinesCGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
1001176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                                             const llvm::Twine &Name) {
1002176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  SmallString<256> Buffer;
1003176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::raw_svector_ostream Out(Buffer);
1004176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  Out << Name;
1005176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto RuntimeName = Out.str();
1006176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1007176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (Elem.second) {
1008176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    assert(Elem.second->getType()->getPointerElementType() == Ty &&
1009176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines           "OMP internal variable has different type than requested");
1010176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return &*Elem.second;
1011176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
1012176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
1013176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return Elem.second = new llvm::GlobalVariable(
1014176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines             CGM.getModule(), Ty, /*IsConstant*/ false,
1015176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines             llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1016176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines             Elem.first());
1017176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
1018176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
10190e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesllvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
1020176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::Twine Name(".gomp_critical_user_", CriticalName);
10210e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
1022176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
1023176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
102433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarnamespace {
102533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarclass CallEndCleanup : public EHScopeStack::Cleanup {
102633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarpublic:
102733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  typedef ArrayRef<llvm::Value *> CleanupValuesTy;
102833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarprivate:
102933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  llvm::Value *Callee;
103033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  llvm::SmallVector<llvm::Value *, 8> Args;
103133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
103233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarpublic:
103333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CallEndCleanup(llvm::Value *Callee, CleanupValuesTy Args)
103433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      : Callee(Callee), Args(Args.begin(), Args.end()) {}
103533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
103633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.EmitRuntimeCall(Callee, Args);
103733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
103833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar};
103933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar} // namespace
104033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
104133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarvoid CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
104233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                         StringRef CriticalName,
104333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                         const RegionCodeGenTy &CriticalOpGen,
104433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                         SourceLocation Loc) {
10450e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // __kmpc_critical(ident_t *, gtid, Lock);
10460e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // CriticalOpGen();
10470e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // __kmpc_end_critical(ident_t *, gtid, Lock);
10480e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Prepare arguments and build a call to __kmpc_critical
104933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  {
105033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CodeGenFunction::RunCleanupsScope Scope(CGF);
105133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
105233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                           getCriticalRegionLock(CriticalName)};
105333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
105433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // Build a call to __kmpc_end_critical
105533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.EHStack.pushCleanup<CallEndCleanup>(
105633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
105733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::makeArrayRef(Args));
105833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    emitInlinedDirective(CGF, CriticalOpGen);
105933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
1060176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
1061176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
10620e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesstatic void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
106333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                       const RegionCodeGenTy &BodyOpGen) {
10640e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *CallBool = CGF.EmitScalarConversion(
10650e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      IfCond,
10660e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
10670e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      CGF.getContext().BoolTy);
10680e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
10690e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
10700e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto *ContBlock = CGF.createBasicBlock("omp_if.end");
10710e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Generate the branch (If-stmt)
10720e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
10730e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitBlock(ThenBlock);
107433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, BodyOpGen);
10750e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Emit the rest of bblocks/branches
10760e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitBranch(ContBlock);
10770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitBlock(ContBlock, true);
1078176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
1079176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
10800e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
108133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                       const RegionCodeGenTy &MasterOpGen,
10820e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                       SourceLocation Loc) {
10830e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // if(__kmpc_master(ident_t *, gtid)) {
10840e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  //   MasterOpGen();
10850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  //   __kmpc_end_master(ident_t *, gtid);
10860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // }
10870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Prepare arguments and build a call to __kmpc_master
10880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
10890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto *IsMaster =
10900e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
109133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  emitIfStmt(CGF, IsMaster, [&](CodeGenFunction &CGF) -> void {
109233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CodeGenFunction::RunCleanupsScope Scope(CGF);
109333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.EHStack.pushCleanup<CallEndCleanup>(
109433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
109533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::makeArrayRef(Args));
109633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    MasterOpGen(CGF);
10970e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  });
1098176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
1099176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
11000e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11010e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                        SourceLocation Loc) {
11020e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
11030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *Args[] = {
11040e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
11050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
11060e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
11070e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
11080e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
11093ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarstatic llvm::Value *emitCopyprivateCopyFunction(
111033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CodeGenModule &CGM, llvm::Type *ArgsType,
111133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
111233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
11133ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto &C = CGM.getContext();
11143ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // void copy_func(void *LHSArg, void *RHSArg);
11153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  FunctionArgList Args;
11163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
11173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                           C.VoidPtrTy);
11183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
11193ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                           C.VoidPtrTy);
11203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  Args.push_back(&LHSArg);
11213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  Args.push_back(&RHSArg);
11223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  FunctionType::ExtInfo EI;
11233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
11243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      C.VoidTy, Args, EI, /*isVariadic=*/false);
11253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *Fn = llvm::Function::Create(
11263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
11273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      ".omp.copyprivate.copy_func", &CGM.getModule());
11283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
11293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CodeGenFunction CGF(CGM);
11303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
113133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // Dest = (void*[n])(LHSArg);
11323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Src = (void*[n])(RHSArg);
11333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
11353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                    CGF.PointerAlignInBytes),
11363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      ArgsType);
11373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
11393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                    CGF.PointerAlignInBytes),
11403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      ArgsType);
11413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // *(Type0*)Dst[0] = *(Type0*)Src[0];
11423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // *(Type1*)Dst[1] = *(Type1*)Src[1];
11433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // ...
11443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // *(Typen*)Dst[n] = *(Typen*)Src[n];
11453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
114633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    auto *DestAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
114733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGF.Builder.CreateAlignedLoad(
114833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            CGF.Builder.CreateStructGEP(nullptr, LHS, I),
114933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            CGM.PointerAlignInBytes),
115033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
115133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    auto *SrcAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
115233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGF.Builder.CreateAlignedLoad(
115333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            CGF.Builder.CreateStructGEP(nullptr, RHS, I),
115433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            CGM.PointerAlignInBytes),
115533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
115633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.EmitOMPCopy(CGF, CopyprivateVars[I]->getType(), DestAddr, SrcAddr,
115733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                    cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()),
115833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                    cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
115933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                    AssignmentOps[I]);
11603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
11613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.FinishFunction();
11623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return Fn;
11633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
11643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
11650e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
116633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                       const RegionCodeGenTy &SingleOpGen,
11673ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                       SourceLocation Loc,
11683ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                       ArrayRef<const Expr *> CopyprivateVars,
11693ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                       ArrayRef<const Expr *> SrcExprs,
11703ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                       ArrayRef<const Expr *> DstExprs,
11713ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                       ArrayRef<const Expr *> AssignmentOps) {
11723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  assert(CopyprivateVars.size() == SrcExprs.size() &&
11733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar         CopyprivateVars.size() == DstExprs.size() &&
11743ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar         CopyprivateVars.size() == AssignmentOps.size());
11753ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto &C = CGM.getContext();
11763ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // int32 did_it = 0;
11770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // if(__kmpc_single(ident_t *, gtid)) {
11780e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  //   SingleOpGen();
11790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  //   __kmpc_end_single(ident_t *, gtid);
11803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //   did_it = 1;
11810e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // }
11823ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
11833ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // <copy_func>, did_it);
11843ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
11853ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::AllocaInst *DidIt = nullptr;
11863ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (!CopyprivateVars.empty()) {
11873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // int32 did_it = 0;
11883ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
11893ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
11903ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CGF.InitTempAlloca(DidIt, CGF.Builder.getInt32(0));
11913ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
11920e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Prepare arguments and build a call to __kmpc_single
11930e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
11940e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto *IsSingle =
11950e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
119633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  emitIfStmt(CGF, IsSingle, [&](CodeGenFunction &CGF) -> void {
119733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CodeGenFunction::RunCleanupsScope Scope(CGF);
119833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.EHStack.pushCleanup<CallEndCleanup>(
119933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
120033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::makeArrayRef(Args));
120133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    SingleOpGen(CGF);
12023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    if (DidIt) {
12033ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      // did_it = 1;
12043ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(1), DidIt,
12053ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                     DidIt->getAlignment());
12063ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    }
12070e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  });
12083ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
12093ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // <copy_func>, did_it);
12103ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (DidIt) {
12113ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
12123ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto CopyprivateArrayTy =
12133ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
12143ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                               /*IndexTypeQuals=*/0);
12153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Create a list of all private variables for copyprivate.
12163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto *CopyprivateList =
12173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
12183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
121933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      auto *Elem = CGF.Builder.CreateStructGEP(
122033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          CopyprivateList->getAllocatedType(), CopyprivateList, I);
12213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.Builder.CreateAlignedStore(
12223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
12233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar              CGF.EmitLValue(CopyprivateVars[I]).getAddress(), CGF.VoidPtrTy),
12243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          Elem, CGM.PointerAlignInBytes);
12253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    }
12263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Build function that copies private values from single region to all other
12273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // threads in the corresponding parallel region.
12283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto *CpyFn = emitCopyprivateCopyFunction(
12293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
123033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
12313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto *BufSize = CGF.Builder.getInt32(
12323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity());
12333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto *CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
12343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                                               CGF.VoidPtrTy);
12353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto *DidItVal =
12363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        CGF.Builder.CreateAlignedLoad(DidIt, CGF.PointerAlignInBytes);
12373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::Value *Args[] = {
12383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        emitUpdateLocation(CGF, Loc), // ident_t *<loc>
12393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        getThreadID(CGF, Loc),        // i32 <gtid>
12403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        BufSize,                      // i32 <buf_size>
12413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        CL,                           // void *<copyprivate list>
12423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        CpyFn,                        // void (*) (void *, void *) <copy_func>
12433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        DidItVal                      // i32 did_it
12443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    };
12453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
12463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
12470e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
12480e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
12490e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
125033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                      OpenMPDirectiveKind Kind) {
12510e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Build call __kmpc_cancel_barrier(loc, thread_id);
125233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
125333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  if (Kind == OMPD_for) {
125433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    Flags =
125533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR);
125633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  } else if (Kind == OMPD_sections) {
125733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    Flags = static_cast<OpenMPLocationFlags>(Flags |
125833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                             OMP_IDENT_BARRIER_IMPL_SECTIONS);
125933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  } else if (Kind == OMPD_single) {
126033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    Flags =
126133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE);
126233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  } else if (Kind == OMPD_barrier) {
126333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL);
126433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  } else {
126533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL);
126633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
12670e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Build call __kmpc_cancel_barrier(loc, thread_id);
12680e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this
12690e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // one provides the same functionality and adds initial support for
12700e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // cancellation constructs introduced in OpenMP 4.0. __kmpc_cancel_barrier()
12710e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // is provided default by the runtime library so it safe to make such
12720e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // replacement.
12730e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
12740e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                         getThreadID(CGF, Loc)};
12750e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
12760e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
12770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
12780e2c34f92f00628d48968dfea096d36381f494cbStephen Hines/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
12790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines/// the enum sched_type in kmp.h).
12800e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesenum OpenMPSchedType {
12810e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Lower bound for default (unordered) versions.
12820e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_sch_lower = 32,
12830e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_sch_static_chunked = 33,
12840e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_sch_static = 34,
12850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_sch_dynamic_chunked = 35,
12860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_sch_guided_chunked = 36,
12870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_sch_runtime = 37,
12880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_sch_auto = 38,
12890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Lower bound for 'ordered' versions.
12900e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_ord_lower = 64,
12910e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  /// \brief Lower bound for 'nomerge' versions.
12920e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OMP_nm_lower = 160,
12930e2c34f92f00628d48968dfea096d36381f494cbStephen Hines};
12940e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
12950e2c34f92f00628d48968dfea096d36381f494cbStephen Hines/// \brief Map the OpenMP loop schedule to the runtime enumeration.
12960e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesstatic OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
12970e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                          bool Chunked) {
12980e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  switch (ScheduleKind) {
12990e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPC_SCHEDULE_static:
13000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return Chunked ? OMP_sch_static_chunked : OMP_sch_static;
13010e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPC_SCHEDULE_dynamic:
13020e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return OMP_sch_dynamic_chunked;
13030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPC_SCHEDULE_guided:
13040e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return OMP_sch_guided_chunked;
13050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPC_SCHEDULE_auto:
13060e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return OMP_sch_auto;
13070e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPC_SCHEDULE_runtime:
13080e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return OMP_sch_runtime;
13090e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  case OMPC_SCHEDULE_unknown:
13100e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    assert(!Chunked && "chunk was specified but schedule kind not known");
13110e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    return OMP_sch_static;
13120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  }
13130e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm_unreachable("Unexpected runtime schedule");
13140e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
13150e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
13160e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesbool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
13170e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                         bool Chunked) const {
13180e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
13190e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  return Schedule == OMP_sch_static;
13200e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
13210e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
13220e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesbool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
13230e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  auto Schedule = getRuntimeSchedule(ScheduleKind, /* Chunked */ false);
13240e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
13250e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  return Schedule != OMP_sch_static;
13260e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
13270e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
13280e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
13290e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                  OpenMPScheduleClauseKind ScheduleKind,
13300e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                  unsigned IVSize, bool IVSigned,
13310e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                  llvm::Value *IL, llvm::Value *LB,
13320e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                  llvm::Value *UB, llvm::Value *ST,
13330e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                  llvm::Value *Chunk) {
13340e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunk != nullptr);
13353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked) {
13363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Call __kmpc_dispatch_init(
13373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    //          ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
13383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    //          kmp_int[32|64] lower, kmp_int[32|64] upper,
13393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    //          kmp_int[32|64] stride, kmp_int[32|64] chunk);
13403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
13413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // If the Chunk was not specified in the clause - use default value 1.
13423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    if (Chunk == nullptr)
13433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      Chunk = CGF.Builder.getIntN(IVSize, 1);
13443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
13453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            getThreadID(CGF, Loc),
13463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            CGF.Builder.getInt32(Schedule), // Schedule type
13473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            CGF.Builder.getIntN(IVSize, 0), // Lower
13483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            UB,                             // Upper
13493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            CGF.Builder.getIntN(IVSize, 1), // Stride
13503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            Chunk                           // Chunk
13513ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    };
13523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
13533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  } else {
13543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Call __kmpc_for_static_init(
13553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    //          ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
13563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    //          kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
13573ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    //          kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
13583ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    //          kmp_int[32|64] incr, kmp_int[32|64] chunk);
13593ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    if (Chunk == nullptr) {
13603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      assert(Schedule == OMP_sch_static &&
13613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar             "expected static non-chunked schedule");
13623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      // If the Chunk was not specified in the clause - use default value 1.
13633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      Chunk = CGF.Builder.getIntN(IVSize, 1);
13643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    } else
13653ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      assert(Schedule == OMP_sch_static_chunked &&
13663ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar             "expected static chunked schedule");
13673ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
13683ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            getThreadID(CGF, Loc),
13693ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            CGF.Builder.getInt32(Schedule), // Schedule type
13703ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            IL,                             // &isLastIter
13713ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            LB,                             // &LB
13723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            UB,                             // &UB
13733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            ST,                             // &Stride
13743ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            CGF.Builder.getIntN(IVSize, 1), // Incr
13753ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                            Chunk                           // Chunk
13763ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    };
13773ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
13783ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
13790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
13800e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
13810e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitForFinish(CodeGenFunction &CGF, SourceLocation Loc,
13820e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                    OpenMPScheduleClauseKind ScheduleKind) {
13830e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  assert((ScheduleKind == OMPC_SCHEDULE_static ||
13840e2c34f92f00628d48968dfea096d36381f494cbStephen Hines          ScheduleKind == OMPC_SCHEDULE_unknown) &&
13850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines         "Non-static schedule kinds are not yet implemented");
138633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  (void)ScheduleKind;
13870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
13880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
13890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                         getThreadID(CGF, Loc)};
13900e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
13910e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                      Args);
13920e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
13930e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
13943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarllvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
13953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                          SourceLocation Loc, unsigned IVSize,
13963ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                          bool IVSigned, llvm::Value *IL,
13973ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                          llvm::Value *LB, llvm::Value *UB,
13983ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                          llvm::Value *ST) {
13993ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Call __kmpc_dispatch_next(
14003ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //          ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
14013ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //          kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
14023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //          kmp_int[32|64] *p_stride);
14033ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::Value *Args[] = {
14043ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
14053ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      IL, // &isLastIter
14063ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      LB, // &Lower
14073ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      UB, // &Upper
14083ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      ST  // &Stride
14093ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  };
14103ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::Value *Call =
14113ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
14123ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return CGF.EmitScalarConversion(
14133ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
14143ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.getContext().BoolTy);
14153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
14163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
14170e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
14180e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                           llvm::Value *NumThreads,
14190e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                           SourceLocation Loc) {
1420176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
1421176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::Value *Args[] = {
14220e2c34f92f00628d48968dfea096d36381f494cbStephen Hines      emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1423176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
14240e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
14250e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                      Args);
1426176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
1427176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
14280e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesvoid CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
14290e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                                SourceLocation Loc) {
14300e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  // Build call void __kmpc_flush(ident_t *loc)
14310e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
14320e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                      emitUpdateLocation(CGF, Loc));
14330e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
14340e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
14353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarnamespace {
14363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/// \brief Indexes of fields for type kmp_task_t.
14373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarenum KmpTaskTFields {
14383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \brief List of shared variables.
14393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  KmpTaskTShareds,
14403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \brief Task routine.
14413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  KmpTaskTRoutine,
14423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \brief Partition id for the untied tasks.
14433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  KmpTaskTPartId,
14443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  /// \brief Function with call of destructors for private variables.
14453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  KmpTaskTDestructors,
14463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar};
14473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar} // namespace
14483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
14493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarvoid CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
14503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (!KmpRoutineEntryPtrTy) {
14513ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
14523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    auto &C = CGM.getContext();
14533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
14543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    FunctionProtoType::ExtProtoInfo EPI;
14553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    KmpRoutineEntryPtrQTy = C.getPointerType(
14563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
14573ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
14583ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  }
14593ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
14603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
14613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarstatic void addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
14623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                 QualType FieldTy) {
14633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *Field = FieldDecl::Create(
14643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
14653ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
14663ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
14673ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  Field->setAccess(AS_public);
14683ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  DC->addDecl(Field);
14693ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
14703ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
14713ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarstatic QualType createKmpTaskTRecordDecl(CodeGenModule &CGM,
14723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                         QualType KmpInt32Ty,
14733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                         QualType KmpRoutineEntryPointerQTy) {
14743ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto &C = CGM.getContext();
14753ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Build struct kmp_task_t {
14763ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //         void *              shareds;
14773ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //         kmp_routine_entry_t routine;
14783ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //         kmp_int32           part_id;
14793ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //         kmp_routine_entry_t destructors;
14803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //         /*  private vars  */
14813ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  //       };
14823ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *RD = C.buildImplicitRecord("kmp_task_t");
14833ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  RD->startDefinition();
14843ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  addFieldToRecordDecl(C, RD, C.VoidPtrTy);
14853ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
14863ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  addFieldToRecordDecl(C, RD, KmpInt32Ty);
14873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
14883ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // TODO: add private fields.
14893ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  RD->completeDefinition();
14903ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return C.getRecordType(RD);
14913ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
14923ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
14933ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/// \brief Emit a proxy function which accepts kmp_task_t as the second
14943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/// argument.
14953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/// \code
14963ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
14973ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar///   TaskFunction(gtid, tt->part_id, tt->shareds);
14983ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar///   return 0;
14993ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/// }
15003ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/// \endcode
15013ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarstatic llvm::Value *
15023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga NainaremitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
15033ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                      QualType KmpInt32Ty, QualType KmpTaskTPtrQTy,
150433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                      QualType SharedsPtrTy, llvm::Value *TaskFunction,
150533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                      llvm::Type *KmpTaskTTy) {
15063ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto &C = CGM.getContext();
15073ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  FunctionArgList Args;
15083ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
15093ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
15103ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                /*Id=*/nullptr, KmpTaskTPtrQTy);
15113ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  Args.push_back(&GtidArg);
15123ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  Args.push_back(&TaskTypeArg);
15133ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  FunctionType::ExtInfo Info;
15143ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto &TaskEntryFnInfo =
15153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
15163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                                    /*isVariadic=*/false);
15173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
15183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *TaskEntry =
15193ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
15203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                             ".omp_task_entry.", &CGM.getModule());
15213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskEntryFnInfo, TaskEntry);
15223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CodeGenFunction CGF(CGM);
15233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.disableDebugInfo();
15243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
15253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
15263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // TaskFunction(gtid, tt->part_id, tt->shareds);
15273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *GtidParam = CGF.EmitLoadOfScalar(
15283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false,
15293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
15303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto TaskTypeArgAddr = CGF.EmitLoadOfScalar(
15313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.GetAddrOfLocalVar(&TaskTypeArg), /*Volatile=*/false,
15323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGM.PointerAlignInBytes, KmpTaskTPtrQTy, Loc);
153333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *PartidPtr = CGF.Builder.CreateStructGEP(KmpTaskTTy, TaskTypeArgAddr,
15343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                                /*Idx=*/KmpTaskTPartId);
15353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *PartidParam = CGF.EmitLoadOfScalar(
15363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      PartidPtr, /*Volatile=*/false,
15373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
153833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *SharedsPtr = CGF.Builder.CreateStructGEP(KmpTaskTTy, TaskTypeArgAddr,
15393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                                 /*Idx=*/KmpTaskTShareds);
15403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *SharedsParam =
15413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.EmitLoadOfScalar(SharedsPtr, /*Volatile=*/false,
15423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                           CGM.PointerAlignInBytes, C.VoidPtrTy, Loc);
15433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::Value *CallArgs[] = {
15443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      GtidParam, PartidParam,
15453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
15463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          SharedsParam, CGF.ConvertTypeForMem(SharedsPtrTy))};
15473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
15483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.EmitStoreThroughLValue(
15493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      RValue::get(CGF.Builder.getInt32(/*C=*/0)),
15503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.MakeNaturalAlignAddrLValue(CGF.ReturnValue, KmpInt32Ty));
15513ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.FinishFunction();
15523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  return TaskEntry;
15533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
15543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
15553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarvoid CGOpenMPRuntime::emitTaskCall(
15563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CodeGenFunction &CGF, SourceLocation Loc, bool Tied,
15573ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
15583ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds) {
15593ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto &C = CGM.getContext();
15603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
15613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Build type kmp_routine_entry_t (if not built yet).
15623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  emitKmpRoutineEntryT(KmpInt32Ty);
15633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Build particular struct kmp_task_t for the given task.
15643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto KmpTaskQTy =
15653ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy);
15663ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  QualType KmpTaskTPtrQTy = C.getPointerType(KmpTaskQTy);
156733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *KmpTaskTTy = CGF.ConvertType(KmpTaskQTy);
156833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *KmpTaskTPtrTy = KmpTaskTTy->getPointerTo();
15693ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto KmpTaskTySize = CGM.getSize(C.getTypeSizeInChars(KmpTaskQTy));
15703ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  QualType SharedsPtrTy = C.getPointerType(SharedsTy);
15713ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
15723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
15733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // kmp_task_t *tt);
157433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *TaskEntry =
157533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      emitProxyTaskFunction(CGM, Loc, KmpInt32Ty, KmpTaskTPtrQTy, SharedsPtrTy,
157633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                            TaskFunction, KmpTaskTTy);
15773ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
15783ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
15793ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
15803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // kmp_routine_entry_t *task_entry);
15813ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Task flags. Format is taken from
15823ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
15833ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // description of kmp_tasking_flags struct.
15843ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  const unsigned TiedFlag = 0x1;
15853ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  const unsigned FinalFlag = 0x2;
15863ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  unsigned Flags = Tied ? TiedFlag : 0;
15873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *TaskFlags =
15883ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      Final.getPointer()
15893ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          ? CGF.Builder.CreateSelect(Final.getPointer(),
15903ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                     CGF.Builder.getInt32(FinalFlag),
15913ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                     CGF.Builder.getInt32(/*C=*/0))
15923ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
15933ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
15943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto SharedsSize = C.getTypeSizeInChars(SharedsTy);
15953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
15963ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                              getThreadID(CGF, Loc), TaskFlags, KmpTaskTySize,
15973ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                              CGM.getSize(SharedsSize),
15983ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                              CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
15993ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                  TaskEntry, KmpRoutineEntryPtrTy)};
16003ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *NewTask = CGF.EmitRuntimeCall(
16013ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
16023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  auto *NewTaskNewTaskTTy =
16033ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(NewTask, KmpTaskTPtrTy);
16043ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Fill the data in the resulting kmp_task_t record.
16053ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Copy shareds if there are any.
16063ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  if (!SharedsTy->getAsStructureType()->getDecl()->field_empty())
16073ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar    CGF.EmitAggregateCopy(
16083ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        CGF.EmitLoadOfScalar(
160933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            CGF.Builder.CreateStructGEP(KmpTaskTTy, NewTaskNewTaskTTy,
16103ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                        /*Idx=*/KmpTaskTShareds),
16113ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar            /*Volatile=*/false, CGM.PointerAlignInBytes, SharedsPtrTy, Loc),
16123ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar        Shareds, SharedsTy);
16133ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // TODO: generate function with destructors for privates.
16143ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Provide pointer to function with destructors for privates.
16153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.Builder.CreateAlignedStore(
16163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      llvm::ConstantPointerNull::get(
16173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar          cast<llvm::PointerType>(KmpRoutineEntryPtrTy)),
161833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGF.Builder.CreateStructGEP(KmpTaskTTy, NewTaskNewTaskTTy,
16193ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                                  /*Idx=*/KmpTaskTDestructors),
16203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar      CGM.PointerAlignInBytes);
16213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
16223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
16233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // libcall.
16243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
16253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // *new_task);
16263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  llvm::Value *TaskArgs[] = {emitUpdateLocation(CGF, Loc),
16273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar                             getThreadID(CGF, Loc), NewTask};
16283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  // TODO: add check for untied tasks.
16293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar  CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
16303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar}
16313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar
163233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarstatic llvm::Value *emitReductionFunction(CodeGenModule &CGM,
163333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          llvm::Type *ArgsType,
163433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          ArrayRef<const Expr *> LHSExprs,
163533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          ArrayRef<const Expr *> RHSExprs,
163633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                          ArrayRef<const Expr *> ReductionOps) {
163733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto &C = CGM.getContext();
163833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
163933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // void reduction_func(void *LHSArg, void *RHSArg);
164033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  FunctionArgList Args;
164133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
164233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                           C.VoidPtrTy);
164333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
164433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                           C.VoidPtrTy);
164533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  Args.push_back(&LHSArg);
164633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  Args.push_back(&RHSArg);
164733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  FunctionType::ExtInfo EI;
164833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
164933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      C.VoidTy, Args, EI, /*isVariadic=*/false);
165033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *Fn = llvm::Function::Create(
165133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
165233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      ".omp.reduction.reduction_func", &CGM.getModule());
165333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
165433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CodeGenFunction CGF(CGM);
165533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
165633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
165733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // Dst = (void*[n])(LHSArg);
165833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // Src = (void*[n])(RHSArg);
165933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
166033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
166133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    CGF.PointerAlignInBytes),
166233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      ArgsType);
166333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
166433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
166533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    CGF.PointerAlignInBytes),
166633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      ArgsType);
166733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
166833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
166933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
167033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
167133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CodeGenFunction::OMPPrivateScope Scope(CGF);
167233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I) {
167333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    Scope.addPrivate(
167433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()),
167533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        [&]() -> llvm::Value *{
167633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
167733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              CGF.Builder.CreateAlignedLoad(
167833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                  CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, RHS, I),
167933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                  CGM.PointerAlignInBytes),
168033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              CGF.ConvertTypeForMem(C.getPointerType(RHSExprs[I]->getType())));
168133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        });
168233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    Scope.addPrivate(
168333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()),
168433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        [&]() -> llvm::Value *{
168533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
168633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              CGF.Builder.CreateAlignedLoad(
168733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                  CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, LHS, I),
168833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                  CGM.PointerAlignInBytes),
168933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              CGF.ConvertTypeForMem(C.getPointerType(LHSExprs[I]->getType())));
169033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        });
169133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
169233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  Scope.Privatize();
169333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  for (auto *E : ReductionOps) {
169433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.EmitIgnoredExpr(E);
169533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
169633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  Scope.ForceCleanup();
169733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.FinishFunction();
169833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  return Fn;
1699176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
17000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
170133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarvoid CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
170233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    ArrayRef<const Expr *> LHSExprs,
170333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    ArrayRef<const Expr *> RHSExprs,
170433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    ArrayRef<const Expr *> ReductionOps,
170533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                    bool WithNowait) {
170633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // Next code should be emitted for reduction:
170733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //
170833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // static kmp_critical_name lock = { 0 };
170933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //
171033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
171133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
171233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
171333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
171433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  *(Type<n>-1*)rhs[<n>-1]);
171533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // }
171633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //
171733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // ...
171833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
171933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
172033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // RedList, reduce_func, &<lock>)) {
172133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // case 1:
172233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
172333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
172433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
172533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
172633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // break;
172733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // case 2:
172833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
172933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
173033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
173133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // break;
173233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // default:;
173333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // }
173433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
173533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto &C = CGM.getContext();
173633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
173733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // 1. Build a list of reduction variables.
173833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
173933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  llvm::APInt ArraySize(/*unsigned int numBits=*/32, RHSExprs.size());
174033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  QualType ReductionArrayTy =
174133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
174233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                             /*IndexTypeQuals=*/0);
174333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *ReductionList =
174433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
174533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I) {
174633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    auto *Elem = CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, ReductionList, I);
174733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.Builder.CreateAlignedStore(
174833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
174933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            CGF.EmitLValue(RHSExprs[I]).getAddress(), CGF.VoidPtrTy),
175033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        Elem, CGM.PointerAlignInBytes);
175133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
175233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
175333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // 2. Emit reduce_func().
175433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *ReductionFn = emitReductionFunction(
175533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), LHSExprs,
175633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      RHSExprs, ReductionOps);
175733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
175833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // 3. Create static kmp_critical_name lock = { 0 };
175933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *Lock = getCriticalRegionLock(".reduction");
176033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
176133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
176233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // RedList, reduce_func, &<lock>);
176333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *IdentTLoc = emitUpdateLocation(
176433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGF, Loc,
176533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
176633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *ThreadId = getThreadID(CGF, Loc);
176733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *ReductionArrayTySize = llvm::ConstantInt::get(
176833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGM.SizeTy, C.getTypeSizeInChars(ReductionArrayTy).getQuantity());
176933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList,
177033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                                             CGF.VoidPtrTy);
177133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  llvm::Value *Args[] = {
177233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      IdentTLoc,                             // ident_t *<loc>
177333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      ThreadId,                              // i32 <gtid>
177433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
177533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      ReductionArrayTySize,                  // size_type sizeof(RedList)
177633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      RL,                                    // void *RedList
177733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      ReductionFn, // void (*) (void *, void *) <reduce_func>
177833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      Lock         // kmp_critical_name *&<lock>
177933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  };
178033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto Res = CGF.EmitRuntimeCall(
178133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
178233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                       : OMPRTL__kmpc_reduce),
178333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      Args);
178433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
178533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // 5. Build switch(res)
178633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
178733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
178833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
178933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // 6. Build case 1:
179033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
179133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
179233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
179333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
179433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // break;
179533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
179633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
179733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.EmitBlock(Case1BB);
179833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
179933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  {
180033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CodeGenFunction::RunCleanupsScope Scope(CGF);
180133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
180233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    llvm::Value *EndArgs[] = {
180333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        IdentTLoc, // ident_t *<loc>
180433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        ThreadId,  // i32 <gtid>
180533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        Lock       // kmp_critical_name *&<lock>
180633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    };
180733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CGF.EHStack.pushCleanup<CallEndCleanup>(
180833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        NormalAndEHCleanup,
180933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
181033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                         : OMPRTL__kmpc_end_reduce),
181133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        llvm::makeArrayRef(EndArgs));
181233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    for (auto *E : ReductionOps) {
181333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      CGF.EmitIgnoredExpr(E);
181433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    }
181533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
181633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
181733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.EmitBranch(DefaultBB);
181833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
181933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // 7. Build case 2:
182033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
182133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
182233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  //  ...
182333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  // break;
182433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
182533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
182633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.EmitBlock(Case2BB);
182733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
182833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  {
182933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    CodeGenFunction::RunCleanupsScope Scope(CGF);
183033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    auto I = LHSExprs.begin();
183133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    for (auto *E : ReductionOps) {
183233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      const Expr *XExpr = nullptr;
183333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      const Expr *EExpr = nullptr;
183433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      const Expr *UpExpr = nullptr;
183533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      BinaryOperatorKind BO = BO_Comma;
183633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      // Try to emit update expression as a simple atomic.
183733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      if (auto *ACO = dyn_cast<AbstractConditionalOperator>(E)) {
183833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        // If this is a conditional operator, analyze it's condition for
183933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        // min/max reduction operator.
184033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        E = ACO->getCond();
184133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      }
184233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      if (auto *BO = dyn_cast<BinaryOperator>(E)) {
184333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        if (BO->getOpcode() == BO_Assign) {
184433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          XExpr = BO->getLHS();
184533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          UpExpr = BO->getRHS();
184633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        }
184733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      }
184833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      // Analyze RHS part of the whole expression.
184933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      if (UpExpr) {
185033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        if (auto *BORHS =
185133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                dyn_cast<BinaryOperator>(UpExpr->IgnoreParenImpCasts())) {
185233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          EExpr = BORHS->getRHS();
185333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          BO = BORHS->getOpcode();
185433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        }
185533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      }
185633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      if (XExpr) {
185733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
185833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        LValue X = CGF.EmitLValue(XExpr);
185933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        RValue E;
186033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        if (EExpr)
186133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          E = CGF.EmitAnyExpr(EExpr);
186233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        CGF.EmitOMPAtomicSimpleUpdateExpr(
186333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
186433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            [&CGF, UpExpr, VD](RValue XRValue) {
186533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
186633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              PrivateScope.addPrivate(
186733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                  VD, [&CGF, VD, XRValue]() -> llvm::Value *{
186833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                    auto *LHSTemp = CGF.CreateMemTemp(VD->getType());
186933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                    CGF.EmitStoreThroughLValue(
187033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                        XRValue,
187133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                        CGF.MakeNaturalAlignAddrLValue(LHSTemp, VD->getType()));
187233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                    return LHSTemp;
187333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                  });
187433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              (void)PrivateScope.Privatize();
187533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar              return CGF.EmitAnyExpr(UpExpr);
187633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar            });
187733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      } else {
187833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        // Emit as a critical region.
187933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        emitCriticalRegion(CGF, ".atomic_reduction", [E](CodeGenFunction &CGF) {
188033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar          CGF.EmitIgnoredExpr(E);
188133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar        }, Loc);
188233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      }
188333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar      ++I;
188433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar    }
188533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  }
188633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
188733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.EmitBranch(DefaultBB);
188833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
188933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar}
189033337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar
189133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainarvoid CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
189233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar                                           const RegionCodeGenTy &CodeGen) {
189333337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  InlinedOpenMPRegionRAII Region(CGF, CodeGen);
189433337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
18950e2c34f92f00628d48968dfea096d36381f494cbStephen Hines}
18960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
1897