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 @@ -75,6 +75,36 @@ standaloneConstruct.u); } +static void +genOMP(Fortran::lower::AbstractConverter &absConv, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { + const auto &blockDirective = + std::get(blockConstruct.t); + const auto ¶llelDirective = + std::get(blockDirective.t); + if (parallelDirective.v == llvm::omp::OMPD_parallel) { + auto &firOpBuilder = absConv.getFirOpBuilder(); + auto currentLocation = absConv.getCurrentLocation(); + auto insertPt = firOpBuilder.saveInsertionPoint(); + llvm::ArrayRef argTy; + mlir::ValueRange range; + llvm::SmallVector operandSegmentSizes(6 /*Size=*/, + 0 /*Value=*/); + // create and insert the operation. + auto parallelOp = firOpBuilder.create( + currentLocation, argTy, range); + parallelOp.setAttr(mlir::omp::ParallelOp::getOperandSegmentSizeAttr(), + firOpBuilder.getI32VectorAttr(operandSegmentSizes)); + parallelOp.getRegion().push_back(new Block{}); + auto &block = parallelOp.getRegion().back(); + firOpBuilder.setInsertionPointToStart(&block); + // ensure the block is well-formed. + firOpBuilder.create(currentLocation); + firOpBuilder.restoreInsertionPoint(insertPt); + } +} + void Fortran::lower::genOpenMPConstruct( Fortran::lower::AbstractConverter &absConv, Fortran::lower::pft::Evaluation &eval, @@ -92,7 +122,7 @@ TODO(); }, [&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { - TODO(); + genOMP(absConv, eval, blockConstruct); }, [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { TODO(); diff --git a/flang/unittests/Lower/OpenMPLoweringTest.cpp b/flang/unittests/Lower/OpenMPLoweringTest.cpp --- a/flang/unittests/Lower/OpenMPLoweringTest.cpp +++ b/flang/unittests/Lower/OpenMPLoweringTest.cpp @@ -71,4 +71,31 @@ EXPECT_EQ(succeeded(taskYieldOp.verify()), true); } +TEST_F(OpenMPLoweringTest, EmptyParallel) { + // Construct a dummy parse tree node for `!OMP parallel`. + struct Fortran::parser::OmpSimpleStandaloneDirective parallelDirective( + llvm::omp::Directive::OMPD_parallel); + + // Check and lower the `!OMP parallel` node to `ParallelOp` operation of + // OpenMPDialect. + EXPECT_EQ(parallelDirective.v, llvm::omp::Directive::OMPD_parallel); + auto insertPt = mlirOpBuilder->saveInsertionPoint(); + llvm::ArrayRef argTy; + mlir::ValueRange range; + llvm::SmallVector operandSegmentSizes(6 /*Size=*/, 0 /*Value=*/); + // create and insert the operation. + auto parallelOp = mlirOpBuilder->create( + mlirOpBuilder->getUnknownLoc(), argTy, range); + parallelOp.setAttr(mlir::omp::ParallelOp::getOperandSegmentSizeAttr(), + mlirOpBuilder->getI32VectorAttr(operandSegmentSizes)); + parallelOp.getRegion().push_back(new mlir::Block{}); + auto &block = parallelOp.getRegion().back(); + mlirOpBuilder->setInsertionPointToStart(&block); + // ensure the block is well-formed. + mlirOpBuilder->create( + mlirOpBuilder->getUnknownLoc()); + mlirOpBuilder->restoreInsertionPoint(insertPt); + EXPECT_EQ(succeeded(parallelOp.verify()), true); +} + // main() from gtest_main