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