r219486 - Code improvements in OpenMP CodeGen.

Alexey Bataev a.bataev at hotmail.com
Fri Oct 10 02:48:27 PDT 2014


Author: abataev
Date: Fri Oct 10 04:48:26 2014
New Revision: 219486

URL: http://llvm.org/viewvc/llvm-project?rev=219486&view=rev
Log:
Code improvements in OpenMP CodeGen.
This patch makes class OMPPrivateScope a common class for all private variables. Reworked processing of firstprivate variables (now it is based on OMPPrivateScope too).

Modified:
    cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
    cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=219486&r1=219485&r2=219486&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Fri Oct 10 04:48:26 2014
@@ -25,26 +25,17 @@ using namespace clang;
 using namespace CodeGen;
 
 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, Stmt *S) {
-  CodeGenFunction::OuterDeclMapTy OuterDeclMap;
-  CGF.EmitOMPFirstprivateClause(Directive, OuterDeclMap);
-  if (!OuterDeclMap.empty()) {
+  CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
+  CGF.EmitOMPFirstprivateClause(Directive, PrivateScope);
+  if (PrivateScope.Privatize()) {
     // Emit implicit barrier to synchronize threads and avoid data races.
     auto Flags = static_cast<CGOpenMPRuntime::OpenMPLocationFlags>(
         CGOpenMPRuntime::OMP_IDENT_KMPC |
         CGOpenMPRuntime::OMP_IDENT_BARRIER_IMPL);
     CGF.CGM.getOpenMPRuntime().EmitOMPBarrierCall(CGF, Directive.getLocStart(),
                                                   Flags);
-    // Remap captured variables to use their private copies in the outlined
-    // function.
-    for (auto I : OuterDeclMap) {
-      CGF.LocalDeclMap[I.first] = I.second;
-    }
   }
   CGCapturedStmtInfo::EmitBody(CGF, S);
-  // Clear mappings of captured private variables.
-  for (auto I : OuterDeclMap) {
-    CGF.LocalDeclMap.erase(I.first);
-  }
 }
 
 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)

Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=219486&r1=219485&r2=219486&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Fri Oct 10 04:48:26 2014
@@ -94,7 +94,7 @@ void CodeGenFunction::EmitOMPAggregateAs
 
 void CodeGenFunction::EmitOMPFirstprivateClause(
     const OMPExecutableDirective &D,
-    CodeGenFunction::OuterDeclMapTy &OuterDeclMap) {
+    CodeGenFunction::OMPPrivateScope &PrivateScope) {
   auto PrivateFilter = [](const OMPClause *C) -> bool {
     return C->getClauseKind() == OMPC_firstprivate;
   };
@@ -104,25 +104,34 @@ void CodeGenFunction::EmitOMPFirstprivat
     auto IRef = C->varlist_begin();
     auto InitsRef = C->inits().begin();
     for (auto IInit : C->private_copies()) {
-      auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+      auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
+      auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+      bool IsRegistered;
       if (*InitsRef != nullptr) {
         // Emit VarDecl with copy init for arrays.
-        auto *FD = CapturedStmtInfo->lookup(
-            cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()));
+        auto *FD = CapturedStmtInfo->lookup(OrigVD);
         LValue Base = MakeNaturalAlignAddrLValue(
             CapturedStmtInfo->getContextValue(),
             getContext().getTagDeclType(FD->getParent()));
         auto OriginalAddr = EmitLValueForField(Base, FD);
         auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
-        auto Emission = EmitAutoVarAlloca(*VD);
-        // Emit initialization of aggregate firstprivate vars.
-        EmitOMPAggregateAssign(OriginalAddr, Emission.getAllocatedAddress(),
-                               VD->getInit(), (*IRef)->getType(), VDInit);
-        EmitAutoVarCleanups(Emission);
+        IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
+          auto Emission = EmitAutoVarAlloca(*VD);
+          // Emit initialization of aggregate firstprivate vars.
+          EmitOMPAggregateAssign(OriginalAddr, Emission.getAllocatedAddress(),
+                                 VD->getInit(), (*IRef)->getType(), VDInit);
+          EmitAutoVarCleanups(Emission);
+          return Emission.getAllocatedAddress();
+        });
       } else
-        // Emit VarDecl with copy init.
-        EmitDecl(*VD);
-      OuterDeclMap[cast<DeclRefExpr>(*IRef)->getDecl()] = GetAddrOfLocalVar(VD);
+        IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
+          // Emit private VarDecl with copy init.
+          EmitDecl(*VD);
+          return GetAddrOfLocalVar(VD);
+        });
+      assert(IsRegistered && "counter already registered as private");
+      // Silence the warning about unused variable.
+      (void)IsRegistered;
       ++IRef, ++InitsRef;
     }
   }
@@ -239,7 +248,7 @@ static void EmitOMPAlignedClause(CodeGen
     unsigned Alignment = ClauseAlignment;
     if (Alignment == 0) {
       // OpenMP [2.8.1, Description]
-      // If no optional parameter isspecified, implementation-defined default
+      // If no optional parameter is specified, implementation-defined default
       // alignments for SIMD instructions on the target platforms are assumed.
       Alignment = CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
           E->getType());
@@ -253,6 +262,24 @@ static void EmitOMPAlignedClause(CodeGen
   }
 }
 
+static void EmitPrivateLoopCounters(CodeGenFunction &CGF,
+                                    CodeGenFunction::OMPPrivateScope &LoopScope,
+                                    ArrayRef<Expr *> Counters) {
+  for (auto *E : Counters) {
+    auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+    bool IsRegistered = LoopScope.addPrivate(VD, [&]() -> llvm::Value * {
+      // Emit var without initialization.
+      auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
+      CGF.EmitAutoVarCleanups(VarEmission);
+      return VarEmission.getAllocatedAddress();
+    });
+    assert(IsRegistered && "counter already registered as private");
+    // Silence the warning about unused variable.
+    (void)IsRegistered;
+  }
+  (void)LoopScope.Privatize();
+}
+
 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
   // Pragma 'simd' code depends on presence of 'lastprivate'.
   // If present, we have to separate last iteration of the loop:
@@ -330,7 +357,7 @@ void CodeGenFunction::EmitOMPSimdDirecti
     // Emit 'then' code.
     {
       OMPPrivateScope LoopScope(*this);
-      LoopScope.addPrivates(S.counters());
+      EmitPrivateLoopCounters(*this, LoopScope, S.counters());
       EmitOMPInnerLoop(S, LoopScope, /* SeparateIter */ true);
       EmitOMPLoopBody(S, /* SeparateIter */ true);
     }
@@ -341,7 +368,7 @@ void CodeGenFunction::EmitOMPSimdDirecti
   } else {
     {
       OMPPrivateScope LoopScope(*this);
-      LoopScope.addPrivates(S.counters());
+      EmitPrivateLoopCounters(*this, LoopScope, S.counters());
       EmitOMPInnerLoop(S, LoopScope);
     }
     EmitOMPSimdFinal(S);

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=219486&r1=219485&r2=219486&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Oct 10 04:48:26 2014
@@ -586,6 +586,68 @@ public:
     void rescopeLabels();
   };
 
+  /// \brief The scope used to remap some variables as private in the OpenMP
+  /// loop body (or other captured region emitted without outlining), and to
+  /// restore old vars back on exit.
+  class OMPPrivateScope : public RunCleanupsScope {
+    typedef llvm::DenseMap<const VarDecl *, llvm::Value *> VarDeclMapTy;
+    VarDeclMapTy SavedLocals;
+    VarDeclMapTy SavedPrivates;
+
+  private:
+    OMPPrivateScope(const OMPPrivateScope &) LLVM_DELETED_FUNCTION;
+    void operator=(const OMPPrivateScope &) LLVM_DELETED_FUNCTION;
+
+  public:
+    /// \brief Enter a new OpenMP private scope.
+    explicit OMPPrivateScope(CodeGenFunction &CGF) : RunCleanupsScope(CGF) {}
+
+    /// \brief Registers \a LocalVD variable as a private and apply \a
+    /// PrivateGen function for it to generate corresponding private variable.
+    /// \a PrivateGen returns an address of the generated private variable.
+    /// \return true if the variable is registered as private, false if it has
+    /// been privatized already.
+    bool
+    addPrivate(const VarDecl *LocalVD,
+               const std::function<llvm::Value *()> &PrivateGen) {
+      assert(PerformCleanup && "adding private to dead scope");
+      assert(LocalVD->isLocalVarDecl() && "privatizing non-local variable");
+      if (SavedLocals.count(LocalVD) > 0) return false;
+      SavedLocals[LocalVD] = CGF.LocalDeclMap.lookup(LocalVD);
+      CGF.LocalDeclMap.erase(LocalVD);
+      SavedPrivates[LocalVD] = PrivateGen();
+      CGF.LocalDeclMap[LocalVD] = SavedLocals[LocalVD];
+      return true;
+    }
+
+    /// \brief Privatizes local variables previously registered as private.
+    /// Registration is separate from the actual privatization to allow
+    /// initializers use values of the original variables, not the private one.
+    /// This is important, for example, if the private variable is a class
+    /// variable initialized by a constructor that references other private
+    /// variables. But at initialization original variables must be used, not
+    /// private copies.
+    /// \return true if at least one variable was privatized, false otherwise.
+    bool Privatize() {
+      for (auto VDPair : SavedPrivates) {
+        CGF.LocalDeclMap[VDPair.first] = VDPair.second;
+      }
+      SavedPrivates.clear();
+      return !SavedLocals.empty();
+    }
+
+    void ForceCleanup() {
+      RunCleanupsScope::ForceCleanup();
+      // Remap vars back to the original values.
+      for (auto I : SavedLocals) {
+        CGF.LocalDeclMap[I.first] = I.second;
+      }
+      SavedLocals.clear();
+    }
+
+    /// \brief Exit scope - all the mapped variables are restored.
+    ~OMPPrivateScope() { ForceCleanup(); }
+  };
 
   /// \brief Takes the old cleanup stack size and emits the cleanup blocks
   /// that have been added.
@@ -867,48 +929,6 @@ private:
   };
   SmallVector<BreakContinue, 8> BreakContinueStack;
 
-  /// \brief The scope used to remap some variables as private in the OpenMP
-  /// loop body (or other captured region emitted without outlining), and to
-  /// restore old vars back on exit.
-  class OMPPrivateScope : public RunCleanupsScope {
-    DeclMapTy SavedLocals;
-
-  private:
-    OMPPrivateScope(const OMPPrivateScope &) LLVM_DELETED_FUNCTION;
-    void operator=(const OMPPrivateScope &) LLVM_DELETED_FUNCTION;
-
-  public:
-    /// \brief Enter a new OpenMP private scope.
-    explicit OMPPrivateScope(CodeGenFunction &CGF) : RunCleanupsScope(CGF) {}
-
-    /// \brief Add and remap private variables (without initialization).
-    /// \param Vars - a range of DeclRefExprs for the private variables.
-    template <class IT> void addPrivates(IT Vars) {
-      assert(PerformCleanup && "adding private to dead scope");
-      for (auto E : Vars) {
-        auto D = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
-        assert(!SavedLocals.lookup(D) && "remapping a var twice");
-        SavedLocals[D] = CGF.LocalDeclMap.lookup(D);
-        CGF.LocalDeclMap.erase(D);
-        // Emit var without initialization.
-        auto VarEmission = CGF.EmitAutoVarAlloca(*D);
-        CGF.EmitAutoVarCleanups(VarEmission);
-      }
-    }
-
-    void ForceCleanup() {
-      RunCleanupsScope::ForceCleanup();
-      // Remap vars back to the original values.
-      for (auto I : SavedLocals) {
-        CGF.LocalDeclMap[I.first] = I.second;
-      }
-      SavedLocals.clear();
-    }
-
-    /// \brief Exit scope - all the mapped variables are restored.
-    ~OMPPrivateScope() { ForceCleanup(); }
-  };
-
   CodeGenPGO PGO;
 
 public:
@@ -1973,12 +1993,11 @@ public:
   llvm::Function *GenerateCapturedStmtFunctionEpilog(const CapturedStmt &S);
   llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S);
   llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S);
-  typedef llvm::DenseMap<const Decl *, llvm::Value *> OuterDeclMapTy;
   void EmitOMPAggregateAssign(LValue OriginalAddr, llvm::Value *PrivateAddr,
                               const Expr *AssignExpr, QualType Type,
                               const VarDecl *VDInit);
   void EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
-                                 OuterDeclMapTy &OuterDeclMap);
+                                 OMPPrivateScope &PrivateScope);
 
   void EmitOMPParallelDirective(const OMPParallelDirective &S);
   void EmitOMPSimdDirective(const OMPSimdDirective &S);





More information about the cfe-commits mailing list