fghanim updated this revision to Diff 237149.
fghanim added a comment.

- Adding array types to OMPKinds.def. Inlining runtime function calls 
generation. reformatting with clang format


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D72304

Files:
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
  llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
  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
@@ -613,4 +613,179 @@
   }
 }
 
+TEST_F(OpenMPIRBuilderTest, MasterDirective) {
+  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
+  OpenMPIRBuilder OMPBuilder(*M);
+  OMPBuilder.initialize();
+  F->setName("func");
+  IRBuilder<> Builder(BB);
+
+  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
+
+  AllocaInst *PrivAI = nullptr;
+
+  BasicBlock *EntryBB = nullptr;
+  BasicBlock *FinalBB = nullptr;
+  BasicBlock *ExitBB = nullptr;
+  BasicBlock *ThenBB = nullptr;
+
+  auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
+                       BasicBlock &FiniBB) {
+    if (AllocaIP.isSet())
+      Builder.restoreIP(AllocaIP);
+    else
+      Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
+    PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
+    Builder.CreateStore(F->arg_begin(), PrivAI);
+
+    llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+    llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
+    EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
+
+    Builder.restoreIP(CodeGenIP);
+
+    // collect some info for checks later
+    FinalBB = &FiniBB;
+    ExitBB = FiniBB.getUniqueSuccessor();
+    ThenBB = Builder.GetInsertBlock();
+    EntryBB = ThenBB->getUniquePredecessor();
+
+    // simple instructions for body
+    Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
+    Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
+  };
+
+  auto FiniCB = [&](InsertPointTy IP) {
+    BasicBlock *IPBB = IP.getBlock();
+    EXPECT_NE(IPBB->end(), IP.getPoint());
+  };
+
+  Builder.restoreIP(OMPBuilder.CreateMaster(Builder, BodyGenCB, FiniCB));
+  Value *EntryBBTI = EntryBB->getTerminator();
+  EXPECT_NE(EntryBBTI, nullptr);
+  EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
+  BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
+  EXPECT_TRUE(EntryBr->isConditional());
+  EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
+  EXPECT_EQ(ThenBB->getUniqueSuccessor(), FinalBB);
+  EXPECT_EQ(FinalBB->getUniqueSuccessor(), ExitBB);
+  EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
+
+  CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
+  EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
+
+  CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
+  EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U);
+  EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_omp_master");
+  EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
+
+  CallInst *MasterEndCI = nullptr;
+  for (auto &FI : *FinalBB) {
+    Instruction *cur = &FI;
+    if (isa<CallInst>(cur)) {
+      MasterEndCI = cast<CallInst>(cur);
+      if (MasterEndCI->getCalledFunction()->getName() ==
+          "__kmpc_omp_end_master")
+        break;
+      else
+        MasterEndCI = nullptr;
+    }
+  }
+  EXPECT_NE(MasterEndCI, nullptr);
+  EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U);
+  EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
+  EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
+}
+
+TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
+  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
+  OpenMPIRBuilder OMPBuilder(*M);
+  OMPBuilder.initialize();
+  F->setName("func");
+  IRBuilder<> Builder(BB);
+
+  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
+
+  AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
+
+  BasicBlock *EntryBB = nullptr;
+  BasicBlock *FinalBB = nullptr;
+  BasicBlock *ExitBB = nullptr;
+
+  auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
+                       BasicBlock &FiniBB) {
+    // collect some info for checks later
+    FinalBB = &FiniBB;
+    ExitBB = FiniBB.getUniqueSuccessor();
+    EntryBB = FinalBB->getUniquePredecessor();
+
+    // actual start for bodyCB
+    llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+    llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
+    EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
+    EXPECT_EQ(EntryBB, CodeGenIPBB);
+
+    // body begin
+    Builder.restoreIP(CodeGenIP);
+    Builder.CreateStore(F->arg_begin(), PrivAI);
+    Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
+    Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
+  };
+
+  auto FiniCB = [&](InsertPointTy IP) {
+    BasicBlock *IPBB = IP.getBlock();
+    EXPECT_NE(IPBB->end(), IP.getPoint());
+  };
+
+  Builder.restoreIP(OMPBuilder.CreateCritical(Builder, BodyGenCB, FiniCB,
+                                              "testCRT", nullptr));
+
+  Value *EntryBBTI = EntryBB->getTerminator();
+  EXPECT_NE(EntryBBTI, nullptr);
+  EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
+  BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
+  EXPECT_FALSE(EntryBr->isConditional());
+  EXPECT_EQ(EntryBB->getUniqueSuccessor(), FinalBB);
+  EXPECT_EQ(FinalBB->getUniqueSuccessor(), ExitBB);
+
+  CallInst *CriticalEntryCI = nullptr;
+  for (auto &EI : *EntryBB) {
+    Instruction *cur = &EI;
+    if (isa<CallInst>(cur)) {
+      CriticalEntryCI = cast<CallInst>(cur);
+      if (CriticalEntryCI->getCalledFunction()->getName() ==
+          "__kmpc_omp_critical")
+        break;
+      else
+        CriticalEntryCI = nullptr;
+    }
+  }
+  EXPECT_NE(CriticalEntryCI, nullptr);
+  EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U);
+  EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(),
+            "__kmpc_omp_critical");
+  EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
+
+  CallInst *CriticalEndCI = nullptr;
+  for (auto &FI : *FinalBB) {
+    Instruction *cur = &FI;
+    if (isa<CallInst>(cur)) {
+      CriticalEndCI = cast<CallInst>(cur);
+      if (CriticalEndCI->getCalledFunction()->getName() ==
+          "__kmpc_omp_end_critical")
+        break;
+      else
+        CriticalEndCI = nullptr;
+    }
+  }
+  EXPECT_NE(CriticalEndCI, nullptr);
+  EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U);
+  EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
+  EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
+  PointerType *CriticalNamePtrTy =
+      PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
+  EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
+  EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
+}
+
 } // namespace
Index: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
===================================================================
--- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -630,3 +630,214 @@
 
   return AfterIP;
 }
+
+OpenMPIRBuilder::InsertPointTy
+OpenMPIRBuilder::CreateMaster(const LocationDescription &Loc,
+                              BodyGenCallbackTy BodyGenCB,
+                              FinalizeCallbackTy FiniCB) {
+
+  if (!updateToLocation(Loc))
+    return Loc.IP;
+
+  Directive OMPD = Directive::OMPD_master;
+  Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
+  Value *Ident = getOrCreateIdent(SrcLocStr);
+  Value *ThreadId = getOrCreateThreadID(Ident);
+  Value *Args[] = {Ident, ThreadId};
+
+  Function *EntryRTLFn = getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_master);
+  Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args);
+
+  Function *ExitRTLFn =
+      getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_end_master);
+  Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args);
+
+  return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
+                              /*Conditional*/ true, /*hasFinalize*/ true);
+}
+
+OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::CreateCritical(
+    const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB,
+    FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst) {
+
+  if (!updateToLocation(Loc))
+    return Loc.IP;
+
+  Directive OMPD = Directive::OMPD_critical;
+  Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
+  Value *Ident = getOrCreateIdent(SrcLocStr);
+  Value *ThreadId = getOrCreateThreadID(Ident);
+  Value *LockVar = getOMPCriticalRegionLock(CriticalName);
+  llvm::Value *Args[] = {Ident, ThreadId, LockVar};
+
+  SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), std::end(Args));
+  Function *fn = nullptr;
+  if (HintInst) {
+    // Add Hint to entry Args and create call
+    EnterArgs.push_back(HintInst);
+    fn = getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_critical_with_hint);
+  } else {
+    fn = getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_critical);
+  }
+  Instruction *EntryCall = Builder.CreateCall(fn, EnterArgs);
+
+  Function *ExitRTLFn =
+      getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_end_critical);
+  Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args);
+
+  return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
+                              /*Conditional*/ false, /*hasFinalize*/ true);
+}
+
+OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::EmitOMPInlinedRegion(
+    omp::Directive OMPD, Instruction *EntryCall, Instruction *ExitCall,
+    BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool conditional,
+    bool hasFinalize) {
+
+  FinalizationStack.push_back({FiniCB, OMPD, /*IsCancellable*/ false});
+
+  // Create 'Critical' entry and body blocks, in preparation
+  // for conditional creation
+  BasicBlock *EntryBB = Builder.GetInsertBlock();
+  Instruction *SplitPos = EntryBB->getTerminator();
+  if (!isa_and_nonnull<BranchInst>(SplitPos))
+    SplitPos = new UnreachableInst(Builder.getContext(), EntryBB);
+  BasicBlock *ExitBB = EntryBB->splitBasicBlock(SplitPos, "omp_region.end");
+  BasicBlock *FiniBB =
+      EntryBB->splitBasicBlock(EntryBB->getTerminator(), "omp_region.finalize");
+
+  Builder.SetInsertPoint(EntryBB->getTerminator());
+  emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, conditional);
+
+  // generate body
+  BodyGenCB(/* AllocaIP */ InsertPointTy(),
+            /* CodeGenIP */ Builder.saveIP(), *FiniBB);
+
+  // emit exit call and do any needed finalization.
+  auto FinIP = InsertPointTy(FiniBB, FiniBB->getFirstInsertionPt());
+  assert(FiniBB->getTerminator()->getNumSuccessors() == 1 &&
+         FiniBB->getTerminator()->getSuccessor(0) == ExitBB &&
+         "Unexpected insertion point for finalization call!");
+  emitCommonDirectiveExit(OMPD, FinIP, ExitBB, ExitCall, /*hasFinalize*/ true);
+
+  BasicBlock *IPBB = SplitPos->getParent();
+  assert(IPBB == ExitBB && "Unexpected Insertion point location!");
+
+  if (!isa_and_nonnull<BranchInst>(SplitPos)) {
+    SplitPos->eraseFromParent();
+  }
+
+  Builder.SetInsertPoint(ExitBB);
+
+  return Builder.saveIP();
+}
+
+OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveEntry(
+    omp::Directive omp, llvm::Value *EntryCall, BasicBlock *ExitBB,
+    bool conditional) {
+
+  OpenMPIRBuilder::InsertPointTy Contpt;
+  llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
+
+  if (conditional) {
+    llvm::Value *CallBool = Builder.CreateIsNotNull(EntryCall);
+    auto *ThenBB = BasicBlock::Create(M.getContext(), "omp_region.body");
+    auto *UI = new UnreachableInst(Builder.getContext(), ThenBB);
+
+    // Emit thenBB and set the Builder's insertion point there for
+    // body generation next. Place the block after the current block.
+    llvm::Function *CurFn = EntryBB->getParent();
+    CurFn->getBasicBlockList().insertAfter(EntryBB->getIterator(), ThenBB);
+
+    // Move Entry branch to end of ThenBB, and replace with conditional
+    // branch (If-stmt)
+    Instruction *EntryBBTI = EntryBB->getTerminator();
+    Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
+    EntryBBTI->removeFromParent();
+    Builder.SetInsertPoint(UI);
+    Builder.Insert(EntryBBTI);
+    UI->eraseFromParent();
+    Builder.SetInsertPoint(ThenBB->getTerminator());
+
+    // return an insertion point to ExitBB.
+    Contpt = IRBuilder<>::InsertPoint(ExitBB, ExitBB->getFirstInsertionPt());
+  } else
+    // otherwise Return an insertion point to current block
+    Contpt = Builder.saveIP();
+
+  return Contpt;
+}
+
+OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveExit(
+    omp::Directive OMPD, InsertPointTy IP, BasicBlock *ExitBB,
+    Instruction *ExitCall, bool hasFinalize) {
+
+  IRBuilder<>::InsertPointGuard IPG(Builder);
+  Builder.restoreIP(IP);
+
+  // If there is finalization to do, emit it before the exit call
+  if (hasFinalize) {
+    assert(!FinalizationStack.empty() &&
+           "Unexpected finalization stack state!");
+
+    FinalizationInfo Fi = FinalizationStack.pop_back_val();
+    assert(Fi.DK == OMPD && "Unexpected Directive for Finalization call!");
+
+    Fi.FiniCB(IP);
+
+    BasicBlock *InsertBB = IP.getBlock();
+    Instruction *InsertBBTI = InsertBB->getTerminator();
+    if (!(InsertBBTI)) {
+      Builder.SetInsertPoint(InsertBB);
+      InsertBBTI = Builder.CreateBr(ExitBB);
+    }
+
+    // set Builder IP for call creation
+    Builder.SetInsertPoint(InsertBBTI);
+  }
+
+  ExitCall->removeFromParent();
+  Builder.Insert(ExitCall);
+
+  return IRBuilder<>::InsertPoint(ExitCall->getParent(),
+                                  ExitCall->getIterator());
+}
+
+std::string OpenMPIRBuilder::getName(ArrayRef<StringRef> Parts,
+                                     StringRef FirstSeparator,
+                                     StringRef Separator) const {
+  SmallString<128> Buffer;
+  llvm::raw_svector_ostream OS(Buffer);
+  StringRef Sep = FirstSeparator;
+  for (StringRef Part : Parts) {
+    OS << Sep << Part;
+    Sep = Separator;
+  }
+  return OS.str();
+}
+
+Constant *OpenMPIRBuilder::getOrCreateOMPInternalVariable(
+    llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
+  SmallString<256> Buffer;
+  llvm::raw_svector_ostream Out(Buffer);
+  Out << Name;
+  StringRef RuntimeName = Out.str();
+  auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
+  if (Elem.second) {
+    assert(Elem.second->getType()->getPointerElementType() == Ty &&
+           "OMP internal variable has different type than requested");
+    return &*Elem.second;
+  }
+
+  return Elem.second = new llvm::GlobalVariable(
+             M, Ty, /*IsConstant*/ false, llvm::GlobalValue::CommonLinkage,
+             llvm::Constant::getNullValue(Ty), Elem.first(),
+             /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal,
+             AddressSpace);
+}
+
+Value *OpenMPIRBuilder::getOMPCriticalRegionLock(StringRef CriticalName) {
+  std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
+  std::string Name = getName({Prefix, "var"}, ".", ".");
+  return getOrCreateOMPInternalVariable(KmpCriticalNameTy, Name);
+}
Index: llvm/lib/Frontend/OpenMP/OMPConstants.cpp
===================================================================
--- llvm/lib/Frontend/OpenMP/OMPConstants.cpp
+++ llvm/lib/Frontend/OpenMP/OMPConstants.cpp
@@ -42,8 +42,12 @@
 /// values.
 ///
 ///{
-
+// ArrayType *llvm::omp::types::KmpCriticalNameTy = nullptr;
+// PointerType *llvm::omp::types::KmpCriticalNamePtrTy = nullptr;
 #define OMP_TYPE(VarName, InitValue) Type *llvm::omp::types::VarName = nullptr;
+#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)                             \
+  ArrayType *llvm::omp::types::VarName##Ty = nullptr;                          \
+  PointerType *llvm::omp::types::VarName##PtrTy = nullptr;
 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...)                  \
   FunctionType *llvm::omp::types::VarName = nullptr;                           \
   PointerType *llvm::omp::types::VarName##Ptr = nullptr;
@@ -59,10 +63,16 @@
     return;
 
   LLVMContext &Ctx = M.getContext();
+  //  KmpCriticalNameTy = ArrayType::get(
+  //  		  	  Type::getInt32Ty(M.getContext()),/*NumElements*/ 8);
+  //  KmpCriticalNamePtrTy = PointerType::getUnqual(KmpCriticalNameTy);
   // Create all simple and struct types exposed by the runtime and remember
   // the llvm::PointerTypes of them for easy access later.
   StructType *T;
 #define OMP_TYPE(VarName, InitValue) VarName = InitValue;
+#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)                             \
+  VarName##Ty = ArrayType::get(ElemTy, ArraySize);                             \
+  VarName##PtrTy = PointerType::getUnqual(VarName##Ty);
 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...)                  \
   VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg);            \
   VarName##Ptr = PointerType::getUnqual(VarName);
Index: llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -122,6 +122,24 @@
 
 ///}
 
+/// array types
+///
+///{
+
+#ifndef OMP_ARRAY_TYPE
+#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)
+#endif
+
+#define __OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) 						  \
+  OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)
+
+__OMP_ARRAY_TYPE(KmpCriticalName, Int32, 8)
+
+#undef __OMP_ARRAY_TYPE
+#undef OMP_ARRAY_TYPE
+
+///}
+
 /// Struct and function types
 ///
 ///{
@@ -176,6 +194,12 @@
 
 __OMP_RTL(omp_get_thread_num, false, Int32, )
 
+__OMP_RTL(__kmpc_omp_master, false, Int32, IdentPtr, Int32)
+__OMP_RTL(__kmpc_omp_end_master, false, Void, IdentPtr, Int32)
+__OMP_RTL(__kmpc_omp_critical, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy)
+__OMP_RTL(__kmpc_omp_critical_with_hint, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy, Int32)
+__OMP_RTL(__kmpc_omp_end_critical, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy)
+
 #undef __OMP_RTL
 #undef OMP_RTL
 
Index: llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -243,6 +243,110 @@
 
   /// Map to remember existing ident_t*.
   DenseMap<std::pair<Constant *, uint64_t>, GlobalVariable *> IdentMap;
+
+  /// An ordered map of auto-generated variables to their unique names.
+  /// It stores variables with the following names: 1) ".gomp_critical_user_" +
+  /// <critical_section_name> + ".var" for "omp critical" directives; 2)
+  /// <mangled_name_for_global_var> + ".cache." for cache for threadprivate
+  /// variables.
+  StringMap<AssertingVH<Constant>, BumpPtrAllocator> InternalVars;
+
+public:
+  /// Generator for '#omp master'
+  ///
+  /// \param Loc The insert and source location description.
+  /// \param BodyGenCB Callback that will generate the region code.
+  ///
+  /// \returns The insertion position *after* the master.
+  InsertPointTy CreateMaster(const LocationDescription &Loc,
+                             BodyGenCallbackTy BodyGenCB,
+                             FinalizeCallbackTy FiniCB);
+
+  /// Generator for '#omp master'
+  ///
+  /// \param Loc The insert and source location description.
+  /// \param BodyGenCB Callback that will generate the region code.
+  /// \param CriticalName name of the lock used by the critical directive
+  /// \param hasHint whether there is ahint clause associated with critical
+  /// \param FiniCB Callback to finalize variable copies.
+  ///
+  /// \returns The insertion position *after* the master.
+  InsertPointTy CreateCritical(const LocationDescription &Loc,
+                               BodyGenCallbackTy BodyGenCB,
+                               FinalizeCallbackTy FiniCB,
+                               StringRef CriticalName, Value *HintInst);
+
+private:
+  /// Common interface for generating entry calls for OMP Directives.
+  /// if the directive has a region/body, It will set the insertion
+  /// point to the body
+  ///
+  /// \param OMPD Directive to generate entry blocks for
+  /// \param EntryCall Call to the entry OMP Runtime Function
+  /// \param ExitBB block where the region ends.
+  /// \param Conditional indicate if the entry call result will be used
+  ///        to evaluate a conditional of whether a thread will execute
+  ///        body code or not.
+  ///
+  /// \return The insertion position in exit block
+  InsertPointTy emitCommonDirectiveEntry(omp::Directive OMPD,
+                                         llvm::Value *EntryCall,
+                                         BasicBlock *ExitBB,
+                                         bool conditional = false);
+
+  /// Common interface to finalize the region
+  ///
+  /// \param OMPD Directive to generate exiting code for
+  /// \param IP Insertion point for emitting Finalization code and exit call
+  /// \param ExitBB Exit BasicBlock for OMP region
+  /// \param ExitCall Call to the ending OMP Runtime Function
+  /// \param hasFinalize indicate if the directive will require finalization
+  /// 		 	 and has a finalization callback in the stack that
+  /// should be
+  ///				 called.
+  ///
+  /// \return The insertion position in exit block
+  InsertPointTy emitCommonDirectiveExit(omp::Directive OMPD, InsertPointTy IP,
+                                        BasicBlock *ExitBB,
+                                        Instruction *ExitCall,
+                                        bool hasFinalize);
+
+  /// Common Interface to generate OMP inlined regions
+  ///
+  /// \param OMPD Directive to generate inlined region for
+  /// \param EntryCall Call to the entry OMP Runtime Function
+  /// \param ExitCall Call to the ending OMP Runtime Function
+  /// \param BodyGenCB Body code generation callback.
+  /// \param FiniCB Finalization Callback. Will be called when finalizing region
+  /// \param Conditional indicate if the entry call result will be used
+  ///        to evaluate a conditional of whether a thread will execute
+  ///        body code or not.
+  /// \param hasFinalize indicate if the directive will require finalization
+  /// 		 	 and has a finalization callback in the stack that
+  /// should be
+  ///				 called.
+  ///
+  /// \return The insertion point after the region
+
+  InsertPointTy EmitOMPInlinedRegion(omp::Directive OMPD,
+                                     Instruction *EntryCall,
+                                     Instruction *ExitCall,
+                                     BodyGenCallbackTy BodyGenCB,
+                                     FinalizeCallbackTy FiniCB,
+                                     bool conditional, bool hasFinalize);
+
+  std::string getName(ArrayRef<StringRef> Parts, StringRef FirstSeparator,
+                      StringRef Separator) const;
+
+  Constant *getOrCreateOMPInternalVariable(llvm::Type *Ty,
+                                           const llvm::Twine &Name,
+                                           unsigned AddressSpace = 0);
+
+  Value *getOMPCriticalRegionLock(StringRef CriticalName);
+
+  llvm::Constant *getOrCreateInternalVariable(llvm::Type *Ty,
+                                              const llvm::Twine &Name,
+                                              unsigned AddressSpace);
 };
 
 } // end namespace llvm
Index: llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
+++ llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
@@ -20,6 +20,7 @@
 namespace llvm {
 class Type;
 class Module;
+class ArrayType;
 class StructType;
 class PointerType;
 class FunctionType;
@@ -84,7 +85,14 @@
 ///{
 namespace types {
 
+/// Type for kmp_critical_name[8], and related pointer type;
+// extern ArrayType *KmpCriticalNameTy;
+// extern PointerType *KmpCriticalNamePtrTy;
+
 #define OMP_TYPE(VarName, InitValue) extern Type *VarName;
+#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)                             \
+  extern ArrayType *VarName##Ty;                                               \
+  extern PointerType *VarName##PtrTy;
 #define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...)                  \
   extern FunctionType *VarName;                                                \
   extern PointerType *VarName##Ptr;
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1319,7 +1319,6 @@
                                      llvm::SmallVectorImpl<llvm::Value *> &) {}
 
 void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
-
   if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
     // Check if we have any if clause associated with the directive.
     llvm::Value *IfCond = nullptr;
@@ -2991,11 +2990,121 @@
 }
 
 void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
+  if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
+    using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+
+    const Stmt *MasterRegionBodyStmt =
+        S.getInnermostCapturedStmt()->getCapturedStmt();
+    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::BranchInst *IPBBTI =
+          llvm::dyn_cast<llvm::BranchInst>(IPBB->getTerminator());
+      llvm::BasicBlock *DestBB = IPBBTI->getSuccessor(0);
+
+      // erase and replace with cleanup branch.
+      IPBB->getTerminator()->eraseFromParent();
+      Builder.SetInsertPoint(IPBB);
+      CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB);
+      EmitBranchThroughCleanup(Dest);
+    };
+
+    auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP,
+                                                  InsertPointTy CodeGenIP,
+                                                  llvm::BasicBlock &FiniBB) {
+      auto OldAllocaIP = AllocaInsertPt;
+      if (AllocaIP.isSet())
+        AllocaInsertPt = &*AllocaIP.getPoint();
+      auto OldReturnBlock = ReturnBlock;
+      ReturnBlock = getJumpDestInCurrentScope(&FiniBB);
+
+      llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+      if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator())
+        CodeGenIPBBTI->eraseFromParent();
+
+      Builder.SetInsertPoint(CodeGenIPBB);
+
+      EmitStmt(MasterRegionBodyStmt);
+
+      Builder.CreateBr(&FiniBB);
+
+      AllocaInsertPt = OldAllocaIP;
+      ReturnBlock = OldReturnBlock;
+    };
+
+    Builder.restoreIP(OMPBuilder->CreateMaster(Builder, BodyGenCB, FiniCB));
+
+    return;
+  }
   OMPLexicalScope Scope(*this, S, OMPD_unknown);
   emitMaster(*this, S);
 }
 
 void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
+  if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
+    using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+
+    const Stmt *CriticalRegionBodyStmt =
+        S.getInnermostCapturedStmt()->getCapturedStmt();
+    const Expr *Hint = nullptr;
+    if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
+      Hint = HintClause->getHint();
+
+    // TODO: Fix the type when everything about typing is final.
+    llvm::Value *HintInst =
+        (!Hint)
+            ? nullptr
+            : Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false);
+
+    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::BranchInst *IPBBTI =
+          llvm::dyn_cast<llvm::BranchInst>(IPBB->getTerminator());
+      llvm::BasicBlock *DestBB = IPBBTI->getSuccessor(0);
+
+      // erase and replace with cleanup branch.
+      IPBB->getTerminator()->eraseFromParent();
+      Builder.SetInsertPoint(IPBB);
+      CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB);
+      EmitBranchThroughCleanup(Dest);
+    };
+
+    auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP,
+                                                    InsertPointTy CodeGenIP,
+                                                    llvm::BasicBlock &FiniBB) {
+      auto OldAllocaIP = AllocaInsertPt;
+      if (AllocaIP.isSet())
+        AllocaInsertPt = &*AllocaIP.getPoint();
+      auto OldReturnBlock = ReturnBlock;
+      ReturnBlock = getJumpDestInCurrentScope(&FiniBB);
+
+      llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+      if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator())
+        CodeGenIPBBTI->eraseFromParent();
+
+      Builder.SetInsertPoint(CodeGenIPBB);
+
+      EmitStmt(CriticalRegionBodyStmt);
+
+      Builder.CreateBr(&FiniBB);
+
+      AllocaInsertPt = OldAllocaIP;
+      ReturnBlock = OldReturnBlock;
+    };
+
+    Builder.restoreIP(OMPBuilder->CreateCritical(
+        Builder, BodyGenCB, FiniCB, S.getDirectiveName().getAsString(),
+        HintInst));
+
+    return;
+  }
+
   auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
     Action.Enter(CGF);
     CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to