diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h --- a/flang/include/flang/Lower/OpenACC.h +++ b/flang/include/flang/Lower/OpenACC.h @@ -15,7 +15,7 @@ namespace Fortran { namespace parser { -struct OpenACCConstruct; +struct OpenACCLoopConstruct; } // namespace parser namespace lower { @@ -26,8 +26,8 @@ struct Evaluation; } // namespace pft -void genOpenACCConstruct(AbstractConverter &, pft::Evaluation &, - const parser::OpenACCConstruct &); +void genACC(AbstractConverter &, pft::Evaluation &, + const parser::OpenACCLoopConstruct &); } // namespace lower } // namespace Fortran diff --git a/flang/include/flang/Optimizer/Dialect/FIRDialect.h b/flang/include/flang/Optimizer/Dialect/FIRDialect.h --- a/flang/include/flang/Optimizer/Dialect/FIRDialect.h +++ b/flang/include/flang/Optimizer/Dialect/FIRDialect.h @@ -38,6 +38,7 @@ [[maybe_unused]] static bool init_once = [] { mlir::registerDialect(); mlir::registerDialect(); + mlir::registerDialect(); mlir::registerDialect(); mlir::registerDialect(); mlir::registerDialect(); 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 @@ -15,38 +15,57 @@ #include "flang/Lower/FIRBuilder.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Parser/parse-tree.h" +#include "flang/Semantics/tools.h" +#include "mlir/Dialect/OpenACC/OpenACC.h" #include "llvm/Frontend/OpenACC/ACC.h.inc" #define TODO() llvm_unreachable("not yet implemented") -void Fortran::lower::genOpenACCConstruct( +void Fortran::lower::genACC( Fortran::lower::AbstractConverter &absConv, Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenACCConstruct &accConstruct) { - - std::visit( - common::visitors{ - [&](const Fortran::parser::OpenACCBlockConstruct &blockConstruct) { - TODO(); - }, - [&](const Fortran::parser::OpenACCCombinedConstruct - &combinedConstruct) { TODO(); }, - [&](const Fortran::parser::OpenACCLoopConstruct &loopConstruct) { - TODO(); - }, - [&](const Fortran::parser::OpenACCStandaloneConstruct - &standaloneConstruct) { TODO(); }, - [&](const Fortran::parser::OpenACCRoutineConstruct - &routineConstruct) { TODO(); }, - [&](const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) { - TODO(); - }, - [&](const Fortran::parser::OpenACCWaitConstruct &waitConstruct) { - TODO(); - }, - [&](const Fortran::parser::OpenACCAtomicConstruct &atomicConstruct) { - TODO(); - }, - }, - accConstruct.u); + const Fortran::parser::OpenACCLoopConstruct &loopConstruct) { + + const auto &beginLoopDirective = + std::get(loopConstruct.t); + const auto &loopDirective = + std::get(beginLoopDirective.t); + + if (loopDirective.v == llvm::acc::ACCD_loop) { + auto &firOpBuilder = absConv.getFirOpBuilder(); + auto currentLocation = absConv.getCurrentLocation(); + auto insertPt = firOpBuilder.saveInsertionPoint(); + llvm::ArrayRef argTy; + mlir::ValueRange range; + llvm::SmallVector operandSegmentSizes(2 /*Size=*/, + 0 /*Value=*/); + auto loopOp = + firOpBuilder.create(currentLocation, argTy, range); + loopOp.setAttr(mlir::acc::LoopOp::getOperandSegmentSizeAttr(), + firOpBuilder.getI32VectorAttr(operandSegmentSizes)); + loopOp.getRegion().push_back(new Block{}); + auto &block = loopOp.getRegion().back(); + firOpBuilder.setInsertionPointToStart(&block); + // ensure the block is well-formed. + firOpBuilder.create(currentLocation); + + // Add attribute extracted from clauses. + const auto &accClauseList = + std::get(beginLoopDirective.t); + for (const auto &clause : accClauseList.v) { + if (const auto *collapseClause{ + std::get_if(&clause.u)}) { + + const auto *expr = Fortran::semantics::GetExpr(collapseClause->v); + const auto collapseValue = Fortran::evaluate::ToInt64(*expr); + if (collapseValue.has_value()) { + loopOp.setAttr(mlir::acc::LoopOp::getCollapseAttrName(), + firOpBuilder.getI64IntegerAttr(collapseValue.value())); + } + } + } + + // Place the insertion point to the start of the first block. + firOpBuilder.setInsertionPointToStart(&block); + } }