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 @@ -140,6 +140,8 @@ std::get(blockConstruct.t); const auto &blockDirective = std::get(beginBlockDirective.t); + const auto &endBlockDirective = + std::get(blockConstruct.t); auto &firOpBuilder = converter.getFirOpBuilder(); auto currentLocation = converter.getCurrentLocation(); @@ -200,6 +202,21 @@ auto masterOp = firOpBuilder.create(currentLocation, argTy); createBodyOfOp(masterOp, firOpBuilder, currentLocation); + + // Single Construct + } else if (blockDirective.v == llvm::omp::OMPD_single) { + mlir::UnitAttr nowaitAttr; + for (const auto &clause : + std::get(endBlockDirective.t).v) { + if (const auto &nowait = + std::get_if(&clause.u)) + nowaitAttr = firOpBuilder.getUnitAttr(); + // TODO: Handle allocate clause (D122302) + } + auto singleOp = firOpBuilder.create( + currentLocation, /*allocate_vars=*/ValueRange(), + /*allocators_vars=*/ValueRange(), nowaitAttr); + createBodyOfOp(singleOp, firOpBuilder, currentLocation); } } diff --git a/flang/test/Lower/OpenMP/single.f90 b/flang/test/Lower/OpenMP/single.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenMP/single.f90 @@ -0,0 +1,46 @@ +!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s --check-prefixes="FIRDialect,OMPDialect" +!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | fir-opt --cfg-conversion | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="OMPDialect" + +!=============================================================================== +! Single construct +!=============================================================================== + +!FIRDialect-LABEL: func @_QPomp_single +!FIRDialect-SAME: (%[[x:.*]]: !fir.ref {fir.bindc_name = "x"}) +subroutine omp_single(x) + integer, intent(inout) :: x + !OMPDialect: omp.parallel + !$omp parallel + !OMPDialect: omp.single + !$omp single + !FIRDialect: %[[xval:.*]] = fir.load %[[x]] : !fir.ref + !FIRDialect: %[[res:.*]] = arith.addi %[[xval]], %{{.*}} : i32 + !FIRDialect: fir.store %[[res]] to %[[x]] : !fir.ref + x = x + 12 + !OMPDialect: omp.terminator + !$omp end single + !OMPDialect: omp.terminator + !$omp end parallel +end subroutine omp_single + +!=============================================================================== +! Single construct with nowait +!=============================================================================== + +!FIRDialect-LABEL: func @_QPomp_single_nowait +!FIRDialect-SAME: (%[[x:.*]]: !fir.ref {fir.bindc_name = "x"}) +subroutine omp_single_nowait(x) + integer, intent(inout) :: x + !OMPDialect: omp.parallel + !$omp parallel + !OMPDialect: omp.single nowait + !$omp single + !FIRDialect: %[[xval:.*]] = fir.load %[[x]] : !fir.ref + !FIRDialect: %[[res:.*]] = arith.addi %[[xval]], %{{.*}} : i32 + !FIRDialect: fir.store %[[res]] to %[[x]] : !fir.ref + x = x + 12 + !OMPDialect: omp.terminator + !$omp end single nowait + !OMPDialect: omp.terminator + !$omp end parallel +end subroutine omp_single_nowait