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 @@ -2736,19 +2736,47 @@ std::get(routineConstruct.t); if (name) TODO(loc, "acc routine with name"); - if (!clauses.v.empty()) - TODO(loc, "acc routine with clauses"); mlir::func::FuncOp func = builder.getFunction(); mlir::ModuleOp mod = builder.getModule(); mlir::OpBuilder modBuilder(mod.getBodyRegion()); std::stringstream routineOpName; routineOpName << accRoutinePrefix.str() << routineCounter++; - modBuilder.create( + auto routineOp = modBuilder.create( loc, routineOpName.str(), func.getName(), mlir::StringAttr{}, mlir::UnitAttr{}, mlir::UnitAttr{}, mlir::UnitAttr{}, mlir::UnitAttr{}, mlir::UnitAttr{}, mlir::UnitAttr{}, mlir::IntegerAttr{}); + for (const Fortran::parser::AccClause &clause : clauses.v) { + if (std::get_if(&clause.u)) { + routineOp.setSeqAttr(builder.getUnitAttr()); + } else if (const auto *gangClause = + std::get_if(&clause.u)) { + routineOp.setGangAttr(builder.getUnitAttr()); + if (gangClause->v) { + const Fortran::parser::AccGangArgList &x = *gangClause->v; + for (const Fortran::parser::AccGangArg &gangArg : x.v) { + if (const auto *dim = + std::get_if(&gangArg.u)) { + const std::optional dimValue = Fortran::evaluate::ToInt64( + *Fortran::semantics::GetExpr(dim->v)); + if (!dimValue) + mlir::emitError(loc, + "dim value must be a constant positive integer"); + routineOp.setGangDimAttr( + builder.getIntegerAttr(builder.getIntegerType(32), *dimValue)); + } + } + } + } else if (std::get_if(&clause.u)) { + routineOp.setVectorAttr(builder.getUnitAttr()); + } else if (std::get_if(&clause.u)) { + routineOp.setWorkerAttr(builder.getUnitAttr()); + } else if (std::get_if(&clause.u)) { + routineOp.setNohostAttr(builder.getUnitAttr()); + } + } + llvm::SmallVector routines; if (func.getOperation()->hasAttr(mlir::acc::getRoutineInfoAttrName())) { auto routineInfo = diff --git a/flang/test/Lower/OpenACC/acc-routine.f90 b/flang/test/Lower/OpenACC/acc-routine.f90 --- a/flang/test/Lower/OpenACC/acc-routine.f90 +++ b/flang/test/Lower/OpenACC/acc-routine.f90 @@ -2,9 +2,52 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s +! CHECK: acc.routine @acc_routine_6 func(@_QPacc_routine7) gang(dim = 1 : i32) +! CHECK: acc.routine @acc_routine_5 func(@_QPacc_routine6) nohost +! CHECK: acc.routine @acc_routine_4 func(@_QPacc_routine5) worker +! CHECK: acc.routine @acc_routine_3 func(@_QPacc_routine4) vector +! CHECK: acc.routine @acc_routine_2 func(@_QPacc_routine3) gang +! CHECK: acc.routine @acc_routine_1 func(@_QPacc_routine2) seq +! CHECK: acc.routine @acc_routine_0 func(@_QPacc_routine1) + subroutine acc_routine1() !$acc routine end subroutine -! CHECK: acc.routine @acc_routine_0 func(@_QPacc_routine1) ! CHECK-LABEL: func.func @_QPacc_routine1() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} + +subroutine acc_routine2() + !$acc routine seq +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine2() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>} + +subroutine acc_routine3() + !$acc routine gang +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine3() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_2]>} + +subroutine acc_routine4() + !$acc routine vector +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine4() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_3]>} + +subroutine acc_routine5() + !$acc routine worker +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine5() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_4]>} + +subroutine acc_routine6() + !$acc routine nohost +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine6() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_5]>} + +subroutine acc_routine7() + !$acc routine gang(dim:1) +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine7() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_6]>}