diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -80,7 +80,7 @@ READ_FEATURE(AccEndAtomic) READ_FEATURE(AccEndBlockDirective) READ_FEATURE(AccEndCombinedDirective) - READ_FEATURE(AccGangArgument) + READ_FEATURE(AccGangArg) READ_FEATURE(AccObject) READ_FEATURE(AccObjectList) READ_FEATURE(AccObjectListWithModifier) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -81,7 +81,11 @@ NODE(parser, AccEndAtomic) NODE(parser, AccEndBlockDirective) NODE(parser, AccEndCombinedDirective) - NODE(parser, AccGangArgument) + NODE(parser, AccGangArg) + NODE(AccGangArg, Num) + NODE(AccGangArg, Dim) + NODE(AccGangArg, Static) + NODE(parser, AccGangArgList) NODE(parser, AccObject) NODE(parser, AccObjectList) NODE(parser, AccObjectListWithModifier) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4020,9 +4020,7 @@ }; struct AccSizeExpr { - TUPLE_CLASS_BOILERPLATE(AccSizeExpr); - CharBlock source; - std::tuple> t; // if null then * + WRAPPER_CLASS_BOILERPLATE(AccSizeExpr, std::optional); }; struct AccSizeExprList { @@ -4035,9 +4033,18 @@ CharBlock source; }; -struct AccGangArgument { - TUPLE_CLASS_BOILERPLATE(AccGangArgument); - std::tuple, std::optional> t; +// num, dim, static +struct AccGangArg { + UNION_CLASS_BOILERPLATE(AccGangArg); + WRAPPER_CLASS(Num, ScalarIntExpr); + WRAPPER_CLASS(Dim, ScalarIntExpr); + WRAPPER_CLASS(Static, AccSizeExpr); + std::variant u; + CharBlock source; +}; + +struct AccGangArgList { + WRAPPER_CLASS_BOILERPLATE(AccGangArgList, std::list); }; struct AccClause { diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -648,25 +648,26 @@ if (const auto *gangClause = std::get_if(&clause.u)) { if (gangClause->v) { - const Fortran::parser::AccGangArgument &x = *gangClause->v; - if (const auto &gangNumValue = - std::get>(x.t)) { - gangNum = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(gangNumValue.value()), stmtCtx)); - } - if (const auto &gangStaticValue = - std::get>(x.t)) { - const auto &expr = - std::get>( - gangStaticValue.value().t); - if (expr) { - gangStatic = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(*expr), stmtCtx)); - } else { - // * was passed as value and will be represented as a special - // constant. - gangStatic = firOpBuilder.createIntegerConstant( - clauseLocation, firOpBuilder.getIndexType(), starCst); + const Fortran::parser::AccGangArgList &x = *gangClause->v; + for (const Fortran::parser::AccGangArg &gangArg : x.v) { + if (const auto *num = + std::get_if(&gangArg.u)) { + gangNum = fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(num->v), stmtCtx)); + } else if (const auto *staticArg = + std::get_if( + &gangArg.u)) { + + const Fortran::parser::AccSizeExpr &sizeExpr = staticArg->v; + if (sizeExpr.v) { + gangStatic = fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(*sizeExpr.v), stmtCtx)); + } else { + // * was passed as value and will be represented as a special + // constant. + gangStatic = firOpBuilder.createIntegerConstant( + clauseLocation, firOpBuilder.getIndexType(), starCst); + } } } } diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp --- a/flang/lib/Parser/openacc-parsers.cpp +++ b/flang/lib/Parser/openacc-parsers.cpp @@ -66,11 +66,20 @@ "*" >> construct>())) TYPE_PARSER(construct(nonemptyList(Parser{}))) -// 2.9 (1607) gang-arg is: -// [[num:]int-expr][[,]static:size-expr] -TYPE_PARSER(construct( - maybe(("NUM:"_tok >> scalarIntExpr || scalarIntExpr)), - maybe(", STATIC:" >> Parser{}))) +// 2.9 gang-arg is one of : +// [num:]int-expr +// dim:int-expr +// static:size-expr +TYPE_PARSER(construct(construct( + "STATIC: " >> Parser{})) || + construct( + construct("DIM: " >> scalarIntExpr)) || + construct( + construct(maybe("NUM: "_tok) >> scalarIntExpr))) + +// 2.9 gang-arg-list +TYPE_PARSER( + construct(many(maybe(","_tok) >> Parser{}))) // 2.5.13 Reduction // Operator for reduction diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -1884,9 +1884,19 @@ } } void Unparse(const AccClauseList &x) { Walk(" ", x.v, " "); } - void Unparse(const AccGangArgument &x) { - Walk("NUM:", std::get>(x.t)); - Walk(", STATIC:", std::get>(x.t)); + void Unparse(const AccGangArgList &x) { Walk(x.v, ","); } + void Before(const AccSizeExpr &x) { + if (!x.v) + Put("*"); + } + void Before(const AccGangArg &x) { + common::visit(common::visitors{ + [&](const AccGangArg::Num &) { Word("NUM:"); }, + [&](const AccGangArg::Dim &) { Word("DIM:"); }, + [&](const AccGangArg::Static &) { Word("STATIC:"); }, + [](const StatOrErrmsg &) {}, + }, + x.u); } void Unparse(const OpenACCBlockConstruct &x) { BeginOpenACC(); diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp --- a/flang/lib/Semantics/check-acc-structure.cpp +++ b/flang/lib/Semantics/check-acc-structure.cpp @@ -326,7 +326,6 @@ CHECK_SIMPLE_CLAUSE(DeviceType, ACCC_device_type) CHECK_SIMPLE_CLAUSE(Finalize, ACCC_finalize) CHECK_SIMPLE_CLAUSE(Firstprivate, ACCC_firstprivate) -CHECK_SIMPLE_CLAUSE(Gang, ACCC_gang) CHECK_SIMPLE_CLAUSE(Host, ACCC_host) CHECK_SIMPLE_CLAUSE(If, ACCC_if) CHECK_SIMPLE_CLAUSE(IfPresent, ACCC_if_present) @@ -407,6 +406,26 @@ } } +void AccStructureChecker::Enter(const parser::AccClause::Gang &g) { + CheckAllowed(llvm::acc::Clause::ACCC_gang); + + if (g.v) { + bool hasNum = false; + bool hasDim = false; + const Fortran::parser::AccGangArgList &x = *g.v; + for (const Fortran::parser::AccGangArg &gangArg : x.v) { + if (std::get_if(&gangArg.u)) + hasNum = true; + else if (std::get_if(&gangArg.u)) + hasDim = true; + } + + if (hasDim && hasNum) + context_.Say(GetContext().clauseSource, + "The num argument is not allowed when dim is specified"_err_en_US); + } +} + void AccStructureChecker::Enter(const parser::AccClause::Self &x) { CheckAllowed(llvm::acc::Clause::ACCC_self); const std::optional &accSelfClause = x.v; diff --git a/flang/test/Parser/acc-unparse.f90 b/flang/test/Parser/acc-unparse.f90 --- a/flang/test/Parser/acc-unparse.f90 +++ b/flang/test/Parser/acc-unparse.f90 @@ -17,3 +17,53 @@ !CHECK-LABEL: PROGRAM bug47659 !CHECK: !$ACC PARALLEL LOOP + +subroutine acc_loop(a) + real :: a(10) + integer :: i, gangNum, gangDim, gangStatic + +! CHECK-LABEL: acc_loop + + !$acc loop gang + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG + + !$acc loop gang(gangNum) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(NUM:gangnum) + + !$acc loop gang(num: gangNum) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(NUM:gangnum) + + !$acc loop gang(dim: gangDim) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(DIM:gangdim) + + !$acc loop gang(static:gangStatic) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(STATIC:gangstatic) + + !$acc loop gang(static:*) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(STATIC:*) + + !$acc loop gang(static:gangStatic, dim: gangDim) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(STATIC:gangstatic,DIM:gangdim) + +end subroutine diff --git a/flang/test/Semantics/OpenACC/acc-loop.f90 b/flang/test/Semantics/OpenACC/acc-loop.f90 --- a/flang/test/Semantics/OpenACC/acc-loop.f90 +++ b/flang/test/Semantics/OpenACC/acc-loop.f90 @@ -257,4 +257,10 @@ a(i) = 3.14 end do end do + + !ERROR: The num argument is not allowed when dim is specified + !$acc loop gang(1, dim: 2) + do i = 1, N + end do + end program openacc_loop_validity diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td --- a/llvm/include/llvm/Frontend/OpenACC/ACC.td +++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td @@ -147,7 +147,7 @@ // 2.9.2 def ACCC_Gang : Clause<"gang"> { - let flangClass = "AccGangArgument"; + let flangClass = "AccGangArgList"; let isValueOptional = true; }