forked from OSchip/llvm-project
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). llvm-svn: 219486
This commit is contained in:
parent
afe56ae75d
commit
435ad7ba5e
|
@ -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)
|
||||
|
|
|
@ -94,7 +94,7 @@ void CodeGenFunction::EmitOMPAggregateAssign(LValue OriginalAddr,
|
|||
|
||||
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::EmitOMPFirstprivateClause(
|
|||
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(CodeGenFunction &CGF, CodeGenModule &CGM,
|
|||
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(CodeGenFunction &CGF, CodeGenModule &CGM,
|
|||
}
|
||||
}
|
||||
|
||||
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::EmitOMPSimdDirective(const OMPSimdDirective &S) {
|
|||
// 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::EmitOMPSimdDirective(const OMPSimdDirective &S) {
|
|||
} else {
|
||||
{
|
||||
OMPPrivateScope LoopScope(*this);
|
||||
LoopScope.addPrivates(S.counters());
|
||||
EmitPrivateLoopCounters(*this, LoopScope, S.counters());
|
||||
EmitOMPInnerLoop(S, LoopScope);
|
||||
}
|
||||
EmitOMPSimdFinal(S);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue