Index: flang/lib/Lower/OpenMP.cpp =================================================================== --- flang/lib/Lower/OpenMP.cpp +++ flang/lib/Lower/OpenMP.cpp @@ -824,7 +824,8 @@ } else if (blockDirective.v == llvm::omp::OMPD_single) { auto singleOp = firOpBuilder.create( currentLocation, allocateOperands, allocatorOperands, nowaitAttr); - createBodyOfOp(singleOp, converter, currentLocation, eval); + createBodyOfOp(singleOp, converter, currentLocation, eval, + &opClauseList); } else if (blockDirective.v == llvm::omp::OMPD_ordered) { auto orderedOp = firOpBuilder.create( currentLocation, /*simd=*/nullptr); Index: flang/lib/Optimizer/Builder/FIRBuilder.cpp =================================================================== --- flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -197,7 +197,7 @@ /// Get the block for adding Allocas. mlir::Block *fir::FirOpBuilder::getAllocaBlock() { auto iface = - getRegion().getParentOfType(); + getRegion().getParentOfType(); return iface ? iface.getAllocaBlock() : getEntryBlock(); } @@ -222,7 +222,7 @@ // If the alloca is inside an OpenMP Op which will be outlined then pin the // alloca here. const bool pinned = - getRegion().getParentOfType(); + getRegion().getParentOfType(); assert(!type.isa() && "cannot be a reference"); auto ae = create(loc, type, /*unique_name=*/llvm::StringRef{}, name, Index: flang/test/Lower/OpenMP/single.f90 =================================================================== --- flang/test/Lower/OpenMP/single.f90 +++ flang/test/Lower/OpenMP/single.f90 @@ -1,25 +1,25 @@ -!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="LLVMDialect,OMPDialect" +!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s +!RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s !=============================================================================== ! Single construct !=============================================================================== -!FIRDialect-LABEL: func @_QPomp_single -!FIRDialect-SAME: (%[[x:.*]]: !fir.ref {fir.bindc_name = "x"}) +!CHECK-LABEL: func @_QPomp_single +!CHECK-SAME: (%[[x:.*]]: !fir.ref {fir.bindc_name = "x"}) subroutine omp_single(x) integer, intent(inout) :: x - !OMPDialect: omp.parallel + !CHECK: omp.parallel !$omp parallel - !OMPDialect: omp.single + !CHECK: 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 + !CHECK: %[[xval:.*]] = fir.load %[[x]] : !fir.ref + !CHECK: %[[res:.*]] = arith.addi %[[xval]], %{{.*}} : i32 + !CHECK: fir.store %[[res]] to %[[x]] : !fir.ref x = x + 12 - !OMPDialect: omp.terminator + !CHECK: omp.terminator !$omp end single - !OMPDialect: omp.terminator + !CHECK: omp.terminator !$omp end parallel end subroutine omp_single @@ -27,21 +27,21 @@ ! Single construct with nowait !=============================================================================== -!FIRDialect-LABEL: func @_QPomp_single_nowait -!FIRDialect-SAME: (%[[x:.*]]: !fir.ref {fir.bindc_name = "x"}) +!CHECK-LABEL: func @_QPomp_single_nowait +!CHECK-SAME: (%[[x:.*]]: !fir.ref {fir.bindc_name = "x"}) subroutine omp_single_nowait(x) integer, intent(inout) :: x - !OMPDialect: omp.parallel + !CHECK: omp.parallel !$omp parallel - !OMPDialect: omp.single nowait + !CHECK: 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 + !CHECK: %[[xval:.*]] = fir.load %[[x]] : !fir.ref + !CHECK: %[[res:.*]] = arith.addi %[[xval]], %{{.*}} : i32 + !CHECK: fir.store %[[res]] to %[[x]] : !fir.ref x = x + 12 - !OMPDialect: omp.terminator + !CHECK: omp.terminator !$omp end single nowait - !OMPDialect: omp.terminator + !CHECK: omp.terminator !$omp end parallel end subroutine omp_single_nowait @@ -49,21 +49,77 @@ ! Single construct with allocate !=============================================================================== -!FIRDialect-LABEL: func @_QPsingle_allocate +!CHECK-LABEL: func @_QPsingle_allocate subroutine single_allocate() use omp_lib integer :: x - !OMPDialect: omp.parallel { + !CHECK: omp.parallel { !$omp parallel - !OMPDialect: omp.single allocate( - !FIRDialect: %{{.+}} : i32 -> %{{.+}} : !fir.ref - !LLVMDialect: %{{.+}} : i32 -> %{{.+}} : !llvm.ptr - !OMPDialect: ) { + !CHECK: omp.single allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref) { !$omp single allocate(omp_high_bw_mem_alloc: x) private(x) - !FIRDialect: arith.addi + !CHECK: arith.addi x = x + 12 - !OMPDialect: omp.terminator + !CHECK: omp.terminator !$omp end single - !OMPDialect: omp.terminator + !CHECK: omp.terminator !$omp end parallel end subroutine single_allocate + +!=============================================================================== +! Single construct with private +!=============================================================================== +!CHECK-LABEL: func @_QPsingle_private +subroutine single_private + type mytype + integer :: x + end type mytype + + !CHECK: %[[int_var:.+]] = fir.alloca i32 + !CHECK: %[[mytype_var:.+]] = fir.alloca !fir.type<_QFsingle_privateTmytype{x:i32}> + integer :: int_var + type(mytype) :: mytype_var + + !CHECK: fir.call @_QPbar(%[[int_var]], %[[mytype_var]]) : (!fir.ref, !fir.ref>) -> () + call bar(int_var, mytype_var) + + !CHECK: omp.single { + !$omp single private(int_var, mytype_var) + !CHECK: %[[int_var_private:.+]] = fir.alloca i32 + !CHECK: %[[mytype_var_private:.+]] = fir.alloca !fir.type<_QFsingle_privateTmytype{x:i32}> + + !CHECK: fir.call @_QPbar(%[[int_var_private]], %[[mytype_var_private]]) : (!fir.ref, !fir.ref>) -> () + call bar(int_var, mytype_var) + !CHECK: omp.terminator + !$omp end single +end subroutine single_private + +!=============================================================================== +! Single construct with firstprivate +!=============================================================================== +!CHECK-LABEL: func @_QPsingle_firstprivate +subroutine single_firstprivate + type mytype + integer :: x + end type mytype + + !CHECK: %[[int_var:.+]] = fir.alloca i32 + !CHECK: %[[mytype_var:.+]] = fir.alloca !fir.type<_QFsingle_firstprivateTmytype{x:i32}> + integer :: int_var + type(mytype) :: mytype_var + + !CHECK: fir.call @_QPbaz(%[[int_var]], %[[mytype_var]]) : (!fir.ref, !fir.ref>) -> () + call baz(int_var, mytype_var) + + !CHECK: omp.single { + !$omp single firstprivate(int_var, mytype_var) + !CHECK: %[[int_var_firstprivate:.+]] = fir.alloca i32 + !CHECK: %[[int_var_load:.+]] = fir.load %[[int_var]] : !fir.ref + !CHECK: fir.store %[[int_var_load]] to %[[int_var_firstprivate]] : !fir.ref + !CHECK: %[[mytype_var_firstprivate:.+]] = fir.alloca !fir.type<_QFsingle_firstprivateTmytype{x:i32}> + !CHECK: %[[mytype_var_load:.+]] = fir.load %[[mytype_var]] : !fir.ref> + !CHECK: fir.store %[[mytype_var_load]] to %[[mytype_var_firstprivate]] + !CHECK: fir.call @_QPbaz(%[[int_var_firstprivate]], %[[mytype_var_firstprivate]]) : (!fir.ref, !fir.ref>) -> () + call baz(int_var, mytype_var) + !CHECK: omp.terminator + !$omp end single +end subroutine single_firstprivate Index: mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td =================================================================== --- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -51,7 +51,7 @@ def ParallelOp : OpenMP_Op<"parallel", [ AutomaticAllocationScope, AttrSizedOperandSegments, - DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods, RecursiveSideEffects, ReductionClauseInterface]> { let summary = "parallel construct"; let description = [{ @@ -218,7 +218,8 @@ // 2.8.2 Single Construct //===----------------------------------------------------------------------===// -def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> { +def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments, + RegionalOpenMPOpInterface]> { let summary = "single directive"; let description = [{ The single construct specifies that the associated structured block is @@ -462,7 +463,7 @@ //===----------------------------------------------------------------------===// def TaskOp : OpenMP_Op<"task", [AttrSizedOperandSegments, - OutlineableOpenMPOpInterface, AutomaticAllocationScope, + RegionalOpenMPOpInterface, AutomaticAllocationScope, ReductionClauseInterface]> { let summary = "task construct"; let description = [{ Index: mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td =================================================================== --- mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td +++ mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td @@ -15,10 +15,10 @@ include "mlir/IR/OpBase.td" -def OutlineableOpenMPOpInterface : OpInterface<"OutlineableOpenMPOpInterface"> { +def RegionalOpenMPOpInterface : OpInterface<"RegionalOpenMPOpInterface"> { let description = [{ - OpenMP operations whose region will be outlined will implement this - interface. These operations will + OpenMP operations which are performed in one region, either inlined or + outlined, will implement this interface. }]; let cppNamespace = "::mlir::omp";