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
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 92a7431..d8d715d 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -586,6 +586,68 @@
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 @@
};
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 @@
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);