summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2017-07-21 18:48:21 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2017-07-21 18:48:21 +0000
commitfa312f33f8409f43fab488ec983546b275199ab7 (patch)
treef2710f90420f0587cc1a681142001d6942d29999 /clang/lib
parent6ab9ea961435aa5341460f120b2c40abbf8528f7 (diff)
downloadbcm5719-llvm-fa312f33f8409f43fab488ec983546b275199ab7.tar.gz
bcm5719-llvm-fa312f33f8409f43fab488ec983546b275199ab7.zip
[OPENMP] Initial support for 'in_reduction' clause.
Parsing/sema analysis for 'in_reduction' clause for task-based directives. llvm-svn: 308768
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/OpenMPClause.cpp57
-rw-r--r--clang/lib/AST/StmtPrinter.cpp22
-rw-r--r--clang/lib/AST/StmtProfile.cpp24
-rw-r--r--clang/lib/Basic/OpenMPKinds.cpp6
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp1
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp27
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp188
-rw-r--r--clang/lib/Sema/TreeTransform.h61
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp37
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp19
10 files changed, 430 insertions, 12 deletions
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 2c4d159a1bc..9dcf5c19201 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -48,6 +48,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
return static_cast<const OMPReductionClause *>(C);
case OMPC_task_reduction:
return static_cast<const OMPTaskReductionClause *>(C);
+ case OMPC_in_reduction:
+ return static_cast<const OMPInReductionClause *>(C);
case OMPC_linear:
return static_cast<const OMPLinearClause *>(C);
case OMPC_if:
@@ -116,6 +118,8 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
return static_cast<const OMPReductionClause *>(C);
case OMPC_task_reduction:
return static_cast<const OMPTaskReductionClause *>(C);
+ case OMPC_in_reduction:
+ return static_cast<const OMPInReductionClause *>(C);
case OMPC_linear:
return static_cast<const OMPLinearClause *>(C);
case OMPC_schedule:
@@ -562,6 +566,59 @@ OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPTaskReductionClause(N);
}
+void OMPInReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
+ assert(Privates.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(Privates.begin(), Privates.end(), varlist_end());
+}
+
+void OMPInReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
+ assert(
+ LHSExprs.size() == varlist_size() &&
+ "Number of LHS expressions is not the same as the preallocated buffer");
+ std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end());
+}
+
+void OMPInReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
+ assert(
+ RHSExprs.size() == varlist_size() &&
+ "Number of RHS expressions is not the same as the preallocated buffer");
+ std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
+}
+
+void OMPInReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
+ assert(ReductionOps.size() == varlist_size() && "Number of in reduction "
+ "expressions is not the same "
+ "as the preallocated buffer");
+ std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
+}
+
+OMPInReductionClause *OMPInReductionClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
+ NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
+ ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
+ ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit,
+ Expr *PostUpdate) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
+ OMPInReductionClause *Clause = new (Mem) OMPInReductionClause(
+ StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
+ Clause->setVarRefs(VL);
+ Clause->setPrivates(Privates);
+ Clause->setLHSExprs(LHSExprs);
+ Clause->setRHSExprs(RHSExprs);
+ Clause->setReductionOps(ReductionOps);
+ Clause->setPreInitStmt(PreInit);
+ Clause->setPostUpdateExpr(PostUpdate);
+ return Clause;
+}
+
+OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
+ return new (Mem) OMPInReductionClause(N);
+}
+
OMPFlushClause *OMPFlushClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 5ebaa32b49c..f4418c92406 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -859,6 +859,28 @@ void OMPClausePrinter::VisitOMPTaskReductionClause(
}
}
+void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "in_reduction(";
+ NestedNameSpecifier *QualifierLoc =
+ Node->getQualifierLoc().getNestedNameSpecifier();
+ OverloadedOperatorKind OOK =
+ Node->getNameInfo().getName().getCXXOverloadedOperator();
+ if (QualifierLoc == nullptr && OOK != OO_None) {
+ // Print reduction identifier in C format
+ OS << getOperatorSpelling(OOK);
+ } else {
+ // Use C++ format
+ if (QualifierLoc != nullptr)
+ QualifierLoc->print(OS, Policy);
+ OS << Node->getNameInfo();
+ }
+ OS << ":";
+ VisitOMPClauseList(Node, ' ');
+ OS << ")";
+ }
+}
+
void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
if (!Node->varlist_empty()) {
OS << "linear";
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index e06386018d6..a86fded2a2c 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -573,6 +573,30 @@ void OMPClauseProfiler::VisitOMPTaskReductionClause(
Profiler->VisitStmt(E);
}
}
+void OMPClauseProfiler::VisitOMPInReductionClause(
+ const OMPInReductionClause *C) {
+ Profiler->VisitNestedNameSpecifier(
+ C->getQualifierLoc().getNestedNameSpecifier());
+ Profiler->VisitName(C->getNameInfo().getName());
+ VisitOMPClauseList(C);
+ VistOMPClauseWithPostUpdate(C);
+ for (auto *E : C->privates()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->lhs_exprs()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->rhs_exprs()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+ for (auto *E : C->reduction_ops()) {
+ if (E)
+ Profiler->VisitStmt(E);
+ }
+}
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
VistOMPClauseWithPostUpdate(C);
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 050c0cc466d..5eea4b5a5cf 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -139,6 +139,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
@@ -279,6 +280,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
@@ -851,8 +853,8 @@ bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
return Kind == OMPC_private || Kind == OMPC_firstprivate ||
Kind == OMPC_lastprivate || Kind == OMPC_linear ||
- Kind == OMPC_reduction ||
- Kind == OMPC_task_reduction; // TODO add next clauses like 'reduction'.
+ Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
+ Kind == OMPC_in_reduction; // TODO add next clauses like 'reduction'.
}
bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) {
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 6135cf31d17..b9f5d3979eb 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -3467,6 +3467,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_lastprivate:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_collapse:
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index d9a088595ab..353b0795f66 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1102,7 +1102,8 @@ bool Parser::ParseOpenMPSimpleVarList(
/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
/// thread_limit-clause | priority-clause | grainsize-clause |
/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
-/// from-clause | is_device_ptr-clause | task_reduction-clause
+/// from-clause | is_device_ptr-clause | task_reduction-clause |
+/// in_reduction-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -1221,6 +1222,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -1586,7 +1588,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
// Handle reduction-identifier for reduction clause.
- if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) {
+ if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
+ Kind == OMPC_in_reduction) {
ColonProtectionRAIIObject ColonRAII(*this);
if (getLangOpts().CPlusPlus)
ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
@@ -1734,13 +1737,14 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
}
- bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
- Kind != OMPC_depend && Kind != OMPC_map) ||
- (Kind == OMPC_reduction && !InvalidReductionId) ||
- (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
- (!MapTypeModifierSpecified ||
- Data.MapTypeModifier == OMPC_MAP_always)) ||
- (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
+ bool IsComma =
+ (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
+ Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
+ (Kind == OMPC_reduction && !InvalidReductionId) ||
+ (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
+ (!MapTypeModifierSpecified ||
+ Data.MapTypeModifier == OMPC_MAP_always)) ||
+ (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
@@ -1796,7 +1800,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
}
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
-/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction' or 'task_reduction'.
+/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
+/// 'in_reduction'.
///
/// private-clause:
/// 'private' '(' list ')'
@@ -1814,6 +1819,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
/// 'reduction' '(' reduction-identifier ':' list ')'
/// task_reduction-clause:
/// 'task_reduction' '(' reduction-identifier ':' list ')'
+/// in_reduction-clause:
+/// 'in_reduction' '(' reduction-identifier ':' list ')'
/// copyprivate-clause:
/// 'copyprivate' '(' list ')'
/// flush-clause:
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 1bf44127f23..1eb2ec45dbe 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -31,6 +31,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
+#include "llvm/ADT/PointerEmbeddedInt.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -84,9 +85,26 @@ private:
CriticalsWithHintsTy;
typedef llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>
DoacrossDependMapTy;
+ struct ReductionData {
+ SourceRange ReductionRange;
+ llvm::PointerUnion<const Expr *,
+ llvm::PointerEmbeddedInt<BinaryOperatorKind>>
+ ReductionOp;
+ ReductionData() = default;
+ void set(BinaryOperatorKind BO, SourceRange RR) {
+ ReductionRange = RR;
+ ReductionOp = BO;
+ }
+ void set(const Expr *RefExpr, SourceRange RR) {
+ ReductionRange = RR;
+ ReductionOp = RefExpr;
+ }
+ };
+ typedef llvm::DenseMap<ValueDecl *, ReductionData> DeclReductionMapTy;
struct SharingMapTy final {
DeclSAMapTy SharingMap;
+ DeclReductionMapTy ReductionMap;
AlignedMapTy AlignedMap;
MappedExprComponentsTy MappedExprComponents;
LoopControlVariablesMapTy LCVMap;
@@ -221,6 +239,21 @@ public:
void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
DeclRefExpr *PrivateCopy = nullptr);
+ /// Adds additional information for the reduction items with the reduction id
+ /// represented as an operator.
+ void addReductionData(ValueDecl *D, SourceRange SR, BinaryOperatorKind BOK);
+ /// Adds additional information for the reduction items with the reduction id
+ /// represented as reduction identifier.
+ void addReductionData(ValueDecl *D, SourceRange SR, const Expr *ReductionRef);
+ /// Returns the location and reduction operation from the innermost parent
+ /// region for the given \p D.
+ bool getTopMostReductionData(ValueDecl *D, SourceRange &SR,
+ BinaryOperatorKind &BOK);
+ /// Returns the location and reduction operation from the innermost parent
+ /// region for the given \p D.
+ bool getTopMostReductionData(ValueDecl *D, SourceRange &SR,
+ const Expr *&ReductionRef);
+
/// \brief Returns data sharing attributes from top of the stack for the
/// specified declaration.
DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
@@ -709,6 +742,81 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
}
}
+void DSAStackTy::addReductionData(ValueDecl *D, SourceRange SR,
+ BinaryOperatorKind BOK) {
+ D = getCanonicalDecl(D);
+ assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
+ auto &Data = Stack.back().first.back().SharingMap[D];
+ assert(
+ Data.Attributes == OMPC_reduction &&
+ "Additional reduction info may be specified only for reduction items.");
+ auto &ReductionData = Stack.back().first.back().ReductionMap[D];
+ assert(ReductionData.ReductionRange.isInvalid() &&
+ "Additional reduction info may be specified only once for reduction "
+ "items.");
+ ReductionData.set(BOK, SR);
+}
+
+void DSAStackTy::addReductionData(ValueDecl *D, SourceRange SR,
+ const Expr *ReductionRef) {
+ D = getCanonicalDecl(D);
+ assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
+ auto &Data = Stack.back().first.back().SharingMap[D];
+ assert(
+ Data.Attributes == OMPC_reduction &&
+ "Additional reduction info may be specified only for reduction items.");
+ auto &ReductionData = Stack.back().first.back().ReductionMap[D];
+ assert(ReductionData.ReductionRange.isInvalid() &&
+ "Additional reduction info may be specified only once for reduction "
+ "items.");
+ ReductionData.set(ReductionRef, SR);
+}
+
+bool DSAStackTy::getTopMostReductionData(ValueDecl *D, SourceRange &SR,
+ BinaryOperatorKind &BOK) {
+ D = getCanonicalDecl(D);
+ assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
+ "Data-sharing attributes stack is empty or has only 1 region.");
+ for (auto I = std::next(Stack.back().first.rbegin(), 0),
+ E = Stack.back().first.rend();
+ I != E; std::advance(I, 1)) {
+ auto &Data = I->SharingMap[D];
+ if (Data.Attributes != OMPC_reduction)
+ continue;
+ auto &ReductionData = I->ReductionMap[D];
+ if (!ReductionData.ReductionOp ||
+ ReductionData.ReductionOp.is<const Expr *>())
+ return false;
+ SR = ReductionData.ReductionRange;
+ BOK = ReductionData.ReductionOp
+ .get<llvm::PointerEmbeddedInt<BinaryOperatorKind>>();
+ return true;
+ }
+ return false;
+}
+
+bool DSAStackTy::getTopMostReductionData(ValueDecl *D, SourceRange &SR,
+ const Expr *&ReductionRef) {
+ D = getCanonicalDecl(D);
+ assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
+ "Data-sharing attributes stack is empty or has only 1 region.");
+ for (auto I = std::next(Stack.back().first.rbegin(), 0),
+ E = Stack.back().first.rend();
+ I != E; std::advance(I, 1)) {
+ auto &Data = I->SharingMap[D];
+ if (Data.Attributes != OMPC_reduction)
+ continue;
+ auto &ReductionData = I->ReductionMap[D];
+ if (!ReductionData.ReductionOp ||
+ !ReductionData.ReductionOp.is<const Expr *>())
+ return false;
+ SR = ReductionData.ReductionRange;
+ ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
+ return true;
+ }
+ return false;
+}
+
bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
D = D->getCanonicalDecl();
if (!isStackEmpty() && Stack.back().first.size() > 1) {
@@ -6853,6 +6961,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -7157,6 +7266,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_lastprivate:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_default:
case OMPC_proc_bind:
@@ -7473,6 +7583,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -7631,6 +7742,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -7829,6 +7941,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_shared:
case OMPC_reduction:
case OMPC_task_reduction:
+ case OMPC_in_reduction:
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
@@ -7946,6 +8059,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
EndLoc, ReductionIdScopeSpec,
ReductionId);
break;
+ case OMPC_in_reduction:
+ Res =
+ ActOnOpenMPInReductionClause(VarList, StartLoc, LParenLoc, ColonLoc,
+ EndLoc, ReductionIdScopeSpec, ReductionId);
+ break;
case OMPC_linear:
Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
LinKind, DepLinMapLoc, ColonLoc, EndLoc);
@@ -9428,6 +9546,51 @@ static bool ActOnOMPReductionKindClause(
continue;
}
+ // OpenMP [2.15.4.6, Restrictions, p.2]
+ // A list item that appears in an in_reduction clause of a task construct
+ // must appear in a task_reduction clause of a construct associated with a
+ // taskgroup region that includes the participating task in its taskgroup
+ // set. The construct associated with the innermost region that meets this
+ // condition must specify the same reduction-identifier as the in_reduction
+ // clause.
+ if (ClauseKind == OMPC_in_reduction) {
+ DVar = Stack->hasDSA(
+ D, [](OpenMPClauseKind K) { return K != OMPC_unknown; },
+ [](OpenMPDirectiveKind K) { return K == OMPD_taskgroup; },
+ /*FromParent=*/true);
+ if (DVar.CKind != OMPC_reduction || DVar.DKind != OMPD_taskgroup) {
+ S.Diag(ELoc, diag::err_omp_in_reduction_not_task_reduction);
+ continue;
+ }
+ SourceRange ParentSR;
+ BinaryOperatorKind ParentBOK;
+ const Expr *ParentReductionOp;
+ bool IsParentBOK = Stack->getTopMostReductionData(D, ParentSR, ParentBOK);
+ bool IsParentReductionOp =
+ Stack->getTopMostReductionData(D, ParentSR, ParentReductionOp);
+ if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
+ (DeclareReductionRef.isUsable() && IsParentBOK) || BOK != ParentBOK ||
+ IsParentReductionOp) {
+ bool EmitError = true;
+ if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
+ llvm::FoldingSetNodeID RedId, ParentRedId;
+ ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
+ DeclareReductionRef.get()->Profile(RedId, Context,
+ /*Canonical=*/true);
+ EmitError = RedId != ParentRedId;
+ }
+ if (EmitError) {
+ S.Diag(ReductionId.getLocStart(),
+ diag::err_omp_reduction_identifier_mismatch)
+ << ReductionIdRange << RefExpr->getSourceRange();
+ S.Diag(ParentSR.getBegin(),
+ diag::note_omp_previous_reduction_identifier)
+ << ParentSR << DVar.RefExpr->getSourceRange();
+ continue;
+ }
+ }
+ }
+
DeclRefExpr *Ref = nullptr;
Expr *VarsExpr = RefExpr->IgnoreParens();
if (!VD && !S.CurContext->isDependentContext()) {
@@ -9465,6 +9628,10 @@ static bool ActOnOMPReductionKindClause(
// All reduction items are still marked as reduction (to do not increase
// code base size).
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
+ if (DeclareReductionRef.isUsable())
+ Stack->addReductionData(D, ReductionIdRange, DeclareReductionRef.get());
+ else
+ Stack->addReductionData(D, ReductionIdRange, BOK);
RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get());
}
return RD.Vars.empty();
@@ -9512,6 +9679,27 @@ OMPClause *Sema::ActOnOpenMPTaskReductionClause(
buildPostUpdate(*this, RD.ExprPostUpdates));
}
+OMPClause *Sema::ActOnOpenMPInReductionClause(
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions) {
+ ReductionData RD(VarList.size());
+
+ if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
+ StartLoc, LParenLoc, ColonLoc, EndLoc,
+ ReductionIdScopeSpec, ReductionId,
+ UnresolvedReductions, RD))
+ return nullptr;
+
+ return OMPInReductionClause::Create(
+ Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
+ ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
+ RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
+ buildPreInits(Context, RD.ExprCaptures),
+ buildPostUpdate(*this, RD.ExprPostUpdates));
+}
+
bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
SourceLocation LinLoc) {
if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 91da9f88c59..ee67e15b9ae 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1666,6 +1666,22 @@ public:
ReductionId, UnresolvedReductions);
}
+ /// Build a new OpenMP 'in_reduction' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *
+ RebuildOMPInReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions) {
+ return getSema().ActOnOpenMPInReductionClause(
+ VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec,
+ ReductionId, UnresolvedReductions);
+ }
+
/// \brief Build a new OpenMP 'linear' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -8461,6 +8477,51 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause(
template <typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ CXXScopeSpec ReductionIdScopeSpec;
+ ReductionIdScopeSpec.Adopt(C->getQualifierLoc());
+
+ DeclarationNameInfo NameInfo = C->getNameInfo();
+ if (NameInfo.getName()) {
+ NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
+ if (!NameInfo.getName())
+ return nullptr;
+ }
+ // Build a list of all UDR decls with the same names ranged by the Scopes.
+ // The Scope boundary is a duplication of the previous decl.
+ llvm::SmallVector<Expr *, 16> UnresolvedReductions;
+ for (auto *E : C->reduction_ops()) {
+ // Transform all the decls.
+ if (E) {
+ auto *ULE = cast<UnresolvedLookupExpr>(E);
+ UnresolvedSet<8> Decls;
+ for (auto *D : ULE->decls()) {
+ NamedDecl *InstD =
+ cast<NamedDecl>(getDerived().TransformDecl(E->getExprLoc(), D));
+ Decls.addDecl(InstD, InstD->getAccess());
+ }
+ UnresolvedReductions.push_back(UnresolvedLookupExpr::Create(
+ SemaRef.Context, /*NamingClass=*/nullptr,
+ ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
+ /*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end()));
+ } else
+ UnresolvedReductions.push_back(nullptr);
+ }
+ return getDerived().RebuildOMPInReductionClause(
+ Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
+ C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
+}
+
+template <typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 21adcddd3a4..272d30260cf 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1837,6 +1837,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_task_reduction:
C = OMPTaskReductionClause::CreateEmpty(Context, Reader->Record.readInt());
break;
+ case OMPC_in_reduction:
+ C = OMPInReductionClause::CreateEmpty(Context, Reader->Record.readInt());
+ break;
case OMPC_linear:
C = OMPLinearClause::CreateEmpty(Context, Reader->Record.readInt());
break;
@@ -2175,6 +2178,40 @@ void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
C->setReductionOps(Vars);
}
+void OMPClauseReader::VisitOMPInReductionClause(OMPInReductionClause *C) {
+ VisitOMPClauseWithPostUpdate(C);
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setColonLoc(Reader->ReadSourceLocation());
+ NestedNameSpecifierLoc NNSL = Reader->Record.readNestedNameSpecifierLoc();
+ DeclarationNameInfo DNI;
+ Reader->ReadDeclarationNameInfo(DNI);
+ C->setQualifierLoc(NNSL);
+ C->setNameInfo(DNI);
+
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setPrivates(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setLHSExprs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setRHSExprs(Vars);
+ Vars.clear();
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setReductionOps(Vars);
+}
+
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
VisitOMPClauseWithPostUpdate(C);
C->setLParenLoc(Reader->ReadSourceLocation());
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index ae2e0b88c31..f8e41eda53a 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1982,6 +1982,25 @@ void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
Record.AddStmt(E);
}
+void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) {
+ Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPostUpdate(C);
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getColonLoc());
+ Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
+ Record.AddDeclarationNameInfo(C->getNameInfo());
+ for (auto *VE : C->varlists())
+ Record.AddStmt(VE);
+ for (auto *VE : C->privates())
+ Record.AddStmt(VE);
+ for (auto *E : C->lhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->rhs_exprs())
+ Record.AddStmt(E);
+ for (auto *E : C->reduction_ops())
+ Record.AddStmt(E);
+}
+
void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
Record.push_back(C->varlist_size());
VisitOMPClauseWithPostUpdate(C);
OpenPOWER on IntegriCloud