|
@@ -31,6 +31,7 @@
|
|
#include "clang/Sema/Scope.h"
|
|
#include "clang/Sema/Scope.h"
|
|
#include "clang/Sema/ScopeInfo.h"
|
|
#include "clang/Sema/ScopeInfo.h"
|
|
#include "clang/Sema/SemaInternal.h"
|
|
#include "clang/Sema/SemaInternal.h"
|
|
|
|
+#include "llvm/ADT/PointerEmbeddedInt.h"
|
|
using namespace clang;
|
|
using namespace clang;
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
//===----------------------------------------------------------------------===//
|
|
@@ -84,9 +85,26 @@ private:
|
|
CriticalsWithHintsTy;
|
|
CriticalsWithHintsTy;
|
|
typedef llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>
|
|
typedef llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>
|
|
DoacrossDependMapTy;
|
|
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 {
|
|
struct SharingMapTy final {
|
|
DeclSAMapTy SharingMap;
|
|
DeclSAMapTy SharingMap;
|
|
|
|
+ DeclReductionMapTy ReductionMap;
|
|
AlignedMapTy AlignedMap;
|
|
AlignedMapTy AlignedMap;
|
|
MappedExprComponentsTy MappedExprComponents;
|
|
MappedExprComponentsTy MappedExprComponents;
|
|
LoopControlVariablesMapTy LCVMap;
|
|
LoopControlVariablesMapTy LCVMap;
|
|
@@ -221,6 +239,21 @@ public:
|
|
void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
|
|
void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
|
|
DeclRefExpr *PrivateCopy = nullptr);
|
|
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
|
|
/// \brief Returns data sharing attributes from top of the stack for the
|
|
/// specified declaration.
|
|
/// specified declaration.
|
|
DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
|
|
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) {
|
|
bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
|
|
D = D->getCanonicalDecl();
|
|
D = D->getCanonicalDecl();
|
|
if (!isStackEmpty() && Stack.back().first.size() > 1) {
|
|
if (!isStackEmpty() && Stack.back().first.size() > 1) {
|
|
@@ -6853,6 +6961,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
|
|
case OMPC_shared:
|
|
case OMPC_shared:
|
|
case OMPC_reduction:
|
|
case OMPC_reduction:
|
|
case OMPC_task_reduction:
|
|
case OMPC_task_reduction:
|
|
|
|
+ case OMPC_in_reduction:
|
|
case OMPC_linear:
|
|
case OMPC_linear:
|
|
case OMPC_aligned:
|
|
case OMPC_aligned:
|
|
case OMPC_copyin:
|
|
case OMPC_copyin:
|
|
@@ -7157,6 +7266,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
|
|
case OMPC_lastprivate:
|
|
case OMPC_lastprivate:
|
|
case OMPC_reduction:
|
|
case OMPC_reduction:
|
|
case OMPC_task_reduction:
|
|
case OMPC_task_reduction:
|
|
|
|
+ case OMPC_in_reduction:
|
|
case OMPC_linear:
|
|
case OMPC_linear:
|
|
case OMPC_default:
|
|
case OMPC_default:
|
|
case OMPC_proc_bind:
|
|
case OMPC_proc_bind:
|
|
@@ -7473,6 +7583,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
|
|
case OMPC_shared:
|
|
case OMPC_shared:
|
|
case OMPC_reduction:
|
|
case OMPC_reduction:
|
|
case OMPC_task_reduction:
|
|
case OMPC_task_reduction:
|
|
|
|
+ case OMPC_in_reduction:
|
|
case OMPC_linear:
|
|
case OMPC_linear:
|
|
case OMPC_aligned:
|
|
case OMPC_aligned:
|
|
case OMPC_copyin:
|
|
case OMPC_copyin:
|
|
@@ -7631,6 +7742,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
|
|
case OMPC_shared:
|
|
case OMPC_shared:
|
|
case OMPC_reduction:
|
|
case OMPC_reduction:
|
|
case OMPC_task_reduction:
|
|
case OMPC_task_reduction:
|
|
|
|
+ case OMPC_in_reduction:
|
|
case OMPC_linear:
|
|
case OMPC_linear:
|
|
case OMPC_aligned:
|
|
case OMPC_aligned:
|
|
case OMPC_copyin:
|
|
case OMPC_copyin:
|
|
@@ -7829,6 +7941,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
|
|
case OMPC_shared:
|
|
case OMPC_shared:
|
|
case OMPC_reduction:
|
|
case OMPC_reduction:
|
|
case OMPC_task_reduction:
|
|
case OMPC_task_reduction:
|
|
|
|
+ case OMPC_in_reduction:
|
|
case OMPC_linear:
|
|
case OMPC_linear:
|
|
case OMPC_aligned:
|
|
case OMPC_aligned:
|
|
case OMPC_copyin:
|
|
case OMPC_copyin:
|
|
@@ -7946,6 +8059,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
|
|
EndLoc, ReductionIdScopeSpec,
|
|
EndLoc, ReductionIdScopeSpec,
|
|
ReductionId);
|
|
ReductionId);
|
|
break;
|
|
break;
|
|
|
|
+ case OMPC_in_reduction:
|
|
|
|
+ Res =
|
|
|
|
+ ActOnOpenMPInReductionClause(VarList, StartLoc, LParenLoc, ColonLoc,
|
|
|
|
+ EndLoc, ReductionIdScopeSpec, ReductionId);
|
|
|
|
+ break;
|
|
case OMPC_linear:
|
|
case OMPC_linear:
|
|
Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
|
|
Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
|
|
LinKind, DepLinMapLoc, ColonLoc, EndLoc);
|
|
LinKind, DepLinMapLoc, ColonLoc, EndLoc);
|
|
@@ -9428,6 +9546,51 @@ static bool ActOnOMPReductionKindClause(
|
|
continue;
|
|
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;
|
|
DeclRefExpr *Ref = nullptr;
|
|
Expr *VarsExpr = RefExpr->IgnoreParens();
|
|
Expr *VarsExpr = RefExpr->IgnoreParens();
|
|
if (!VD && !S.CurContext->isDependentContext()) {
|
|
if (!VD && !S.CurContext->isDependentContext()) {
|
|
@@ -9465,6 +9628,10 @@ static bool ActOnOMPReductionKindClause(
|
|
// All reduction items are still marked as reduction (to do not increase
|
|
// All reduction items are still marked as reduction (to do not increase
|
|
// code base size).
|
|
// code base size).
|
|
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
|
|
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());
|
|
RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get());
|
|
}
|
|
}
|
|
return RD.Vars.empty();
|
|
return RD.Vars.empty();
|
|
@@ -9512,6 +9679,27 @@ OMPClause *Sema::ActOnOpenMPTaskReductionClause(
|
|
buildPostUpdate(*this, RD.ExprPostUpdates));
|
|
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,
|
|
bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
|
|
SourceLocation LinLoc) {
|
|
SourceLocation LinLoc) {
|
|
if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
|
|
if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
|