diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index c8089f4060286..4d6c32493136b 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -356,6 +356,19 @@ fir::ShapeOp genShapeOp(mlir::OpBuilder &builder, fir::SequenceType seqTy, return builder.create<fir::ShapeOp>(loc, extents); } +/// Return the nested sequence type if any. +static mlir::Type extractSequenceType(mlir::Type ty) { + if (mlir::isa<fir::SequenceType>(ty)) + return ty; + if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) + return extractSequenceType(boxTy.getEleTy()); + if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty)) + return extractSequenceType(heapTy.getEleTy()); + if (auto ptrTy = mlir::dyn_cast<fir::PointerType>(ty)) + return extractSequenceType(ptrTy.getEleTy()); + return mlir::Type{}; +} + template <typename RecipeOp> static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe, mlir::Type ty, mlir::Location loc) { @@ -381,7 +394,8 @@ static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe, } } } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) { - if (!mlir::isa<fir::SequenceType>(boxTy.getEleTy())) + mlir::Type innerTy = extractSequenceType(boxTy); + if (!innerTy) TODO(loc, "Unsupported boxed type in OpenACC privatization"); fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; hlfir::Entity source = hlfir::Entity{retVal}; @@ -751,19 +765,6 @@ static mlir::Value getReductionInitValue(fir::FirOpBuilder &builder, llvm::report_fatal_error("Unsupported OpenACC reduction type"); } -/// Return the nested sequence type if any. -static mlir::Type extractSequenceType(mlir::Type ty) { - if (mlir::isa<fir::SequenceType>(ty)) - return ty; - if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) - return extractSequenceType(boxTy.getEleTy()); - if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty)) - return extractSequenceType(heapTy.getEleTy()); - if (auto ptrTy = mlir::dyn_cast<fir::PointerType>(ty)) - return extractSequenceType(ptrTy.getEleTy()); - return mlir::Type{}; -} - static mlir::Value genReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type ty, mlir::acc::ReductionOperator op) { diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 index 6c71a9bc72ff3..ac9e38e596044 100644 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -3,6 +3,26 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefixes=CHECK,FIR ! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,HLFIR +! CHECK-LABEL: acc.private.recipe @privatization_box_ptr_Uxi32 : !fir.box<!fir.ptr<!fir.array<?xi32>>> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.ptr<!fir.array<?xi32>>>): +! HLFIR: %[[C0:.*]] = arith.constant 0 : index +! HLFIR: %[[BOX_DIMS:.*]]:3 = fir.box_dims %arg0, %c0 : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> (index, index, index) +! HLFIR: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! HLFIR: %[[TEMP:.*]] = fir.allocmem !fir.array<?xi32>, %0#1 {bindc_name = ".tmp", uniq_name = ""} +! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.heap<!fir.array<?xi32>>) +! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.box<!fir.array<?xi32>> +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_box_heap_Uxi32 : !fir.box<!fir.heap<!fir.array<?xi32>>> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.heap<!fir.array<?xi32>>>): +! HLFIR: %[[C0:.*]] = arith.constant 0 : index +! HLFIR: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index) +! HLFIR: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! HLFIR: %[[TEMP:.*]] = fir.allocmem !fir.array<?xi32>, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} +! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.heap<!fir.array<?xi32>>) +! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.box<!fir.array<?xi32>> +! CHECK: } + ! CHECK-LABEL: acc.private.recipe @privatization_box_Uxi32 : !fir.box<!fir.array<?xi32>> init { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>): ! HLFIR: %[[C0:.*]] = arith.constant 0 : index @@ -191,7 +211,43 @@ subroutine acc_private_assumed_shape(a, n) ! CHECK-LABEL: func.func @_QPacc_private_assumed_shape( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"} -! HLFIR: %[[DECL_A:.*]]:2 = hlfir.declare %arg0 {uniq_name = "_QFacc_private_assumed_shapeEa"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! HLFIR: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFacc_private_assumed_shapeEa"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) ! HLFIR: %[[ADDR:.*]] = fir.box_addr %[[DECL_A]]#1 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> ! HLFIR: %[[PRIVATE:.*]] = acc.private varPtr(%[[ADDR]] : !fir.ref<!fir.array<?xi32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<?xi32>> {name = "a"} ! HLFIR: acc.parallel private(@privatization_box_Uxi32 -> %[[PRIVATE]] : !fir.ref<!fir.array<?xi32>>) { + +subroutine acc_private_allocatable_array(a, n) + integer, allocatable :: a(:) + integer :: i, n + + !$acc parallel loop private(a) + do i = 1, n + a(i) = i + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_private_allocatable_array( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a"} +! HLFIR: %[[DECLA_A:.*]]:2 = hlfir.declare %[[ARG0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFacc_private_allocatable_arrayEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) +! HLFIR: %[[BOX:.*]] = fir.load %[[DECLA_A]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> +! HLFIR: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> +! HLFIR: %[[PRIVATE:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.heap<!fir.array<?xi32>>) bounds(%{{.*}}) -> !fir.heap<!fir.array<?xi32>> {name = "a"} +! HLFIR: acc.parallel private(@privatization_box_heap_Uxi32 -> %[[PRIVATE]] : !fir.heap<!fir.array<?xi32>>) { + +subroutine acc_private_pointer_array(a, n) + integer, pointer :: a(:) + integer :: i, n + + !$acc parallel loop private(a) + do i = 1, n + a(i) = i + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_private_pointer_array( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) { +! HLFIR: %[[DECL_A:.*]]:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFacc_private_pointer_arrayEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) +! HLFIR: %[[BOX:.*]] = fir.load %[[DECLA_A]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> +! HLFIR: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.ptr<!fir.array<?xi32>> +! HLFIR: %[[PRIVATE:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.ptr<!fir.array<?xi32>>) bounds(%{{.*}}) -> !fir.ptr<!fir.array<?xi32>> {name = "a"} +! HLFIR: acc.parallel private(@privatization_box_ptr_Uxi32 -> %[[PRIVATE]] : !fir.ptr<!fir.array<?xi32>>) diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp index 4cb758623093b..69a413305b825 100644 --- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp +++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp @@ -435,7 +435,7 @@ static LogicalResult verifyInitLikeSingleArgRegion( LogicalResult acc::PrivateRecipeOp::verifyRegions() { if (failed(verifyInitLikeSingleArgRegion(*this, getInitRegion(), "privatization", "init", getType(), - /*verifyYield=*/true))) + /*verifyYield=*/false))) return failure(); if (failed(verifyInitLikeSingleArgRegion( *this, getDestroyRegion(), "privatization", "destroy", getType(),