diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h --- a/flang/include/flang/Lower/OpenMP.h +++ b/flang/include/flang/Lower/OpenMP.h @@ -5,6 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +// +// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ +// +//===----------------------------------------------------------------------===// #ifndef FORTRAN_LOWER_OPENMP_H #define FORTRAN_LOWER_OPENMP_H 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/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -5,18 +5,98 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +// +// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ +// +//===----------------------------------------------------------------------===// #include "flang/Lower/OpenMP.h" #include "flang/Lower/Bridge.h" +#include "flang/Lower/FIRBuilder.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Parser/parse-tree.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" #define TODO() llvm_unreachable("not yet implemented") +static void genOMP(Fortran::lower::AbstractConverter &absConv, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPSimpleStandaloneConstruct + &simpleStandaloneConstruct) { + const auto &directive = + std::get( + simpleStandaloneConstruct.t); + switch (directive.v) { + default: + break; + case llvm::omp::Directive::OMPD_barrier: + absConv.getFirOpBuilder().create( + absConv.getCurrentLocation()); + break; + case llvm::omp::Directive::OMPD_taskwait: + TODO(); + case llvm::omp::Directive::OMPD_taskyield: + TODO(); + case llvm::omp::Directive::OMPD_target_enter_data: + TODO(); + case llvm::omp::Directive::OMPD_target_exit_data: + TODO(); + case llvm::omp::Directive::OMPD_target_update: + TODO(); + case llvm::omp::Directive::OMPD_ordered: + TODO(); + } +} + +static void +genOMP(Fortran::lower::AbstractConverter &absConv, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPStandaloneConstruct &standaloneConstruct) { + std::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::OpenMPSimpleStandaloneConstruct + &simpleStandaloneConstruct) { + genOMP(absConv, eval, simpleStandaloneConstruct); + }, + [&](const Fortran::parser::OpenMPFlushConstruct &flushConstruct) { + TODO(); + }, + [&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) { + TODO(); + }, + [&](const Fortran::parser::OpenMPCancellationPointConstruct + &cancellationPointConstruct) { TODO(); }, + }, + standaloneConstruct.u); +} + void Fortran::lower::genOpenMPConstruct( - Fortran::lower::AbstractConverter &, Fortran::lower::pft::Evaluation &, - const Fortran::parser::OpenMPConstruct &) { - TODO(); + Fortran::lower::AbstractConverter &absConv, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPConstruct &ompConstruct) { + + std::visit( + common::visitors{ + [&](const Fortran::parser::OpenMPStandaloneConstruct + &standaloneConstruct) { + genOMP(absConv, eval, standaloneConstruct); + }, + [&](const Fortran::parser::OpenMPSectionsConstruct + §ionsConstruct) { TODO(); }, + [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { + TODO(); + }, + [&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { + TODO(); + }, + [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { + TODO(); + }, + [&](const Fortran::parser::OpenMPCriticalConstruct + &criticalConstruct) { TODO(); }, + }, + ompConstruct.u); } void Fortran::lower::genOpenMPEndLoop( diff --git a/flang/unittests/CMakeLists.txt b/flang/unittests/CMakeLists.txt --- a/flang/unittests/CMakeLists.txt +++ b/flang/unittests/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(Decimal) add_subdirectory(Evaluate) add_subdirectory(Runtime) +add_subdirectory(Lower) diff --git a/flang/unittests/Lower/CMakeLists.txt b/flang/unittests/Lower/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/flang/unittests/Lower/CMakeLists.txt @@ -0,0 +1,13 @@ +get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) + +set(LIBS + MLIRLLVMIR + ${dialect_libs} +) + +add_flang_unittest(FlangLoweringOpenMPTests + OpenMPLoweringTest.cpp +) +target_link_libraries(FlangLoweringOpenMPTests + PRIVATE + ${LIBS}) diff --git a/flang/unittests/Lower/OpenMPLoweringTest.cpp b/flang/unittests/Lower/OpenMPLoweringTest.cpp new file mode 100644 --- /dev/null +++ b/flang/unittests/Lower/OpenMPLoweringTest.cpp @@ -0,0 +1,44 @@ +//===- OpenMPLoweringTest.cpp -- OpenMPLowering unit tests ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/IR/Builders.h" +#include "flang/Parser/parse-tree.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" + +class OpenMPLoweringTest : public testing::Test { +protected: + void SetUp() override { + mlir::registerDialect(); + mlir::registerAllDialects(&ctx); + mlirOpBuilder.reset(new mlir::OpBuilder(&ctx)); + } + + void TearDown() override { mlirOpBuilder.reset(); } + + mlir::MLIRContext ctx; + std::unique_ptr mlirOpBuilder; +}; + +TEST_F(OpenMPLoweringTest, Barrier) { + // Construct a dummy parse tree node for `!OMP barrier`. + struct Fortran::parser::OmpSimpleStandaloneDirective barrierDirective( + llvm::omp::Directive::OMPD_barrier); + + // Check and lower the `!OMP barrier` node to `BarrierOp` operation of + // OpenMPDialect. + EXPECT_EQ(barrierDirective.v, llvm::omp::Directive::OMPD_barrier); + auto barrierOp = mlirOpBuilder->create( + mlirOpBuilder->getUnknownLoc()); + + EXPECT_EQ(barrierOp.getOperationName(), "omp.barrier"); + EXPECT_EQ(succeeded(barrierOp.verify()), true); +} + +// main() from gtest_main