[OPENMP] Fix the restrictions for in_reduction clause.

This patch allows to use in_reduction clause even if the innermost
directive is not taskgroup.

llvm-svn: 308883
This commit is contained in:
Alexey Bataev 2017-07-24 14:52:13 +00:00
parent 3e05105486
commit f189cb79d4
2 changed files with 61 additions and 38 deletions

View File

@ -57,6 +57,10 @@ public:
DeclRefExpr *PrivateCopy = nullptr;
SourceLocation ImplicitDSALoc;
DSAVarData() = default;
DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, Expr *RefExpr,
DeclRefExpr *PrivateCopy, SourceLocation ImplicitDSALoc)
: DKind(DKind), CKind(CKind), RefExpr(RefExpr),
PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {}
};
typedef llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>
OperatorOffsetTy;
@ -246,12 +250,12 @@ public:
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);
DSAVarData getTopMostTaskgroupReductionData(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);
DSAVarData getTopMostTaskgroupReductionData(ValueDecl *D, SourceRange &SR,
const Expr *&ReductionRef);
/// \brief Returns data sharing attributes from top of the stack for the
/// specified declaration.
@ -769,48 +773,54 @@ void DSAStackTy::addReductionData(ValueDecl *D, SourceRange SR,
ReductionData.set(ReductionRef, SR);
}
bool DSAStackTy::getTopMostReductionData(ValueDecl *D, SourceRange &SR,
BinaryOperatorKind &BOK) {
DSAStackTy::DSAVarData
DSAStackTy::getTopMostTaskgroupReductionData(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),
assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
if (Stack.back().first.empty())
return DSAVarData();
for (auto I = std::next(Stack.back().first.rbegin(), 1),
E = Stack.back().first.rend();
I != E; std::advance(I, 1)) {
auto &Data = I->SharingMap[D];
if (Data.Attributes != OMPC_reduction)
if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
continue;
auto &ReductionData = I->ReductionMap[D];
if (!ReductionData.ReductionOp ||
ReductionData.ReductionOp.is<const Expr *>())
return false;
return DSAVarData();
SR = ReductionData.ReductionRange;
BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
return true;
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
Data.PrivateCopy, I->DefaultAttrLoc);
}
return false;
return DSAVarData();
}
bool DSAStackTy::getTopMostReductionData(ValueDecl *D, SourceRange &SR,
const Expr *&ReductionRef) {
DSAStackTy::DSAVarData
DSAStackTy::getTopMostTaskgroupReductionData(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),
assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
if (Stack.back().first.empty())
return DSAVarData();
for (auto I = std::next(Stack.back().first.rbegin(), 1),
E = Stack.back().first.rend();
I != E; std::advance(I, 1)) {
auto &Data = I->SharingMap[D];
if (Data.Attributes != OMPC_reduction)
if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
continue;
auto &ReductionData = I->ReductionMap[D];
if (!ReductionData.ReductionOp ||
!ReductionData.ReductionOp.is<const Expr *>())
return false;
return DSAVarData();
SR = ReductionData.ReductionRange;
ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
return true;
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
Data.PrivateCopy, I->DefaultAttrLoc);
}
return false;
return DSAVarData();
}
bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
@ -9550,20 +9560,20 @@ static bool ActOnOMPReductionKindClause(
// 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);
DSAStackTy::DSAVarData ParentBOKDSA =
Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK);
DSAStackTy::DSAVarData ParentReductionOpDSA =
Stack->getTopMostTaskgroupReductionData(D, ParentSR,
ParentReductionOp);
bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
if (!IsParentBOK && !IsParentReductionOp) {
S.Diag(ELoc, diag::err_omp_in_reduction_not_task_reduction);
continue;
}
if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
(DeclareReductionRef.isUsable() && IsParentBOK) || BOK != ParentBOK ||
IsParentReductionOp) {
@ -9581,7 +9591,10 @@ static bool ActOnOMPReductionKindClause(
<< ReductionIdRange << RefExpr->getSourceRange();
S.Diag(ParentSR.getBegin(),
diag::note_omp_previous_reduction_identifier)
<< ParentSR << DVar.RefExpr->getSourceRange();
<< ParentSR
<< (IsParentBOK ? ParentBOKDSA.RefExpr
: ParentReductionOpDSA.RefExpr)
->getSourceRange();
continue;
}
}
@ -9624,10 +9637,12 @@ 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);
if (CurrDir == OMPD_taskgroup) {
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();

View File

@ -155,6 +155,14 @@ int main(int argc, char **argv) {
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0) final(a > 0) depend(inout : a,argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1)
foo();
// CHECK-NEXT: foo();
#pragma omp taskgroup task_reduction(min: arr1)
#pragma omp parallel reduction(+:arr1)
#pragma omp task in_reduction(min: arr1)
// CHECK-NEXT: #pragma omp taskgroup task_reduction(min: arr1)
// CHECK-NEXT: #pragma omp parallel reduction(+: arr1)
// CHECK-NEXT: #pragma omp task in_reduction(min: arr1)
foo();
// CHECK-NEXT: foo();
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
}