Skip to content

Commit d9568bd

Browse files
authored
[flang][openacc] Support array with dynamic extents in firstprivate recipe (#69026)
Add lowering support for array with dynamic extents in the firstprivate recipe. Generalize the lowering so static shaped arrays and array with dynamic extents use the same path. Some cleaning code is taken from #68836 that is not landed yet.
1 parent f74b85c commit d9568bd

File tree

5 files changed

+77
-86
lines changed

5 files changed

+77
-86
lines changed

flang/lib/Lower/OpenACC.cpp

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -569,8 +569,20 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe(
569569
mlir::OpBuilder modBuilder(mod.getBodyRegion());
570570
auto recipe =
571571
modBuilder.create<mlir::acc::FirstprivateRecipeOp>(loc, recipeName, ty);
572+
llvm::SmallVector<mlir::Type> initArgsTy{ty};
573+
llvm::SmallVector<mlir::Location> initArgsLoc{loc};
574+
auto refTy = fir::unwrapRefType(ty);
575+
if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(refTy)) {
576+
if (seqTy.hasDynamicExtents()) {
577+
mlir::Type idxTy = builder.getIndexType();
578+
for (unsigned i = 0; i < seqTy.getDimension(); ++i) {
579+
initArgsTy.push_back(idxTy);
580+
initArgsLoc.push_back(loc);
581+
}
582+
}
583+
}
572584
builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
573-
{ty}, {loc});
585+
initArgsTy, initArgsLoc);
574586
builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
575587
genPrivateLikeInitRegion<mlir::acc::FirstprivateRecipeOp>(builder, recipe, ty,
576588
loc);
@@ -601,32 +613,28 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe(
601613
builder.create<fir::StoreOp>(loc, initValue,
602614
recipe.getCopyRegion().front().getArgument(1));
603615
} else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) {
604-
if (seqTy.hasDynamicExtents())
605-
TODO(loc, "firstprivate recipe of array with dynamic extents");
606-
mlir::Type idxTy = builder.getIndexType();
607-
mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy());
608-
mlir::Value arraySrc = recipe.getCopyRegion().front().getArgument(0);
609-
mlir::Value arrayDst = recipe.getCopyRegion().front().getArgument(1);
610-
llvm::SmallVector<fir::DoLoopOp> loops;
611-
llvm::SmallVector<mlir::Value> ivs;
612-
for (auto ext : llvm::reverse(seqTy.getShape())) {
613-
auto lb = builder.create<mlir::arith::ConstantOp>(
614-
loc, idxTy, builder.getIntegerAttr(idxTy, 0));
615-
auto ub = builder.create<mlir::arith::ConstantOp>(
616-
loc, idxTy, builder.getIntegerAttr(idxTy, ext - 1));
617-
auto step = builder.create<mlir::arith::ConstantOp>(
618-
loc, idxTy, builder.getIntegerAttr(idxTy, 1));
619-
auto loop = builder.create<fir::DoLoopOp>(loc, lb, ub, step,
620-
/*unordered=*/false);
621-
builder.setInsertionPointToStart(loop.getBody());
622-
loops.push_back(loop);
623-
ivs.push_back(loop.getInductionVar());
624-
}
625-
auto addr1 = builder.create<fir::CoordinateOp>(loc, refTy, arraySrc, ivs);
626-
auto addr2 = builder.create<fir::CoordinateOp>(loc, refTy, arrayDst, ivs);
627-
auto loadedValue = builder.create<fir::LoadOp>(loc, addr1);
628-
builder.create<fir::StoreOp>(loc, loadedValue, addr2);
629-
builder.setInsertionPointAfter(loops[0]);
616+
fir::FirOpBuilder firBuilder{builder, recipe.getOperation()};
617+
auto shape = genShapeFromBoundsOrArgs(
618+
loc, firBuilder, seqTy, bounds, recipe.getCopyRegion().getArguments());
619+
620+
auto leftDeclOp = builder.create<hlfir::DeclareOp>(
621+
loc, recipe.getCopyRegion().getArgument(0), llvm::StringRef{}, shape,
622+
llvm::ArrayRef<mlir::Value>{}, fir::FortranVariableFlagsAttr{});
623+
auto rightDeclOp = builder.create<hlfir::DeclareOp>(
624+
loc, recipe.getCopyRegion().getArgument(1), llvm::StringRef{}, shape,
625+
llvm::ArrayRef<mlir::Value>{}, fir::FortranVariableFlagsAttr{});
626+
627+
hlfir::DesignateOp::Subscripts triplets =
628+
getSubscriptsFromArgs(recipe.getCopyRegion().getArguments());
629+
auto leftEntity = hlfir::Entity{leftDeclOp.getBase()};
630+
auto left =
631+
genDesignateWithTriplets(firBuilder, loc, leftEntity, triplets, shape);
632+
auto rightEntity = hlfir::Entity{rightDeclOp.getBase()};
633+
auto right =
634+
genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape);
635+
636+
firBuilder.create<hlfir::AssignOp>(loc, left, right);
637+
630638
} else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) {
631639
fir::FirOpBuilder firBuilder{builder, recipe.getOperation()};
632640
llvm::SmallVector<mlir::Value> tripletArgs;

flang/test/Lower/OpenACC/acc-parallel-loop.f90

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,6 @@
33
! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefixes=CHECK,FIR
44
! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,HLFIR
55

6-
! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext10_ref_10xf32 : !fir.ref<!fir.array<10xf32>> init {
7-
! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<10xf32>>):
8-
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
9-
! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32>
10-
! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
11-
! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<10xf32>>
12-
! CHECK: } copy {
13-
! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<!fir.array<10xf32>>, %[[DST:.*]]: !fir.ref<!fir.array<10xf32>>):
14-
! CHECK: %[[LB0:.*]] = arith.constant 0 : index
15-
! CHECK: %[[UB0:.*]] = arith.constant 9 : index
16-
! CHECK: %[[STEP0:.*]] = arith.constant 1 : index
17-
! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] {
18-
! CHECK: %[[COORD0:.*]] = fir.coordinate_of %[[SRC]], %[[IV0]] : (!fir.ref<!fir.array<10xf32>>, index) -> !fir.ref<f32>
19-
! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[DST]], %[[IV0]] : (!fir.ref<!fir.array<10xf32>>, index) -> !fir.ref<f32>
20-
! CHECK: %[[LOAD:.*]] = fir.load %[[COORD0]] : !fir.ref<f32>
21-
! CHECK: fir.store %[[LOAD]] to %[[COORD1]] : !fir.ref<f32>
22-
! CHECK: }
23-
! CHECK: acc.terminator
24-
! CHECK: }
25-
26-
! CHECK-LABEL: acc.private.recipe @privatization_ref_10xf32 : !fir.ref<!fir.array<10xf32>> init {
27-
! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<10xf32>>):
28-
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
29-
! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
30-
! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<10xf32>>
31-
! CHECK: }
32-
336
! CHECK-LABEL: func.func @_QPacc_parallel_loop()
347

358
subroutine acc_parallel_loop

flang/test/Lower/OpenACC/acc-private.f90

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@
33
! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefixes=CHECK,FIR
44
! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,HLFIR
55

6+
! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_UxUx2xi32 : !fir.ref<!fir.array<?x?x2xi32>> init {
7+
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.array<?x?x2xi32>>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index):
8+
! HLFIR: %[[SHAPE:.*]] = fir.shape %[[ARG1]], %[[ARG2]], %[[ARG3]] : (index, index, index) -> !fir.shape<3>
9+
! HLFIR: %[[TEMP:.*]] = fir.alloca !fir.array<?x?x2xi32>, %[[ARG1]], %[[ARG2]], %[[ARG3]]
10+
! HLFIR: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref<!fir.array<?x?x2xi32>>, !fir.shape<3>) -> (!fir.box<!fir.array<?x?x2xi32>>, !fir.ref<!fir.array<?x?x2xi32>>)
11+
! HLFIR: acc.yield %[[DECL]]#0 : !fir.box<!fir.array<?x?x2xi32>>
12+
! CHECK: } copy {
13+
! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<!fir.array<?x?x2xi32>>, %[[DST:.*]]: !fir.ref<!fir.array<?x?x2xi32>>, %[[LB0:.*]]: index, %[[UB0:.*]]: index, %[[STEP0:.*]]: index, %[[LB1:.*]]: index, %[[UB1:.*]]: index, %[[STEP1:.*]]: index, %[[LB2:.*]]: index, %[[UB2:.*]]: index, %[[STEP2:.*]]: index):
14+
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}}, %{{.*}} : (index, index, index) -> !fir.shape<3>
15+
! HLFIR: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<?x?x2xi32>>, !fir.shape<3>) -> (!fir.box<!fir.array<?x?x2xi32>>, !fir.ref<!fir.array<?x?x2xi32>>)
16+
! HLFIR: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<?x?x2xi32>>, !fir.shape<3>) -> (!fir.box<!fir.array<?x?x2xi32>>, !fir.ref<!fir.array<?x?x2xi32>>)
17+
! HLFIR: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 (%[[LB0]]:%[[UB0]]:%[[STEP0]], %[[LB1]]:%[[UB1]]:%[[STEP1]], %[[LB2]]:%[[UB2]]:%[[STEP2]]) shape %[[SHAPE]] : (!fir.box<!fir.array<?x?x2xi32>>, index, index, index, index, index, index, index, index, index, !fir.shape<3>) -> !fir.box<!fir.array<?x?x2xi32>>
18+
! HLFIR: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 (%[[LB0]]:%[[UB0]]:%[[STEP0]], %[[LB1]]:%[[UB1]]:%[[STEP1]], %[[LB2]]:%[[UB2]]:%[[STEP2]]) shape %[[SHAPE]] : (!fir.box<!fir.array<?x?x2xi32>>, index, index, index, index, index, index, index, index, index, !fir.shape<3>) -> !fir.box<!fir.array<?x?x2xi32>>
19+
! HLFIR: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.box<!fir.array<?x?x2xi32>>, !fir.box<!fir.array<?x?x2xi32>>
20+
! HLFIR: acc.terminator
21+
! CHECK: }
22+
623
! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_lb4.ub9_box_Uxi32 : !fir.box<!fir.array<?xi32>> init {
724
! CHECK: ^bb0(%{{.*}}: !fir.box<!fir.array<?xi32>>):
825
! CHECK: } copy {
@@ -87,16 +104,12 @@
87104
! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<50xf32>>
88105
! CHECK: } copy {
89106
! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<!fir.array<50xf32>>, %[[DST:.*]]: !fir.ref<!fir.array<50xf32>>):
90-
! CHECK: %[[LB0:.*]] = arith.constant 0 : index
91-
! CHECK: %[[UB0:.*]] = arith.constant 49 : index
92-
! CHECK: %[[STEP0:.*]] = arith.constant 1 : index
93-
! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] {
94-
! CHECK: %[[COORD0:.*]] = fir.coordinate_of %[[SRC]], %[[IV0]] : (!fir.ref<!fir.array<50xf32>>, index) -> !fir.ref<f32>
95-
! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[DST]], %[[IV0]] : (!fir.ref<!fir.array<50xf32>>, index) -> !fir.ref<f32>
96-
! CHECK: %[[VALUE:.*]] = fir.load %[[COORD0]] : !fir.ref<f32>
97-
! CHECK: fir.store %[[VALUE]] to %[[COORD1]] : !fir.ref<f32>
98-
! CHECK: }
99-
! CHECK: acc.terminator
107+
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
108+
! HLFIR: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<50xf32>>, !fir.ref<!fir.array<50xf32>>)
109+
! HLFIR: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<50xf32>>, !fir.ref<!fir.array<50xf32>>)
110+
! HLFIR: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE:.*]] : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<50xf32>>
111+
! HLFIR: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE:.*]] : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<50xf32>>
112+
! HLFIR: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref<!fir.array<50xf32>>, !fir.ref<!fir.array<50xf32>>
100113
! CHECK: }
101114

102115
! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext100_ref_100xf32 : !fir.ref<!fir.array<100xf32>> init {
@@ -107,15 +120,12 @@
107120
! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.array<100xf32>>
108121
! CHECK: } copy {
109122
! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref<!fir.array<100xf32>>, %[[DST:.*]]: !fir.ref<!fir.array<100xf32>>):
110-
! CHECK: %[[LB0:.*]] = arith.constant 0 : index
111-
! CHECK: %[[UB0:.*]] = arith.constant 99 : index
112-
! CHECK: %[[STEP1:.*]] = arith.constant 1 : index
113-
! CHECK: fir.do_loop %[[IV0:.*]] = %c0 to %c99 step %c1 {
114-
! CHECK: %[[COORD0:.*]] = fir.coordinate_of %[[SRC]], %[[IV0]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32>
115-
! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[DST]], %[[IV0]] : (!fir.ref<!fir.array<100xf32>>, index) -> !fir.ref<f32>
116-
! CHECK: %[[VALUE:.*]] = fir.load %[[COORD0]] : !fir.ref<f32>
117-
! CHECK: fir.store %[[VALUE]] to %[[COORD1]] : !fir.ref<f32>
118-
! CHECK: }
123+
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
124+
! HLFIR: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
125+
! HLFIR: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>)
126+
! HLFIR: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE]] : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<100xf32>>
127+
! HLFIR: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE]] : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<100xf32>>
128+
! HLFIR: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref<!fir.array<100xf32>>, !fir.ref<!fir.array<100xf32>>
119129
! CHECK: acc.terminator
120130
! CHECK: }
121131

@@ -337,3 +347,15 @@ subroutine acc_firstprivate_assumed_shape_with_section(a, n)
337347
a(i) = i
338348
end do
339349
end subroutine
350+
351+
subroutine acc_firstprivate_dynamic_extent(a, n)
352+
integer :: n, i
353+
integer :: a(n, n, 2)
354+
355+
!$acc parallel loop firstprivate(a)
356+
do i = 1, n
357+
a(i, i, 1) = i
358+
end do
359+
end subroutine
360+
361+
! CHECK: acc.parallel firstprivate(@firstprivatization_ref_UxUx2xi32 -> %{{.*}} : !fir.ref<!fir.array<?x?x2xi32>>)

mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ LogicalResult acc::PrivateRecipeOp::verifyRegions() {
452452
LogicalResult acc::FirstprivateRecipeOp::verifyRegions() {
453453
if (failed(verifyInitLikeSingleArgRegion(*this, getInitRegion(),
454454
"privatization", "init", getType(),
455-
/*verifyYield=*/true)))
455+
/*verifyYield=*/false)))
456456
return failure();
457457

458458
if (getCopyRegion().empty())

mlir/test/Dialect/OpenACC/invalid.mlir

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -312,18 +312,6 @@ acc.firstprivate.recipe @privatization_i32 : !llvm.ptr<i32> init {
312312

313313
// -----
314314

315-
// expected-error@+1 {{expects init region to yield a value of the privatization type}}
316-
acc.firstprivate.recipe @privatization_i32 : !llvm.ptr<f32> init {
317-
^bb0(%arg0 : !llvm.ptr<f32>):
318-
%c1 = arith.constant 1 : i32
319-
%c0 = arith.constant 0 : i32
320-
%0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<i32>
321-
llvm.store %c0, %0 : !llvm.ptr<i32>
322-
acc.yield %0 : !llvm.ptr<i32>
323-
} copy {}
324-
325-
// -----
326-
327315
// expected-error@+1 {{expects non-empty copy region}}
328316
acc.firstprivate.recipe @privatization_i32 : !llvm.ptr<i32> init {
329317
^bb0(%arg0 : !llvm.ptr<i32>):

0 commit comments

Comments
 (0)