diff --git a/flang/include/flang/Lower/PFTBuilder.h b/flang/include/flang/Lower/PFTBuilder.h index 42d6546b77553..ac87fcd7c3b9b 100644 --- a/flang/include/flang/Lower/PFTBuilder.h +++ b/flang/include/flang/Lower/PFTBuilder.h @@ -184,6 +184,11 @@ static constexpr bool isExecutableDirective{common::HasMember< A, std::tuple>}; +template +static constexpr bool isOpenMPDirective{ + common::HasMember>}; + template static constexpr bool isFunctionLike{common::HasMember< A, std::tuple>; }}); } + constexpr bool isOpenMPDirective() const { + return visit(common::visitors{[](auto &r) { + return pft::isOpenMPDirective>; + }}); + } /// Return the predicate: "This is a non-initial, non-terminal construct /// statement." For an IfConstruct, this is ElseIfStmt and ElseStmt. diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp index 2cc458cb6130d..68023610c3c50 100644 --- a/flang/lib/Lower/PFTBuilder.cpp +++ b/flang/lib/Lower/PFTBuilder.cpp @@ -1096,7 +1096,9 @@ class PFTBuilder { // The first executable statement in the subprogram is preceded by a // branch to the entry point, so it starts a new block. - if (initialEval->hasNestedEvaluations()) + // OpenMP directives can generate code around the nested evaluations. + if (initialEval->hasNestedEvaluations() && + !initialEval->isOpenMPDirective()) initialEval = &initialEval->getFirstNestedEvaluation(); else if (initialEval->isA()) initialEval = initialEval->lexicalSuccessor; diff --git a/flang/test/Lower/OpenMP/multiple-entry-points.f90 b/flang/test/Lower/OpenMP/multiple-entry-points.f90 new file mode 100644 index 0000000000000..2b8caa79eaa15 --- /dev/null +++ b/flang/test/Lower/OpenMP/multiple-entry-points.f90 @@ -0,0 +1,46 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s + +! Check the first entry point +!CHECK: func.func @_QPprocess_a +!CHECK: omp.parallel +!CHECK: omp.wsloop +!CHECK: %[[V0:[0-9]+]] = fir.load %{{[0-9]+}} : !fir.ref +!CHECK: %[[V1:[a-z_0-9]+]] = arith.constant 2.000000e+00 : f32 +!CHECK: = arith.mulf %[[V0]], %[[V1]] fastmath : f32 +!CHECK: omp.terminator +!CHECK-NOT: omp +!CHECK: return + +! Check the second entry point +!CHECK: func.func @_QPprocess_b +!CHECK: omp.parallel +!CHECK: fir.do_loop +!CHECK: %[[V3:[0-9]+]] = fir.load %[[V2:[0-9]+]]#0 : !fir.ref +!CHECK: %[[V4:[0-9]+]] = fir.load %[[V2]]#0 : !fir.ref +!CHECK: = arith.muli %[[V3]], %[[V4]] : i32 +!CHECK: omp.terminator +!CHECK-NOT: omp +!CHECK: return + +subroutine process_a(n, a) + integer, intent(in) :: n + real, intent(inout) :: a(n) + integer :: i + + !$omp parallel do + do i = 1, n + a(i) = a(i) * 2.0 + end do + !$omp end parallel do + + return + + entry process_b(n, b) + + !$omp parallel + do i = 1, n + a(i) = i * i + end do + !$omp end parallel + +end subroutine process_a