[PATCH] D70290: [OpenMP] Use the OpenMPIRBuilder for "omp parallel"

2019-12-30 Thread Johannes Doerfert via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG10fedd94b432: [OpenMP] Use the OpenMPIRBuilder for `omp 
parallel` (authored by jdoerfert).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70290/new/

https://reviews.llvm.org/D70290

Files:
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/test/OpenMP/cancel_codegen.cpp
  clang/test/OpenMP/parallel_codegen.cpp
  llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
  llvm/lib/Frontend/OpenMP/OMPConstants.cpp
  llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
  llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Index: llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
===
--- llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -376,6 +376,10 @@
   Function *OutlinedFn = PrivAI->getFunction();
   EXPECT_NE(F, OutlinedFn);
   EXPECT_FALSE(verifyModule(*M));
+  EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
+  EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
+  EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
+  EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
 
   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
Index: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
===
--- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
@@ -501,10 +502,21 @@
   dbgs() << " PBR: " << BB->getName() << "\n";
   });
 
+  // Add some known attributes to the outlined function.
   Function *OutlinedFn = Extractor.extractCodeRegion(CEAC);
+  OutlinedFn->addParamAttr(0, Attribute::NoAlias);
+  OutlinedFn->addParamAttr(1, Attribute::NoAlias);
+  OutlinedFn->addFnAttr(Attribute::NoUnwind);
+  OutlinedFn->addFnAttr(Attribute::NoRecurse);
+
   LLVM_DEBUG(dbgs() << "After  outlining: " << *UI->getFunction() << "\n");
   LLVM_DEBUG(dbgs() << "   Outlined function: " << *OutlinedFn << "\n");
 
+  // For compability with the clang CG we move the outlined function after the
+  // one with the parallel region.
+  OutlinedFn->removeFromParent();
+  M.getFunctionList().insertAfter(OuterFn->getIterator(), OutlinedFn);
+
   // Remove the artificial entry introduced by the extractor right away, we
   // made our own entry block after all.
   {
@@ -535,6 +547,23 @@
   RealArgs.append(CI->arg_begin() + /* tid & bound tid */ 2, CI->arg_end());
 
   FunctionCallee RTLFn = getOrCreateRuntimeFunction(OMPRTL___kmpc_fork_call);
+  if (auto *F = dyn_cast(RTLFn.getCallee())) {
+if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
+  llvm::LLVMContext &Ctx = F->getContext();
+  MDBuilder MDB(Ctx);
+  // Annotate the callback behavior of the __kmpc_fork_call:
+  //  - The callback callee is argument number 2 (microtask).
+  //  - The first two arguments of the callback callee are unknown (-1).
+  //  - All variadic arguments to the __kmpc_fork_call are passed to the
+  //callback callee.
+  F->addMetadata(
+  llvm::LLVMContext::MD_callback,
+  *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
+  2, {-1, -1},
+  /* VarArgsArePassed */ true)}));
+}
+  }
+
   Builder.CreateCall(RTLFn, RealArgs);
 
   LLVM_DEBUG(dbgs() << "With fork_call placed: "
Index: llvm/lib/Frontend/OpenMP/OMPConstants.cpp
===
--- llvm/lib/Frontend/OpenMP/OMPConstants.cpp
+++ llvm/lib/Frontend/OpenMP/OMPConstants.cpp
@@ -65,7 +65,7 @@
 #define OMP_TYPE(VarName, InitValue) VarName = InitValue;
 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...)  \
   VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg);\
-  VarName##Ptr = PointerType::getUnqual(T);
+  VarName##Ptr = PointerType::getUnqual(VarName);
 #define OMP_STRUCT_TYPE(VarName, StructName, ...)  \
   T = M.getTypeByName(StructName); \
   if (!T)  \
Index: llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
===
--- llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -205,6 +205,9 @@
 #define __OMP_RTL_ATTRS(Name, FnAttrSet, RetAttrSet, ArgAttrSets)  \
   OMP_RTL_ATTRS(OMPRTL_##Name, FnAttrSet, RetAttrSet, ArgAttrSets)
 
+__OMP_RTL_ATTRS(__kmpc_fork_call, Attri

[PATCH] D70290: [OpenMP] Use the OpenMPIRBuilder for "omp parallel"

2019-12-27 Thread pre-merge checks [bot] via Phabricator via cfe-commits
merge_guards_bot added a comment.

{icon question-circle color=gray} Unit tests: unknown.

{icon question-circle color=gray} clang-tidy: unknown.

{icon question-circle color=gray} clang-format: unknown.

Build artifacts 
: 
diff.json 
,
 console-log.txt 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70290/new/

https://reviews.llvm.org/D70290



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70290: [OpenMP] Use the OpenMPIRBuilder for "omp parallel"

2019-12-27 Thread Johannes Doerfert via Phabricator via cfe-commits
jdoerfert updated this revision to Diff 235449.
jdoerfert added a comment.

Rebased on D71948  and combined with 
OpenMPIRBuilder cancel code gen


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70290/new/

https://reviews.llvm.org/D70290

Files:
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/test/OpenMP/cancel_codegen.cpp
  clang/test/OpenMP/parallel_codegen.cpp
  llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
  llvm/lib/Frontend/OpenMP/OMPConstants.cpp
  llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
  llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Index: llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
===
--- llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -376,6 +376,10 @@
   Function *OutlinedFn = PrivAI->getFunction();
   EXPECT_NE(F, OutlinedFn);
   EXPECT_FALSE(verifyModule(*M));
+  EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
+  EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
+  EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
+  EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
 
   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
Index: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
===
--- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
@@ -510,10 +511,21 @@
   dbgs() << " PBR: " << BB->getName() << "\n";
   });
 
+  // Add some known attributes to the outlined function.
   Function *OutlinedFn = Extractor.extractCodeRegion(CEAC);
+  OutlinedFn->addParamAttr(0, Attribute::NoAlias);
+  OutlinedFn->addParamAttr(1, Attribute::NoAlias);
+  OutlinedFn->addFnAttr(Attribute::NoUnwind);
+  OutlinedFn->addFnAttr(Attribute::NoRecurse);
+
   LLVM_DEBUG(dbgs() << "After  outlining: " << *UI->getFunction() << "\n");
   LLVM_DEBUG(dbgs() << "   Outlined function: " << *OutlinedFn << "\n");
 
+  // For compability with the clang CG we move the outlined function after the
+  // one with the parallel region.
+  OutlinedFn->removeFromParent();
+  M.getFunctionList().insertAfter(OuterFn->getIterator(), OutlinedFn);
+
   // Remove the artificial entry introduced by the extractor right away, we
   // made our own entry block after all.
   {
@@ -544,6 +556,23 @@
   RealArgs.append(CI->arg_begin() + /* tid & bound tid */ 2, CI->arg_end());
 
   FunctionCallee RTLFn = getOrCreateRuntimeFunction(OMPRTL___kmpc_fork_call);
+  if (auto *F = dyn_cast(RTLFn.getCallee())) {
+if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
+  llvm::LLVMContext &Ctx = F->getContext();
+  MDBuilder MDB(Ctx);
+  // Annotate the callback behavior of the __kmpc_fork_call:
+  //  - The callback callee is argument number 2 (microtask).
+  //  - The first two arguments of the callback callee are unknown (-1).
+  //  - All variadic arguments to the __kmpc_fork_call are passed to the
+  //callback callee.
+  F->addMetadata(
+  llvm::LLVMContext::MD_callback,
+  *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
+  2, {-1, -1},
+  /* VarArgsArePassed */ true)}));
+}
+  }
+
   Builder.CreateCall(RTLFn, RealArgs);
 
   LLVM_DEBUG(dbgs() << "With fork_call placed: "
Index: llvm/lib/Frontend/OpenMP/OMPConstants.cpp
===
--- llvm/lib/Frontend/OpenMP/OMPConstants.cpp
+++ llvm/lib/Frontend/OpenMP/OMPConstants.cpp
@@ -65,7 +65,7 @@
 #define OMP_TYPE(VarName, InitValue) VarName = InitValue;
 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...)  \
   VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg);\
-  VarName##Ptr = PointerType::getUnqual(T);
+  VarName##Ptr = PointerType::getUnqual(VarName);
 #define OMP_STRUCT_TYPE(VarName, StructName, ...)  \
   T = M.getTypeByName(StructName); \
   if (!T)  \
Index: llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
===
--- llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -204,6 +204,9 @@
 #define __OMP_RTL_ATTRS(Name, FnAttrSet, RetAttrSet, ArgAttrSets)  \
   OMP_RTL_ATTRS(OMPRTL_##Name, FnAttrSet, RetAttrSet, ArgAttrSets)
 
+__OMP_RTL_ATTRS(__kmpc_fork_call, AttributeS

[PATCH] D70290: [OpenMP] Use the OpenMPIRBuilder for "omp parallel"

2019-12-26 Thread pre-merge checks [bot] via Phabricator via cfe-commits
merge_guards_bot added a comment.

{icon times-circle color=red} Unit tests: fail. 61124 tests passed, 1 failed 
and 728 were skipped.

  failed: Clang.OpenMP/cancel_codegen.cpp

{icon times-circle color=red} clang-tidy: fail. Please fix clang-tidy findings 
.

{icon times-circle color=red} clang-format: fail. Please format your changes 
with clang-format by running `git-clang-format HEAD^` or applying this patch 
.

Build artifacts 
: 
diff.json 
,
 clang-tidy.txt 
,
 clang-format.patch 
,
 CMakeCache.txt 
,
 console-log.txt 
,
 test-results.xml 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70290/new/

https://reviews.llvm.org/D70290



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70290: [OpenMP] Use the OpenMPIRBuilder for "omp parallel"

2019-12-26 Thread Johannes Doerfert via Phabricator via cfe-commits
jdoerfert updated this revision to Diff 235390.
jdoerfert added a comment.
Herald added subscribers: llvm-commits, hiraditya.
Herald added a project: LLVM.

Rebase + add a test case


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70290/new/

https://reviews.llvm.org/D70290

Files:
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/test/OpenMP/parallel_codegen.cpp
  llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
  llvm/lib/Frontend/OpenMP/OMPConstants.cpp
  llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
  llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Index: llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
===
--- llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -260,6 +260,10 @@
   Function *OutlinedFn = PrivAI->getFunction();
   EXPECT_NE(F, OutlinedFn);
   EXPECT_FALSE(verifyModule(*M));
+  EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
+  EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
+  EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
+  EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
 
   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
Index: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
===
--- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
@@ -452,10 +453,21 @@
   dbgs() << " PBR: " << BB->getName() << "\n";
   });
 
+  // Add some known attributes to the outlined function.
   Function *OutlinedFn = Extractor.extractCodeRegion(CEAC);
+  OutlinedFn->addParamAttr(0, Attribute::NoAlias);
+  OutlinedFn->addParamAttr(1, Attribute::NoAlias);
+  OutlinedFn->addFnAttr(Attribute::NoUnwind);
+  OutlinedFn->addFnAttr(Attribute::NoRecurse);
+
   LLVM_DEBUG(dbgs() << "After  outlining: " << *UI->getFunction() << "\n");
   LLVM_DEBUG(dbgs() << "   Outlined function: " << *OutlinedFn << "\n");
 
+  // For compability with the clang CG we move the outlined function after the
+  // one with the parallel region.
+  OutlinedFn->removeFromParent();
+  M.getFunctionList().insertAfter(OuterFn->getIterator(), OutlinedFn);
+
   // Remove the artificial entry introduced by the extractor right away, we
   // made our own entry block after all.
   {
@@ -486,6 +498,23 @@
   RealArgs.append(CI->arg_begin() + /* tid & bound tid */ 2, CI->arg_end());
 
   FunctionCallee RTLFn = getOrCreateRuntimeFunction(OMPRTL___kmpc_fork_call);
+  if (auto *F = dyn_cast(RTLFn.getCallee())) {
+if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
+  llvm::LLVMContext &Ctx = F->getContext();
+  MDBuilder MDB(Ctx);
+  // Annotate the callback behavior of the __kmpc_fork_call:
+  //  - The callback callee is argument number 2 (microtask).
+  //  - The first two arguments of the callback callee are unknown (-1).
+  //  - All variadic arguments to the __kmpc_fork_call are passed to the
+  //callback callee.
+  F->addMetadata(
+  llvm::LLVMContext::MD_callback,
+  *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
+  2, {-1, -1},
+  /* VarArgsArePassed */ true)}));
+}
+  }
+
   Builder.CreateCall(RTLFn, RealArgs);
 
   LLVM_DEBUG(dbgs() << "With fork_call placed: "
Index: llvm/lib/Frontend/OpenMP/OMPConstants.cpp
===
--- llvm/lib/Frontend/OpenMP/OMPConstants.cpp
+++ llvm/lib/Frontend/OpenMP/OMPConstants.cpp
@@ -65,7 +65,7 @@
 #define OMP_TYPE(VarName, InitValue) VarName = InitValue;
 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...)  \
   VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg);\
-  VarName##Ptr = PointerType::getUnqual(T);
+  VarName##Ptr = PointerType::getUnqual(VarName);
 #define OMP_STRUCT_TYPE(VarName, StructName, ...)  \
   T = M.getTypeByName(StructName); \
   if (!T)  \
Index: llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
===
--- llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -203,6 +203,9 @@
 #define __OMP_RTL_ATTRS(Name, FnAttrSet, RetAttrSet, ArgAttrSets)  \
   OMP_RTL_ATTRS(OMPRTL_##Name, FnAttrSet, RetAttrSet, ArgAttrSets)
 
+__OMP_RTL_ATTRS(__kmpc_fork_call, AttributeSet(EnumAttr(NoUnwind)),
+   

[PATCH] D70290: [OpenMP] Use the OpenMPIRBuilder for "omp parallel"

2019-11-14 Thread Johannes Doerfert via Phabricator via cfe-commits
jdoerfert created this revision.
jdoerfert added reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, 
gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim.
Herald added subscribers: guansong, bollu.
Herald added a project: clang.

NOTE: This patch needs tests and is missing privatization functionality (see
the TODO). Basic testing was done and any other functionality should be
in place.

This allows to use the OpenMPIRBuilder for parallel regions. Code was
extracted from D61953  and adapted to work 
with the new version (D70109 ).

All but one feature should be supported. An update of this patch will
provide test coverage and privatization other than shared.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70290

Files:
  clang/lib/CodeGen/CGStmtOpenMP.cpp

Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -15,10 +15,11 @@
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "TargetInfo.h"
+#include "clang/AST/DeclOpenMP.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtOpenMP.h"
-#include "clang/AST/DeclOpenMP.h"
 #include "clang/Basic/PrettyStackTrace.h"
+#include "llvm/Frontend/OpenMPIRBuilder.h"
 using namespace clang;
 using namespace CodeGen;
 using namespace llvm::omp;
@@ -1316,6 +1317,86 @@
  llvm::SmallVectorImpl &) {}
 
 void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
+
+  llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder();
+  if (OMPBuilder) {
+// Check if we have any if clause associated with the directive.
+llvm::Value *IfCond = nullptr;
+if (const auto *C = S.getSingleClause())
+  IfCond = EmitScalarExpr(C->getCondition(),
+  /*IgnoreResultAssign=*/true);
+
+llvm::Value *NumThreads = nullptr;
+if (const auto *NumThreadsClause = S.getSingleClause())
+  NumThreads = EmitScalarExpr(NumThreadsClause->getNumThreads(),
+  /*IgnoreResultAssign=*/true);
+
+ProcBindKind ProcBind = OMP_PB_default;
+if (const auto *ProcBindClause = S.getSingleClause())
+  ProcBind = ProcBindClause->getProcBindKind();
+
+using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+
+// The cleanup callback that finalizes all variabels at the given location,
+// thus calls destructors etc.
+auto FiniCB = [this](InsertPointTy IP) {
+  CGBuilderTy::InsertPointGuard IPG(Builder);
+  assert(IP.getBlock()->end() != IP.getPoint() &&
+ "OpenMP IR Builder should cause terminated block!");
+  llvm::BasicBlock *IPBB = IP.getBlock();
+  llvm::BasicBlock *DestBB = IPBB->splitBasicBlock(IP.getPoint());
+  IPBB->getTerminator()->eraseFromParent();
+  Builder.SetInsertPoint(IPBB);
+  CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB);
+  EmitBranchThroughCleanup(Dest);
+};
+
+// Privatization callback that performs appropriate action for
+// shared/private/firstprivate/lastprivate/copyin/... variables.
+//
+// TODO: This defaults to shared right now.
+auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
+ llvm::Value &Val, llvm::Value *&ReplVal) {
+  // The next line is appropriate only for variables (Val) with the
+  // data-sharing attribute "shared".
+  ReplVal = &Val;
+
+  return CodeGenIP;
+};
+
+const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
+const Stmt *ParallelRegionBodyStmt = CS->getCapturedStmt();
+
+auto BodyGenCB = [ParallelRegionBodyStmt,
+  this](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
+llvm::BasicBlock &ContinuationBB) {
+  auto OldAllocaIP = AllocaInsertPt;
+  AllocaInsertPt = &*AllocaIP.getPoint();
+
+  auto OldReturnBlock = ReturnBlock;
+  ReturnBlock = getJumpDestInCurrentScope(&ContinuationBB);
+
+  llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+  CodeGenIPBB->splitBasicBlock(CodeGenIP.getPoint());
+  llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator();
+  CodeGenIPBBTI->removeFromParent();
+
+  Builder.SetInsertPoint(CodeGenIPBB);
+
+  EmitStmt(ParallelRegionBodyStmt);
+
+  Builder.Insert(CodeGenIPBBTI);
+
+  AllocaInsertPt = OldAllocaIP;
+  ReturnBlock = OldReturnBlock;
+};
+
+Builder.restoreIP(OMPBuilder->CreateParallel(Builder, BodyGenCB, PrivCB,
+ FiniCB, IfCond, NumThreads,
+ ProcBind, S.hasCancel()));
+return;
+  }
+
   // Emit parallel region as a standalone region.
   auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
 Action.Enter(CGF);