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 @@ -85,6 +85,7 @@ NODE(parser, AccEndBlockDirective) NODE(parser, AccEndCombinedDirective) NODE(parser, AccGangArgument) + NODE(parser, AccCollapseArg) 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 @@ -4097,6 +4097,11 @@ std::tuple, std::optional> t; }; +struct AccCollapseArg { + TUPLE_CLASS_BOILERPLATE(AccCollapseArg); + std::tuple t; +}; + struct AccClause { UNION_CLASS_BOILERPLATE(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 @@ -910,9 +910,16 @@ // Lower clauses mapped to attributes for (const Fortran::parser::AccClause &clause : accClauseList.v) { + mlir::Location clauseLocation = converter.genLocation(clause.source); if (const auto *collapseClause = std::get_if(&clause.u)) { - const auto *expr = Fortran::semantics::GetExpr(collapseClause->v); + const Fortran::parser::AccCollapseArg &arg = collapseClause->v; + const auto &force = std::get(arg.t); + if (force) + TODO(clauseLocation, "OpenACC collapse force modifier"); + const auto &intExpr = + std::get(arg.t); + const auto *expr = Fortran::semantics::GetExpr(intExpr); const std::optional collapseValue = Fortran::evaluate::ToInt64(*expr); if (collapseValue) { 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 @@ -72,6 +72,10 @@ maybe(("NUM:"_tok >> scalarIntExpr || scalarIntExpr)), maybe(", STATIC:" >> Parser{}))) +// 2.9.1 collapse +TYPE_PARSER(construct( + "FORCE:"_tok >> pure(true) || pure(false), scalarIntConstantExpr)) + // 2.5.13 Reduction // Operator for reduction TYPE_PARSER(sourced(construct( 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 @@ -1912,6 +1912,14 @@ Walk("NUM:", std::get>(x.t)); Walk(", STATIC:", std::get>(x.t)); } + void Unparse(const AccCollapseArg &x) { + const auto &force{std::get(x.t)}; + const auto &collapseValue{std::get(x.t)}; + if (force) { + Put("FORCE:"); + } + Walk(collapseValue); + } void Unparse(const OpenACCBlockConstruct &x) { BeginOpenACC(); Word("!$ACC "); 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 @@ -307,8 +307,6 @@ } // Clause checkers -CHECK_REQ_SCALAR_INT_CONSTANT_CLAUSE(Collapse, ACCC_collapse) - CHECK_SIMPLE_CLAUSE(Auto, ACCC_auto) CHECK_SIMPLE_CLAUSE(Async, ACCC_async) CHECK_SIMPLE_CLAUSE(Attach, ACCC_attach) @@ -432,6 +430,15 @@ } } +void AccStructureChecker::Enter(const parser::AccClause::Collapse &x) { + CheckAllowed(llvm::acc::Clause::ACCC_collapse); + const parser::AccCollapseArg &accCollapseArg = x.v; + const auto &collapseValue{ + std::get(accCollapseArg.t)}; + RequiresConstantPositiveParameter( + llvm::acc::Clause::ACCC_collapse, collapseValue); +} + llvm::StringRef AccStructureChecker::getClauseName(llvm::acc::Clause clause) { return llvm::acc::getOpenACCClauseName(clause); } diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -904,7 +904,9 @@ for (const auto &clause : x.v) { if (const auto *collapseClause{ std::get_if(&clause.u)}) { - if (const auto v{EvaluateInt64(context_, collapseClause->v)}) { + const parser::AccCollapseArg &arg = collapseClause->v; + const auto &collapseValue{std::get(arg.t)}; + if (const auto v{EvaluateInt64(context_, collapseValue)}) { collapseLevel = *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,17 @@ !CHECK-LABEL: PROGRAM bug47659 !CHECK: !$ACC PARALLEL LOOP + + +subroutine acc_loop() + integer :: i, j + + !$acc loop collapse(force: 2) + do i = 1, 10 + do j = 1, 10 + end do + end do +end subroutine + +!CHECK-LABEL: SUBROUTINE acc_loop +!CHECK: !$ACC LOOP COLLAPSE(FORCE:2_4) 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 @@ -56,7 +56,7 @@ // 2.9.1 def ACCC_Collapse : Clause<"collapse"> { - let flangClass = "ScalarIntConstantExpr"; + let flangClass = "AccCollapseArg"; } // 2.7.6