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 @@ -84,6 +84,7 @@ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); auto insPt = firOpBuilder.saveInsertionPoint(); firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); + bool hasFirstPrivateOp = false; for (const Fortran::parser::OmpClause &clause : opClauseList.v) { if (const auto &privateClause = std::get_if(&clause.u)) { @@ -92,8 +93,11 @@ std::get_if( &clause.u)) { createPrivateVarSyms(converter, firstPrivateClause); + hasFirstPrivateOp = true; } } + if (hasFirstPrivateOp) + firOpBuilder.create(converter.getCurrentLocation()); firOpBuilder.restoreInsertionPoint(insPt); } diff --git a/flang/test/Lower/OpenMP/omp-parallel-firstprivate-clause-scalar.f90 b/flang/test/Lower/OpenMP/omp-parallel-firstprivate-clause-scalar.f90 --- a/flang/test/Lower/OpenMP/omp-parallel-firstprivate-clause-scalar.f90 +++ b/flang/test/Lower/OpenMP/omp-parallel-firstprivate-clause-scalar.f90 @@ -3,71 +3,53 @@ ! REQUIRES: shell ! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s --check-prefix=FIRDialect -!FIRDialect: func @_QPfirstprivate_complex(%[[ARG1:.*]]: !fir.ref>{{.*}}, %[[ARG2:.*]]: !fir.ref>{{.*}}) { -!FIRDialect-DAG: omp.parallel { -!FIRDialect-DAG: %[[ARG1_PVT:.*]] = fir.alloca !fir.complex<4> {bindc_name = "arg1", pinned, uniq_name = "_QFfirstprivate_complexEarg1"} -!FIRDialect-DAG: %[[ARG1_VAL:.*]] = fir.load %arg0 : !fir.ref> -!FIRDialect-DAG: fir.store %[[ARG1_VAL]] to %[[ARG1_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG2_PVT:.*]] = fir.alloca !fir.complex<8> {bindc_name = "arg2", pinned, uniq_name = "_QFfirstprivate_complexEarg2"} -!FIRDialect-DAG: %[[ARG2_VAL:.*]] = fir.load %[[ARG2]] : !fir.ref> -!FIRDialect-DAG: fir.store %[[ARG2_VAL]] to %[[ARG2_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[LIST_IO:.*]] = fir.call @_FortranAioBeginExternalListOutput -!FIRDialect-DAG: %[[ARG1_PVT_VAL:.*]] = fir.load %[[ARG1_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG1_PVT_REAL:.*]] = fir.extract_value %[[ARG1_PVT_VAL]], [0 : index] : (!fir.complex<4>) -> f32 -!FIRDialect-DAG: %[[ARG1_PVT_IMAG:.*]] = fir.extract_value %[[ARG1_PVT_VAL]], [1 : index] : (!fir.complex<4>) -> f32 -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputComplex32(%[[LIST_IO]], %[[ARG1_PVT_REAL]], %[[ARG1_PVT_IMAG]]) : (!fir.ref, f32, f32) -> i1 -!FIRDialect-DAG: %[[ARG2_PVT_VAL:.*]] = fir.load %[[ARG2_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG2_PVT_REAL:.*]] = fir.extract_value %[[ARG2_PVT_VAL]], [0 : index] : (!fir.complex<8>) -> f64 -!FIRDialect-DAG: %[[ARG2_PVT_IMAG:.*]] = fir.extract_value %[[ARG2_PVT_VAL]], [1 : index] : (!fir.complex<8>) -> f64 -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputComplex64(%[[LIST_IO]], %[[ARG2_PVT_REAL]], %[[ARG2_PVT_IMAG]]) : (!fir.ref, f64, f64) -> i1 -!FIRDialect-DAG: omp.terminator -!FIRDialect-DAG: } +!FIRDialect-DAG: func @_QPfirstprivate_complex(%[[ARG1:.*]]: !fir.ref>{{.*}}, %[[ARG2:.*]]: !fir.ref>{{.*}}) { +!FIRDialect: omp.parallel { +!FIRDialect: %[[ARG1_PVT:.*]] = fir.alloca !fir.complex<4> {bindc_name = "arg1", pinned, uniq_name = "_QFfirstprivate_complexEarg1"} +!FIRDialect: %[[ARG1_VAL:.*]] = fir.load %[[ARG1]] : !fir.ref> +!FIRDialect: fir.store %[[ARG1_VAL]] to %[[ARG1_PVT]] : !fir.ref> +!FIRDialect: %[[ARG2_PVT:.*]] = fir.alloca !fir.complex<8> {bindc_name = "arg2", pinned, uniq_name = "_QFfirstprivate_complexEarg2"} +!FIRDialect: %[[ARG2_VAL:.*]] = fir.load %[[ARG2]] : !fir.ref> +!FIRDialect: fir.store %[[ARG2_VAL]] to %[[ARG2_PVT]] : !fir.ref> +!FIRDialect: omp.barrier +!FIRDialect: fir.call @_QPfoo(%[[ARG1_PVT]], %[[ARG2_PVT]]) : (!fir.ref>, !fir.ref>) -> () +!FIRDialect: omp.terminator +!FIRDialect: } subroutine firstprivate_complex(arg1, arg2) complex(4) :: arg1 complex(8) :: arg2 !$OMP PARALLEL FIRSTPRIVATE(arg1, arg2) - print *, arg1, arg2 + call foo(arg1, arg2) !$OMP END PARALLEL end subroutine -!FIRDialect: func @_QPfirstprivate_integer(%[[ARG1:.*]]: !fir.ref{{.*}}, %[[ARG2:.*]]: !fir.ref{{.*}}, %[[ARG3:.*]]: !fir.ref{{.*}}, %[[ARG4:.*]]: !fir.ref{{.*}}, %[[ARG5:.*]]: !fir.ref{{.*}}, %[[ARG6:.*]]: !fir.ref{{.*}}) { -!FIRDialect-DAG: omp.parallel { -!FIRDialect-DAG: %[[ARG1_PVT:.*]] = fir.alloca i32 {bindc_name = "arg1", pinned, uniq_name = "_QFfirstprivate_integerEarg1"} -!FIRDialect-DAG: %[[ARG1_VAL:.*]] = fir.load %[[ARG1]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG1_VAL]] to %[[ARG1_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG2_PVT:.*]] = fir.alloca i8 {bindc_name = "arg2", pinned, uniq_name = "_QFfirstprivate_integerEarg2"} -!FIRDialect-DAG: %[[ARG2_VAL:.*]] = fir.load %[[ARG2]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG2_VAL]] to %[[ARG2_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG3_PVT:.*]] = fir.alloca i16 {bindc_name = "arg3", pinned, uniq_name = "_QFfirstprivate_integerEarg3"} -!FIRDialect-DAG: %[[ARG3_VAL:.*]] = fir.load %[[ARG3]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG3_VAL]] to %[[ARG3_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG4_PVT:.*]] = fir.alloca i32 {bindc_name = "arg4", pinned, uniq_name = "_QFfirstprivate_integerEarg4"} -!FIRDialect-DAG: %[[ARG4_VAL:.*]] = fir.load %[[ARG4]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG4_VAL]] to %[[ARG4_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG5_PVT:.*]] = fir.alloca i64 {bindc_name = "arg5", pinned, uniq_name = "_QFfirstprivate_integerEarg5"} -!FIRDialect-DAG: %[[ARG5_VAL:.*]] = fir.load %[[ARG5]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG5_VAL]] to %[[ARG5_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG6_PVT:.*]] = fir.alloca i128 {bindc_name = "arg6", pinned, uniq_name = "_QFfirstprivate_integerEarg6"} -!FIRDialect-DAG: %[[ARG6_VAL:.*]] = fir.load %[[ARG6]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG6_VAL]] to %[[ARG6_PVT]] : !fir.ref -!FIRDialect-DAG: %[[LIST_IO:.*]] = fir.call @_FortranAioBeginExternalListOutput -!FIRDialect-DAG: %[[ARG1_PVT_VAL:.*]] = fir.load %[[ARG1_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputInteger32(%[[LIST_IO]], %[[ARG1_PVT_VAL]]) : (!fir.ref, i32) -> i1 -!FIRDialect-DAG: %[[ARG2_PVT_VAL:.*]] = fir.load %[[ARG2_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputInteger8(%[[LIST_IO]], %[[ARG2_PVT_VAL]]) : (!fir.ref, i8) -> i1 -!FIRDialect-DAG: %[[ARG3_PVT_VAL:.*]] = fir.load %[[ARG3_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputInteger16(%[[LIST_IO]], %[[ARG3_PVT_VAL]]) : (!fir.ref, i16) -> i1 -!FIRDialect-DAG: %[[ARG4_PVT_VAL:.*]] = fir.load %[[ARG4_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputInteger32(%[[LIST_IO]], %[[ARG4_PVT_VAL]]) : (!fir.ref, i32) -> i1 -!FIRDialect-DAG: %[[ARG5_PVT_VAL:.*]] = fir.load %[[ARG5_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputInteger64(%[[LIST_IO]], %[[ARG5_PVT_VAL]]) : (!fir.ref, i64) -> i1 -!FIRDialect-DAG: %[[ARG6_PVT_VAL:.*]] = fir.load %[[ARG6_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputInteger128(%[[LIST_IO]], %[[ARG6_PVT_VAL]]) : (!fir.ref, i128) -> i1 -!FIRDialect-DAG: omp.terminator -!FIRDialect-DAG: } +!FIRDialect-DAG: func @_QPfirstprivate_integer(%[[ARG1:.*]]: !fir.ref{{.*}}, %[[ARG2:.*]]: !fir.ref{{.*}}, %[[ARG3:.*]]: !fir.ref{{.*}}, %[[ARG4:.*]]: !fir.ref{{.*}}, %[[ARG5:.*]]: !fir.ref{{.*}}, %[[ARG6:.*]]: !fir.ref{{.*}}) { +!FIRDialect: omp.parallel { +!FIRDialect: %[[ARG1_PVT:.*]] = fir.alloca i32 {bindc_name = "arg1", pinned, uniq_name = "_QFfirstprivate_integerEarg1"} +!FIRDialect: %[[ARG1_VAL:.*]] = fir.load %[[ARG1]] : !fir.ref +!FIRDialect: fir.store %[[ARG1_VAL]] to %[[ARG1_PVT]] : !fir.ref +!FIRDialect: %[[ARG2_PVT:.*]] = fir.alloca i8 {bindc_name = "arg2", pinned, uniq_name = "_QFfirstprivate_integerEarg2"} +!FIRDialect: %[[ARG2_VAL:.*]] = fir.load %[[ARG2]] : !fir.ref +!FIRDialect: fir.store %[[ARG2_VAL]] to %[[ARG2_PVT]] : !fir.ref +!FIRDialect: %[[ARG3_PVT:.*]] = fir.alloca i16 {bindc_name = "arg3", pinned, uniq_name = "_QFfirstprivate_integerEarg3"} +!FIRDialect: %[[ARG3_VAL:.*]] = fir.load %[[ARG3]] : !fir.ref +!FIRDialect: fir.store %[[ARG3_VAL]] to %[[ARG3_PVT]] : !fir.ref +!FIRDialect: %[[ARG4_PVT:.*]] = fir.alloca i32 {bindc_name = "arg4", pinned, uniq_name = "_QFfirstprivate_integerEarg4"} +!FIRDialect: %[[ARG4_VAL:.*]] = fir.load %[[ARG4]] : !fir.ref +!FIRDialect: fir.store %[[ARG4_VAL]] to %[[ARG4_PVT]] : !fir.ref +!FIRDialect: %[[ARG5_PVT:.*]] = fir.alloca i64 {bindc_name = "arg5", pinned, uniq_name = "_QFfirstprivate_integerEarg5"} +!FIRDialect: %[[ARG5_VAL:.*]] = fir.load %[[ARG5]] : !fir.ref +!FIRDialect: fir.store %[[ARG5_VAL]] to %[[ARG5_PVT]] : !fir.ref +!FIRDialect: %[[ARG6_PVT:.*]] = fir.alloca i128 {bindc_name = "arg6", pinned, uniq_name = "_QFfirstprivate_integerEarg6"} +!FIRDialect: %[[ARG6_VAL:.*]] = fir.load %[[ARG6]] : !fir.ref +!FIRDialect: fir.store %[[ARG6_VAL]] to %[[ARG6_PVT]] : !fir.ref +!FIRDialect: omp.barrier +!FIRDialect: fir.call @_QPbar(%[[ARG1_PVT]], %[[ARG2_PVT]], %[[ARG3_PVT]], %[[ARG4_PVT]], %[[ARG5_PVT]], %[[ARG6_PVT]]) : (!fir.ref, !fir.ref, !fir.ref, !fir.ref, !fir.ref, !fir.ref) -> () +!FIRDialect: omp.terminator +!FIRDialect: } subroutine firstprivate_integer(arg1, arg2, arg3, arg4, arg5, arg6) integer :: arg1 @@ -78,46 +60,32 @@ integer(kind=16) :: arg6 !$OMP PARALLEL FIRSTPRIVATE(arg1, arg2, arg3, arg4, arg5, arg6) - print *, arg1, arg2, arg3, arg4, arg5, arg6 + call bar(arg1, arg2, arg3, arg4, arg5, arg6) !$OMP END PARALLEL end subroutine -!FIRDialect: func @_QPfirstprivate_logical(%[[ARG1:.*]]: !fir.ref>{{.*}}, %[[ARG2:.*]]: !fir.ref>{{.*}}, %[[ARG3:.*]]: !fir.ref>{{.*}}, %[[ARG4:.*]]: !fir.ref>{{.*}}, %[[ARG5:.*]]: !fir.ref>{{.*}}) { -!FIRDialect-DAG: omp.parallel { -!FIRDialect-DAG: %[[ARG1_PVT:.*]] = fir.alloca !fir.logical<4> {bindc_name = "arg1", pinned, uniq_name = "_QFfirstprivate_logicalEarg1"} -!FIRDialect-DAG: %[[ARG1_VAL:.*]] = fir.load %[[ARG1]] : !fir.ref> -!FIRDialect-DAG: fir.store %[[ARG1_VAL]] to %[[ARG1_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG2_PVT:.*]] = fir.alloca !fir.logical<1> {bindc_name = "arg2", pinned, uniq_name = "_QFfirstprivate_logicalEarg2"} -!FIRDialect-DAG: %[[ARG2_VAL:.*]] = fir.load %[[ARG2]] : !fir.ref> -!FIRDialect-DAG: fir.store %[[ARG2_VAL]] to %[[ARG2_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG3_PVT:.*]] = fir.alloca !fir.logical<2> {bindc_name = "arg3", pinned, uniq_name = "_QFfirstprivate_logicalEarg3"} -!FIRDialect-DAG: %[[ARG3_VAL:.*]] = fir.load %[[ARG3]] : !fir.ref> -!FIRDialect-DAG: fir.store %[[ARG3_VAL]] to %[[ARG3_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG4_PVT:.*]] = fir.alloca !fir.logical<4> {bindc_name = "arg4", pinned, uniq_name = "_QFfirstprivate_logicalEarg4"} -!FIRDialect-DAG: %[[ARG4_VAL:.*]] = fir.load %[[ARG4]] : !fir.ref> -!FIRDialect-DAG: fir.store %[[ARG4_VAL]] to %[[ARG4_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG5_PVT:.*]] = fir.alloca !fir.logical<8> {bindc_name = "arg5", pinned, uniq_name = "_QFfirstprivate_logicalEarg5"} -!FIRDialect-DAG: %[[ARG5_VAL:.*]] = fir.load %[[ARG5]] : !fir.ref> -!FIRDialect-DAG: fir.store %[[ARG5_VAL]] to %[[ARG5_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[LIST_IO:.*]] = fir.call @_FortranAioBeginExternalListOutput -!FIRDialect-DAG: %[[ARG1_PVT_VAL:.*]] = fir.load %[[ARG1_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG1_PVT_CVT:.*]] = fir.convert %[[ARG1_PVT_VAL]] : (!fir.logical<4>) -> i1 -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputLogical(%[[LIST_IO]], %[[ARG1_PVT_CVT]]) : (!fir.ref, i1) -> i1 -!FIRDialect-DAG: %[[ARG2_PVT_VAL:.*]] = fir.load %[[ARG2_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG2_PVT_CVT:.*]] = fir.convert %[[ARG2_PVT_VAL]] : (!fir.logical<1>) -> i1 -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputLogical(%[[LIST_IO]], %[[ARG2_PVT_CVT]]) : (!fir.ref, i1) -> i1 -!FIRDialect-DAG: %[[ARG3_PVT_VAL:.*]] = fir.load %[[ARG3_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG3_PVT_CVT:.*]] = fir.convert %[[ARG3_PVT_VAL]] : (!fir.logical<2>) -> i1 -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputLogical(%[[LIST_IO]], %[[ARG3_PVT_CVT]]) : (!fir.ref, i1) -> i1 -!FIRDialect-DAG: %[[ARG4_PVT_VAL:.*]] = fir.load %[[ARG4_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG4_PVT_CVT:.*]] = fir.convert %[[ARG4_PVT_VAL]] : (!fir.logical<4>) -> i1 -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputLogical(%[[LIST_IO]], %[[ARG4_PVT_CVT]]) : (!fir.ref, i1) -> i1 -!FIRDialect-DAG: %[[ARG5_PVT_VAL:.*]] = fir.load %[[ARG5_PVT]] : !fir.ref> -!FIRDialect-DAG: %[[ARG5_PVT_CVT:.*]] = fir.convert %[[ARG5_PVT_VAL]] : (!fir.logical<8>) -> i1 -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputLogical(%[[LIST_IO]], %[[ARG5_PVT_CVT]]) : (!fir.ref, i1) -> i1 -!FIRDialect-DAG: omp.terminator -!FIRDialect-DAG: } +!FIRDialect-DAG: func @_QPfirstprivate_logical(%[[ARG1:.*]]: !fir.ref>{{.*}}, %[[ARG2:.*]]: !fir.ref>{{.*}}, %[[ARG3:.*]]: !fir.ref>{{.*}}, %[[ARG4:.*]]: !fir.ref>{{.*}}, %[[ARG5:.*]]: !fir.ref>{{.*}}) { +!FIRDialect: omp.parallel { +!FIRDialect: %[[ARG1_PVT:.*]] = fir.alloca !fir.logical<4> {bindc_name = "arg1", pinned, uniq_name = "_QFfirstprivate_logicalEarg1"} +!FIRDialect: %[[ARG1_VAL:.*]] = fir.load %[[ARG1]] : !fir.ref> +!FIRDialect: fir.store %[[ARG1_VAL]] to %[[ARG1_PVT]] : !fir.ref> +!FIRDialect: %[[ARG2_PVT:.*]] = fir.alloca !fir.logical<1> {bindc_name = "arg2", pinned, uniq_name = "_QFfirstprivate_logicalEarg2"} +!FIRDialect: %[[ARG2_VAL:.*]] = fir.load %[[ARG2]] : !fir.ref> +!FIRDialect: fir.store %[[ARG2_VAL]] to %[[ARG2_PVT]] : !fir.ref> +!FIRDialect: %[[ARG3_PVT:.*]] = fir.alloca !fir.logical<2> {bindc_name = "arg3", pinned, uniq_name = "_QFfirstprivate_logicalEarg3"} +!FIRDialect: %[[ARG3_VAL:.*]] = fir.load %[[ARG3]] : !fir.ref> +!FIRDialect: fir.store %[[ARG3_VAL]] to %[[ARG3_PVT]] : !fir.ref> +!FIRDialect: %[[ARG4_PVT:.*]] = fir.alloca !fir.logical<4> {bindc_name = "arg4", pinned, uniq_name = "_QFfirstprivate_logicalEarg4"} +!FIRDialect: %[[ARG4_VAL:.*]] = fir.load %[[ARG4]] : !fir.ref> +!FIRDialect: fir.store %[[ARG4_VAL]] to %[[ARG4_PVT]] : !fir.ref> +!FIRDialect: %[[ARG5_PVT:.*]] = fir.alloca !fir.logical<8> {bindc_name = "arg5", pinned, uniq_name = "_QFfirstprivate_logicalEarg5"} +!FIRDialect: %[[ARG5_VAL:.*]] = fir.load %[[ARG5]] : !fir.ref> +!FIRDialect: fir.store %[[ARG5_VAL]] to %[[ARG5_PVT]] : !fir.ref> +!FIRDialect: omp.barrier +!FIRDialect: fir.call @_QPbaz(%[[ARG1_PVT]], %[[ARG2_PVT]], %[[ARG3_PVT]], %[[ARG4_PVT]], %[[ARG5_PVT]]) : (!fir.ref>, !fir.ref>, !fir.ref>, !fir.ref>, !fir.ref>) -> () +!FIRDialect: omp.terminator +!FIRDialect: } subroutine firstprivate_logical(arg1, arg2, arg3, arg4, arg5) logical :: arg1 @@ -127,49 +95,35 @@ logical(kind=8) :: arg5 !$OMP PARALLEL FIRSTPRIVATE(arg1, arg2, arg3, arg4, arg5) - print *, arg1, arg2, arg3, arg4, arg5 + call baz(arg1, arg2, arg3, arg4, arg5) !$OMP END PARALLEL end subroutine !FIRDialect-DAG: func @_QPfirstprivate_real(%[[ARG1:.*]]: !fir.ref{{.*}}, %[[ARG2:.*]]: !fir.ref{{.*}}, %[[ARG3:.*]]: !fir.ref{{.*}}, %[[ARG4:.*]]: !fir.ref{{.*}}, %[[ARG5:.*]]: !fir.ref{{.*}}, %[[ARG6:.*]]: !fir.ref{{.*}}) { -!FIRDialect-DAG: omp.parallel { -!FIRDialect-DAG: %[[ARG1_PVT:.*]] = fir.alloca f32 {bindc_name = "arg1", pinned, uniq_name = "_QFfirstprivate_realEarg1"} -!FIRDialect-DAG: %[[ARG1_VAL:.*]] = fir.load %[[ARG1]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG1_VAL]] to %[[ARG1_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG2_PVT:.*]] = fir.alloca f16 {bindc_name = "arg2", pinned, uniq_name = "_QFfirstprivate_realEarg2"} -!FIRDialect-DAG: %[[ARG2_VAL:.*]] = fir.load %[[ARG2]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG2_VAL]] to %[[ARG2_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG3_PVT:.*]] = fir.alloca f32 {bindc_name = "arg3", pinned, uniq_name = "_QFfirstprivate_realEarg3"} -!FIRDialect-DAG: %[[ARG3_VAL:.*]] = fir.load %[[ARG3]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG3_VAL]] to %[[ARG3_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG4_PVT:.*]] = fir.alloca f64 {bindc_name = "arg4", pinned, uniq_name = "_QFfirstprivate_realEarg4"} -!FIRDialect-DAG: %[[ARG4_VAL:.*]] = fir.load %[[ARG4]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG4_VAL]] to %[[ARG4_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG5_PVT:.*]] = fir.alloca f80 {bindc_name = "arg5", pinned, uniq_name = "_QFfirstprivate_realEarg5"} -!FIRDialect-DAG: %[[ARG5_VAL:.*]] = fir.load %[[ARG5]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG5_VAL]] to %[[ARG5_PVT]] : !fir.ref -!FIRDialect-DAG: %[[ARG6_PVT:.*]] = fir.alloca f128 {bindc_name = "arg6", pinned, uniq_name = "_QFfirstprivate_realEarg6"} -!FIRDialect-DAG: %[[ARG6_VAL:.*]] = fir.load %[[ARG6]] : !fir.ref -!FIRDialect-DAG: fir.store %[[ARG6_VAL]] to %[[ARG6_PVT]] : !fir.ref -!FIRDialect-DAG: %[[LIST_IO:.*]] = fir.call @_FortranAioBeginExternalListOutput -!FIRDialect-DAG: %[[ARG1_PVT_VAL:.*]] = fir.load %[[ARG1_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputReal32(%[[LIST_IO]], %[[ARG1_PVT_VAL]]) : (!fir.ref, f32) -> i1 -!FIRDialect-DAG: %[[ARG2_PVT_VAL:.*]] = fir.embox %[[ARG2_PVT]] : (!fir.ref) -> !fir.box -!FIRDialect-DAG: %[[ARG2_PVT_CVT:.*]] = fir.convert %[[ARG2_PVT_VAL]] : (!fir.box) -> !fir.box -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputDescriptor(%[[LIST_IO]], %[[ARG2_PVT_CVT]]) : (!fir.ref, !fir.box) -> i1 -!FIRDialect-DAG: %[[ARG3_PVT_VAL:.*]] = fir.load %[[ARG3_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputReal32(%[[LIST_IO]], %[[ARG3_PVT_VAL]]) : (!fir.ref, f32) -> i1 -!FIRDialect-DAG: %[[ARG4_PVT_VAL:.*]] = fir.load %[[ARG4_PVT]] : !fir.ref -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputReal64(%[[LIST_IO]], %[[ARG4_PVT_VAL]]) : (!fir.ref, f64) -> i1 -!FIRDialect-DAG: %[[ARG5_PVT_VAL:.*]] = fir.embox %[[ARG5_PVT]] : (!fir.ref) -> !fir.box -!FIRDialect-DAG: %[[ARG5_PVT_CVT:.*]] = fir.convert %[[ARG5_PVT_VAL]] : (!fir.box) -> !fir.box -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputDescriptor(%[[LIST_IO]], %[[ARG5_PVT_CVT]]) : (!fir.ref, !fir.box) -> i1 -!FIRDialect-DAG: %[[ARG6_PVT_VAL:.*]] = fir.embox %[[ARG6_PVT]] : (!fir.ref) -> !fir.box -!FIRDialect-DAG: %[[ARG6_PVT_CVT:.*]] = fir.convert %[[ARG6_PVT_VAL]] : (!fir.box) -> !fir.box -!FIRDialect-DAG: %{{.*}} = fir.call @_FortranAioOutputDescriptor(%[[LIST_IO]], %[[ARG6_PVT_CVT]]) : (!fir.ref, !fir.box) -> i1 -!FIRDialect-DAG: omp.terminator -!FIRDialect-DAG: } +!FIRDialect: omp.parallel { +!FIRDialect: %[[ARG1_PVT:.*]] = fir.alloca f32 {bindc_name = "arg1", pinned, uniq_name = "_QFfirstprivate_realEarg1"} +!FIRDialect: %[[ARG1_VAL:.*]] = fir.load %[[ARG1]] : !fir.ref +!FIRDialect: fir.store %[[ARG1_VAL]] to %[[ARG1_PVT]] : !fir.ref +!FIRDialect: %[[ARG2_PVT:.*]] = fir.alloca f16 {bindc_name = "arg2", pinned, uniq_name = "_QFfirstprivate_realEarg2"} +!FIRDialect: %[[ARG2_VAL:.*]] = fir.load %[[ARG2]] : !fir.ref +!FIRDialect: fir.store %[[ARG2_VAL]] to %[[ARG2_PVT]] : !fir.ref +!FIRDialect: %[[ARG3_PVT:.*]] = fir.alloca f32 {bindc_name = "arg3", pinned, uniq_name = "_QFfirstprivate_realEarg3"} +!FIRDialect: %[[ARG3_VAL:.*]] = fir.load %[[ARG3]] : !fir.ref +!FIRDialect: fir.store %[[ARG3_VAL]] to %[[ARG3_PVT]] : !fir.ref +!FIRDialect: %[[ARG4_PVT:.*]] = fir.alloca f64 {bindc_name = "arg4", pinned, uniq_name = "_QFfirstprivate_realEarg4"} +!FIRDialect: %[[ARG4_VAL:.*]] = fir.load %[[ARG4]] : !fir.ref +!FIRDialect: fir.store %[[ARG4_VAL]] to %[[ARG4_PVT]] : !fir.ref +!FIRDialect: %[[ARG5_PVT:.*]] = fir.alloca f80 {bindc_name = "arg5", pinned, uniq_name = "_QFfirstprivate_realEarg5"} +!FIRDialect: %[[ARG5_VAL:.*]] = fir.load %[[ARG5]] : !fir.ref +!FIRDialect: fir.store %[[ARG5_VAL]] to %[[ARG5_PVT]] : !fir.ref +!FIRDialect: %[[ARG6_PVT:.*]] = fir.alloca f128 {bindc_name = "arg6", pinned, uniq_name = "_QFfirstprivate_realEarg6"} +!FIRDialect: %[[ARG6_VAL:.*]] = fir.load %[[ARG6]] : !fir.ref +!FIRDialect: fir.store %[[ARG6_VAL]] to %[[ARG6_PVT]] : !fir.ref +!FIRDialect: omp.barrier +!FIRDialect: fir.call @_QPqux(%[[ARG1_PVT]], %[[ARG2_PVT]], %[[ARG3_PVT]], %[[ARG4_PVT]], %[[ARG5_PVT]], %[[ARG6_PVT]]) : (!fir.ref, !fir.ref, !fir.ref, !fir.ref, !fir.ref, !fir.ref) -> () +!FIRDialect: omp.terminator +!FIRDialect: } subroutine firstprivate_real(arg1, arg2, arg3, arg4, arg5, arg6) real :: arg1 @@ -180,7 +134,32 @@ real(kind=16) :: arg6 !$OMP PARALLEL FIRSTPRIVATE(arg1, arg2, arg3, arg4, arg5, arg6) - print *, arg1, arg2, arg3, arg4, arg5, arg6 + call qux(arg1, arg2, arg3, arg4, arg5, arg6) !$OMP END PARALLEL end subroutine + +!FIRDialect-LABEL: func.func @_QPmultiple_firstprivate( +!FIRDialect-SAME: %[[A_ADDR:.*]]: !fir.ref {fir.bindc_name = "a"}, +!FIRDialect-SAME: %[[B_ADDR:.*]]: !fir.ref {fir.bindc_name = "b"}) { +!FIRDialect: omp.parallel { +!FIRDialect: %[[A_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFmultiple_firstprivateEa"} +!FIRDialect: %[[A:.*]] = fir.load %[[A_ADDR]] : !fir.ref +!FIRDialect: fir.store %[[A]] to %[[A_PRIV_ADDR]] : !fir.ref +!FIRDialect: %[[B_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "b", pinned, uniq_name = "_QFmultiple_firstprivateEb"} +!FIRDialect: %[[B:.*]] = fir.load %[[B_ADDR]] : !fir.ref +!FIRDialect: fir.store %[[B]] to %[[B_PRIV_ADDR]] : !fir.ref +!FIRDialect: omp.barrier +!FIRDialect-NOT: omp.barrier +!FIRDialect: fir.call @_QPquux(%[[A_PRIV_ADDR]], %[[B_PRIV_ADDR]]) : (!fir.ref, !fir.ref) -> () +!FIRDialect: omp.terminator +!FIRDialect: } +!FIRDialect: return +!FIRDialect: } + +subroutine multiple_firstprivate(a, b) + integer :: a, b +!$OMP PARALLEL FIRSTPRIVATE(a) FIRSTPRIVATE(b) + call quux(a, b) +!$OMP END PARALLEL +end subroutine multiple_firstprivate diff --git a/flang/test/Lower/OpenMP/omp-parallel-wsloop.f90 b/flang/test/Lower/OpenMP/omp-parallel-wsloop.f90 --- a/flang/test/Lower/OpenMP/omp-parallel-wsloop.f90 +++ b/flang/test/Lower/OpenMP/omp-parallel-wsloop.f90 @@ -71,6 +71,11 @@ !$OMP END PARALLEL DO end subroutine +!=============================================================================== +! Checking for the following construct: +! !$omp parallel do private(...) firstprivate(...) +!=============================================================================== + ! CHECK-LABEL: func @_QPparallel_do_with_privatisation_clauses ! CHECK-SAME: %[[COND_REF:.*]]: !fir.ref> {fir.bindc_name = "cond"}, %[[NT_REF:.*]]: !fir.ref {fir.bindc_name = "nt"} subroutine parallel_do_with_privatisation_clauses(cond,nt) @@ -82,6 +87,7 @@ ! CHECK: %[[PRIVATE_NT_REF:.*]] = fir.alloca i32 {bindc_name = "nt", pinned, uniq_name = "_QFparallel_do_with_privatisation_clausesEnt"} ! CHECK: %[[NT_VAL:.*]] = fir.load %[[NT_REF]] : !fir.ref ! CHECK: fir.store %[[NT_VAL]] to %[[PRIVATE_NT_REF]] : !fir.ref + ! CHECK: omp.barrier ! CHECK: %[[WS_LB:.*]] = arith.constant 1 : i32 ! CHECK: %[[WS_UB:.*]] = arith.constant 9 : i32 ! CHECK: %[[WS_STEP:.*]] = arith.constant 1 : i32 @@ -102,3 +108,178 @@ ! CHECK: omp.terminator !$OMP END PARALLEL DO end subroutine + +!=============================================================================== +! Checking for the following construct +! !$omp parallel private(...) firstprivate(...) +! !$omp do +!=============================================================================== + +subroutine parallel_private_do(cond,nt) +logical :: cond + integer :: nt + integer :: i + !$OMP PARALLEL PRIVATE(cond) FIRSTPRIVATE(nt) + !$OMP DO + do i=1, 9 + call foo(i, cond, nt) + end do + !$OMP END DO + !$OMP END PARALLEL +end subroutine parallel_private_do + +! CHECK-LABEL: func.func @_QPparallel_private_do( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref> {fir.bindc_name = "cond"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "nt"}) { +! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFparallel_private_doEi"} +! CHECK: omp.parallel { +! CHECK: %[[I_PRIV:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[COND_ADDR:.*]] = fir.alloca !fir.logical<4> {bindc_name = "cond", pinned, uniq_name = "_QFparallel_private_doEcond"} +! CHECK: %[[NT_ADDR:.*]] = fir.alloca i32 {bindc_name = "nt", pinned, uniq_name = "_QFparallel_private_doEnt"} +! CHECK: %[[NT:.*]] = fir.load %[[VAL_1]] : !fir.ref +! CHECK: fir.store %[[NT]] to %[[NT_ADDR]] : !fir.ref +! CHECK: omp.barrier +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 9 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[I]] to %[[I_PRIV]] : !fir.ref +! CHECK: fir.call @_QPfoo(%[[I_PRIV]], %[[COND_ADDR]], %[[NT_ADDR]]) : (!fir.ref, !fir.ref>, !fir.ref) -> () +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +!=============================================================================== +! Checking for the following construct - multiple firstprivate clauses must emit +! only one barrier +! !$omp parallel +! !$omp do firstprivate(...) firstprivate(...) +!=============================================================================== + +subroutine omp_parallel_multiple_firstprivate_do(a, b) + integer::a, b + !$OMP PARALLEL FIRSTPRIVATE(a) FIRSTPRIVATE(b) + !$OMP DO + do i=1, 10 + call bar(i, a) + end do + !$OMP END DO + !$OMP END PARALLEL +end subroutine omp_parallel_multiple_firstprivate_do + +! CHECK-LABEL: func.func @_QPomp_parallel_multiple_firstprivate_do( +! CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_parallel_multiple_firstprivate_doEi"} +! CHECK: omp.parallel { +! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[A_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFomp_parallel_multiple_firstprivate_doEa"} +! CHECK: %[[A:.*]] = fir.load %[[A_ADDR]] : !fir.ref +! CHECK: fir.store %[[A]] to %[[A_PRIV_ADDR]] : !fir.ref +! CHECK: %[[B_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "b", pinned, uniq_name = "_QFomp_parallel_multiple_firstprivate_doEb"} +! CHECK: %[[B:.*]] = fir.load %[[B_ADDR]] : !fir.ref +! CHECK: fir.store %[[B]] to %[[B_PRIV_ADDR]] : !fir.ref +! CHECK: omp.barrier +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref +! CHECK: fir.call @_QPbar(%[[I_PRIV_ADDR]], %[[A_PRIV_ADDR]]) : (!fir.ref, !fir.ref) -> () +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +!=============================================================================== +! Checking for the following construct +! !$omp parallel +! !$omp do private(...) firstprivate(...) +!=============================================================================== + +subroutine parallel_do_private(cond,nt) +logical :: cond + integer :: nt + integer :: i + !$OMP PARALLEL + !$OMP DO PRIVATE(cond) FIRSTPRIVATE(nt) + do i=1, 9 + call foo(i, cond, nt) + end do + !$OMP END DO + !$OMP END PARALLEL +end subroutine parallel_do_private + +! CHECK-LABEL: func.func @_QPparallel_do_private( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref> {fir.bindc_name = "cond"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "nt"}) { +! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFparallel_do_privateEi"} +! CHECK: omp.parallel { +! CHECK: %[[COND_ADDR:.*]] = fir.alloca !fir.logical<4> {bindc_name = "cond", pinned, uniq_name = "_QFparallel_do_privateEcond"} +! CHECK: %[[NT_ADDR:.*]] = fir.alloca i32 {bindc_name = "nt", pinned, uniq_name = "_QFparallel_do_privateEnt"} +! CHECK: %[[NT:.*]] = fir.load %[[VAL_1]] : !fir.ref +! CHECK: fir.store %[[NT]] to %[[NT_ADDR]] : !fir.ref +! CHECK: omp.barrier +! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 9 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref +! CHECK: fir.call @_QPfoo(%[[I_PRIV_ADDR]], %[[COND_ADDR]], %[[NT_ADDR]]) : (!fir.ref, !fir.ref>, !fir.ref) -> () +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +!=============================================================================== +! Checking for the following construct - multiple firstprivate clauses must emit +! only one barrier +! !$omp parallel +! !$omp do firstprivate(...) firstprivate(...) +!=============================================================================== + +subroutine omp_parallel_do_multiple_firstprivate(a, b) + integer::a, b + !$OMP PARALLEL + !$OMP DO FIRSTPRIVATE(a) FIRSTPRIVATE(b) + do i=1, 10 + call bar(i, a) + end do + !$OMP END DO + !$OMP END PARALLEL +end subroutine omp_parallel_do_multiple_firstprivate + +! CHECK-LABEL: func.func @_QPomp_parallel_do_multiple_firstprivate( +! CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref {fir.bindc_name = "a"}, +! CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_parallel_do_multiple_firstprivateEi"} +! CHECK: omp.parallel { +! CHECK: %[[A_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFomp_parallel_do_multiple_firstprivateEa"} +! CHECK: %[[A:.*]] = fir.load %[[A_ADDR]] : !fir.ref +! CHECK: fir.store %[[A]] to %[[A_PRIV_ADDR]] : !fir.ref +! CHECK: %[[B_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "b", pinned, uniq_name = "_QFomp_parallel_do_multiple_firstprivateEb"} +! CHECK: %[[B:.*]] = fir.load %[[B_ADDR]] : !fir.ref +! CHECK: fir.store %[[B]] to %[[B_PRIV_ADDR]] : !fir.ref +! CHECK: omp.barrier +! CHECK-NOT: omp.barrier +! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref +! CHECK: fir.call @_QPbar(%[[I_PRIV_ADDR]], %[[A_PRIV_ADDR]]) : (!fir.ref, !fir.ref) -> () +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: }