diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 49db55047ff02..faa5164f52573 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -569,8 +569,20 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( mlir::OpBuilder modBuilder(mod.getBodyRegion()); auto recipe = modBuilder.create(loc, recipeName, ty); + llvm::SmallVector initArgsTy{ty}; + llvm::SmallVector initArgsLoc{loc}; + auto refTy = fir::unwrapRefType(ty); + if (auto seqTy = mlir::dyn_cast_or_null(refTy)) { + if (seqTy.hasDynamicExtents()) { + mlir::Type idxTy = builder.getIndexType(); + for (unsigned i = 0; i < seqTy.getDimension(); ++i) { + initArgsTy.push_back(idxTy); + initArgsLoc.push_back(loc); + } + } + } builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(), - {ty}, {loc}); + initArgsTy, initArgsLoc); builder.setInsertionPointToEnd(&recipe.getInitRegion().back()); genPrivateLikeInitRegion(builder, recipe, ty, loc); @@ -601,32 +613,28 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( builder.create(loc, initValue, recipe.getCopyRegion().front().getArgument(1)); } else if (auto seqTy = mlir::dyn_cast_or_null(ty)) { - if (seqTy.hasDynamicExtents()) - TODO(loc, "firstprivate recipe of array with dynamic extents"); - mlir::Type idxTy = builder.getIndexType(); - mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy()); - mlir::Value arraySrc = recipe.getCopyRegion().front().getArgument(0); - mlir::Value arrayDst = recipe.getCopyRegion().front().getArgument(1); - llvm::SmallVector loops; - llvm::SmallVector ivs; - for (auto ext : llvm::reverse(seqTy.getShape())) { - auto lb = builder.create( - loc, idxTy, builder.getIntegerAttr(idxTy, 0)); - auto ub = builder.create( - loc, idxTy, builder.getIntegerAttr(idxTy, ext - 1)); - auto step = builder.create( - loc, idxTy, builder.getIntegerAttr(idxTy, 1)); - auto loop = builder.create(loc, lb, ub, step, - /*unordered=*/false); - builder.setInsertionPointToStart(loop.getBody()); - loops.push_back(loop); - ivs.push_back(loop.getInductionVar()); - } - auto addr1 = builder.create(loc, refTy, arraySrc, ivs); - auto addr2 = builder.create(loc, refTy, arrayDst, ivs); - auto loadedValue = builder.create(loc, addr1); - builder.create(loc, loadedValue, addr2); - builder.setInsertionPointAfter(loops[0]); + fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; + auto shape = genShapeFromBoundsOrArgs( + loc, firBuilder, seqTy, bounds, recipe.getCopyRegion().getArguments()); + + auto leftDeclOp = builder.create( + loc, recipe.getCopyRegion().getArgument(0), llvm::StringRef{}, shape, + llvm::ArrayRef{}, fir::FortranVariableFlagsAttr{}); + auto rightDeclOp = builder.create( + loc, recipe.getCopyRegion().getArgument(1), llvm::StringRef{}, shape, + llvm::ArrayRef{}, fir::FortranVariableFlagsAttr{}); + + hlfir::DesignateOp::Subscripts triplets = + getSubscriptsFromArgs(recipe.getCopyRegion().getArguments()); + auto leftEntity = hlfir::Entity{leftDeclOp.getBase()}; + auto left = + genDesignateWithTriplets(firBuilder, loc, leftEntity, triplets, shape); + auto rightEntity = hlfir::Entity{rightDeclOp.getBase()}; + auto right = + genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape); + + firBuilder.create(loc, left, right); + } else if (auto boxTy = mlir::dyn_cast_or_null(ty)) { fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; llvm::SmallVector tripletArgs; diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 index 9a27a359e80b7..80b1272bd1b10 100644 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -3,33 +3,6 @@ ! 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.firstprivate.recipe @firstprivatization_section_ext10_ref_10xf32 : !fir.ref> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32> -! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) -! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> -! CHECK: } copy { -! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref>, %[[DST:.*]]: !fir.ref>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 9 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[COORD0:.*]] = fir.coordinate_of %[[SRC]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[DST]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref -! CHECK: %[[LOAD:.*]] = fir.load %[[COORD0]] : !fir.ref -! CHECK: fir.store %[[LOAD]] to %[[COORD1]] : !fir.ref -! CHECK: } -! CHECK: acc.terminator -! CHECK: } - -! CHECK-LABEL: acc.private.recipe @privatization_ref_10xf32 : !fir.ref> init { -! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> -! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) -! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> -! CHECK: } - ! CHECK-LABEL: func.func @_QPacc_parallel_loop() subroutine acc_parallel_loop diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 index 10c1bfc7c3802..9ce1828e63ddf 100644 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -3,6 +3,23 @@ ! 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.firstprivate.recipe @firstprivatization_ref_UxUx2xi32 : !fir.ref> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index): +! HLFIR: %[[SHAPE:.*]] = fir.shape %[[ARG1]], %[[ARG2]], %[[ARG3]] : (index, index, index) -> !fir.shape<3> +! HLFIR: %[[TEMP:.*]] = fir.alloca !fir.array, %[[ARG1]], %[[ARG2]], %[[ARG3]] +! HLFIR: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<3>) -> (!fir.box>, !fir.ref>) +! HLFIR: acc.yield %[[DECL]]#0 : !fir.box> +! CHECK: } copy { +! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref>, %[[DST:.*]]: !fir.ref>, %[[LB0:.*]]: index, %[[UB0:.*]]: index, %[[STEP0:.*]]: index, %[[LB1:.*]]: index, %[[UB1:.*]]: index, %[[STEP1:.*]]: index, %[[LB2:.*]]: index, %[[UB2:.*]]: index, %[[STEP2:.*]]: index): +! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}}, %{{.*}} : (index, index, index) -> !fir.shape<3> +! HLFIR: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<3>) -> (!fir.box>, !fir.ref>) +! HLFIR: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<3>) -> (!fir.box>, !fir.ref>) +! HLFIR: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 (%[[LB0]]:%[[UB0]]:%[[STEP0]], %[[LB1]]:%[[UB1]]:%[[STEP1]], %[[LB2]]:%[[UB2]]:%[[STEP2]]) shape %[[SHAPE]] : (!fir.box>, index, index, index, index, index, index, index, index, index, !fir.shape<3>) -> !fir.box> +! HLFIR: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 (%[[LB0]]:%[[UB0]]:%[[STEP0]], %[[LB1]]:%[[UB1]]:%[[STEP1]], %[[LB2]]:%[[UB2]]:%[[STEP2]]) shape %[[SHAPE]] : (!fir.box>, index, index, index, index, index, index, index, index, index, !fir.shape<3>) -> !fir.box> +! HLFIR: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.box>, !fir.box> +! HLFIR: acc.terminator +! CHECK: } + ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_lb4.ub9_box_Uxi32 : !fir.box> init { ! CHECK: ^bb0(%{{.*}}: !fir.box>): ! CHECK: } copy { @@ -87,16 +104,12 @@ ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } copy { ! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref>, %[[DST:.*]]: !fir.ref>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 49 : index -! CHECK: %[[STEP0:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { -! CHECK: %[[COORD0:.*]] = fir.coordinate_of %[[SRC]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[DST]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref -! CHECK: %[[VALUE:.*]] = fir.load %[[COORD0]] : !fir.ref -! CHECK: fir.store %[[VALUE]] to %[[COORD1]] : !fir.ref -! CHECK: } -! CHECK: acc.terminator +! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! HLFIR: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! HLFIR: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! HLFIR: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE:.*]] : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! HLFIR: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE:.*]] : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! HLFIR: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref>, !fir.ref> ! CHECK: } ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext100_ref_100xf32 : !fir.ref> init { @@ -107,15 +120,12 @@ ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } copy { ! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref>, %[[DST:.*]]: !fir.ref>): -! CHECK: %[[LB0:.*]] = arith.constant 0 : index -! CHECK: %[[UB0:.*]] = arith.constant 99 : index -! CHECK: %[[STEP1:.*]] = arith.constant 1 : index -! CHECK: fir.do_loop %[[IV0:.*]] = %c0 to %c99 step %c1 { -! CHECK: %[[COORD0:.*]] = fir.coordinate_of %[[SRC]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref -! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[DST]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref -! CHECK: %[[VALUE:.*]] = fir.load %[[COORD0]] : !fir.ref -! CHECK: fir.store %[[VALUE]] to %[[COORD1]] : !fir.ref -! CHECK: } +! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! HLFIR: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! HLFIR: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! HLFIR: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE]] : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! HLFIR: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE]] : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! HLFIR: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref>, !fir.ref> ! CHECK: acc.terminator ! CHECK: } @@ -337,3 +347,15 @@ subroutine acc_firstprivate_assumed_shape_with_section(a, n) a(i) = i end do end subroutine + +subroutine acc_firstprivate_dynamic_extent(a, n) + integer :: n, i + integer :: a(n, n, 2) + + !$acc parallel loop firstprivate(a) + do i = 1, n + a(i, i, 1) = i + end do +end subroutine + +! CHECK: acc.parallel firstprivate(@firstprivatization_ref_UxUx2xi32 -> %{{.*}} : !fir.ref>) diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp index cea93b8a2ca8c..b7e2aec6a4e6a 100644 --- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp +++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp @@ -452,7 +452,7 @@ LogicalResult acc::PrivateRecipeOp::verifyRegions() { LogicalResult acc::FirstprivateRecipeOp::verifyRegions() { if (failed(verifyInitLikeSingleArgRegion(*this, getInitRegion(), "privatization", "init", getType(), - /*verifyYield=*/true))) + /*verifyYield=*/false))) return failure(); if (getCopyRegion().empty()) diff --git a/mlir/test/Dialect/OpenACC/invalid.mlir b/mlir/test/Dialect/OpenACC/invalid.mlir index 225a8766fc550..ff92eab478bb4 100644 --- a/mlir/test/Dialect/OpenACC/invalid.mlir +++ b/mlir/test/Dialect/OpenACC/invalid.mlir @@ -312,18 +312,6 @@ acc.firstprivate.recipe @privatization_i32 : !llvm.ptr init { // ----- -// expected-error@+1 {{expects init region to yield a value of the privatization type}} -acc.firstprivate.recipe @privatization_i32 : !llvm.ptr init { -^bb0(%arg0 : !llvm.ptr): - %c1 = arith.constant 1 : i32 - %c0 = arith.constant 0 : i32 - %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr - llvm.store %c0, %0 : !llvm.ptr - acc.yield %0 : !llvm.ptr -} copy {} - -// ----- - // expected-error@+1 {{expects non-empty copy region}} acc.firstprivate.recipe @privatization_i32 : !llvm.ptr init { ^bb0(%arg0 : !llvm.ptr):