[flang-commits] [flang] [flang][openacc] Support assumed shape array in firstprivate recipe (PR #68640)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Tue Oct 10 09:04:20 PDT 2023
https://github.com/clementval updated https://github.com/llvm/llvm-project/pull/68640
>From 8459381299602a80b26ea44b5d099f59b0169ba3 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Mon, 9 Oct 2023 15:00:12 -0700
Subject: [PATCH] [flang][openacc] Support assumed shape array in firstprivate
recipe
---
flang/include/flang/Lower/OpenACC.h | 8 +-
flang/lib/Lower/OpenACC.cpp | 280 +++++++++++-------
.../test/Lower/OpenACC/acc-parallel-loop.f90 | 4 +-
flang/test/Lower/OpenACC/acc-parallel.f90 | 4 +-
flang/test/Lower/OpenACC/acc-private.f90 | 64 +++-
flang/test/Lower/OpenACC/acc-serial-loop.f90 | 4 +-
flang/test/Lower/OpenACC/acc-serial.f90 | 4 +-
mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp | 2 +-
8 files changed, 246 insertions(+), 124 deletions(-)
diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index b342e4a4704dab1..c73af0a6eb0f874 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -90,10 +90,10 @@ createOrGetReductionRecipe(fir::FirOpBuilder &, llvm::StringRef, mlir::Location,
/// Get a acc.firstprivate.recipe op for the given type or create it if it does
/// not exist yet.
-mlir::acc::FirstprivateRecipeOp createOrGetFirstprivateRecipe(mlir::OpBuilder &,
- llvm::StringRef,
- mlir::Location,
- mlir::Type);
+mlir::acc::FirstprivateRecipeOp
+createOrGetFirstprivateRecipe(mlir::OpBuilder &, llvm::StringRef,
+ mlir::Location, mlir::Type,
+ llvm::SmallVector<mlir::Value> &);
void attachDeclarePostAllocAction(AbstractConverter &, fir::FirOpBuilder &,
const Fortran::semantics::Symbol &);
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 3d3fcce44c529fe..de551c36c9dc9d5 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -427,9 +427,78 @@ Fortran::lower::createOrGetPrivateRecipe(mlir::OpBuilder &builder,
return recipe;
}
+/// Check if the DataBoundsOp is a constant bound (lb and ub are constants or
+/// extent is a constant).
+bool isConstantBound(mlir::acc::DataBoundsOp &op) {
+ if (op.getLowerbound() && fir::getIntIfConstant(op.getLowerbound()) &&
+ op.getUpperbound() && fir::getIntIfConstant(op.getUpperbound()))
+ return true;
+ if (op.getExtent() && fir::getIntIfConstant(op.getExtent()))
+ return true;
+ return false;
+}
+
+/// Return true iff all the bounds are expressed with constant values.
+bool areAllBoundConstant(llvm::SmallVector<mlir::Value> &bounds) {
+ for (auto bound : bounds) {
+ auto dataBound =
+ mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
+ assert(dataBound && "Must be DataBoundOp operation");
+ if (!isConstantBound(dataBound))
+ return false;
+ }
+ return true;
+}
+
+static fir::ShapeOp
+genShapeFromBounds(mlir::Location loc, fir::FirOpBuilder &builder,
+ const llvm::SmallVector<mlir::Value> &args) {
+ assert(args.size() % 3 == 0 && "Triplets must be a multiple of 3");
+ llvm::SmallVector<mlir::Value> extents;
+ mlir::Type idxTy = builder.getIndexType();
+ mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
+ mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
+ for (unsigned i = 0; i < args.size(); i += 3) {
+ mlir::Value s1 =
+ builder.create<mlir::arith::SubIOp>(loc, args[i + 1], args[0]);
+ mlir::Value s2 = builder.create<mlir::arith::AddIOp>(loc, s1, one);
+ mlir::Value s3 = builder.create<mlir::arith::DivSIOp>(loc, s2, args[i + 2]);
+ mlir::Value cmp = builder.create<mlir::arith::CmpIOp>(
+ loc, mlir::arith::CmpIPredicate::sgt, s3, zero);
+ mlir::Value ext = builder.create<mlir::arith::SelectOp>(loc, cmp, s3, zero);
+ extents.push_back(ext);
+ }
+ return builder.create<fir::ShapeOp>(loc, extents);
+}
+
+static llvm::SmallVector<mlir::Value>
+genConstantBounds(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::acc::DataBoundsOp &dataBound) {
+ mlir::Type idxTy = builder.getIndexType();
+ mlir::Value lb, ub, step;
+ if (dataBound.getLowerbound() &&
+ fir::getIntIfConstant(dataBound.getLowerbound()) &&
+ dataBound.getUpperbound() &&
+ fir::getIntIfConstant(dataBound.getUpperbound())) {
+ lb = builder.createIntegerConstant(
+ loc, idxTy, *fir::getIntIfConstant(dataBound.getLowerbound()));
+ ub = builder.createIntegerConstant(
+ loc, idxTy, *fir::getIntIfConstant(dataBound.getUpperbound()));
+ step = builder.createIntegerConstant(loc, idxTy, 1);
+ } else if (dataBound.getExtent()) {
+ lb = builder.createIntegerConstant(loc, idxTy, 0);
+ ub = builder.createIntegerConstant(
+ loc, idxTy, *fir::getIntIfConstant(dataBound.getExtent()) - 1);
+ step = builder.createIntegerConstant(loc, idxTy, 1);
+ } else {
+ llvm::report_fatal_error("Expect constant lb/ub or extent");
+ }
+ return {lb, ub, step};
+}
+
mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe(
mlir::OpBuilder &builder, llvm::StringRef recipeName, mlir::Location loc,
- mlir::Type ty) {
+ mlir::Type ty, llvm::SmallVector<mlir::Value> &bounds) {
mlir::ModuleOp mod =
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
if (auto recipe =
@@ -446,47 +515,111 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe(
genPrivateLikeInitRegion<mlir::acc::FirstprivateRecipeOp>(builder, recipe, ty,
loc);
- // Add empty copy region for firstprivate. TODO add copy sequence.
+ bool allConstantBound = areAllBoundConstant(bounds);
+ llvm::SmallVector<mlir::Type> argsTy{ty, ty};
+ llvm::SmallVector<mlir::Location> argsLoc{loc, loc};
+ if (!allConstantBound) {
+ for (mlir::Value bound : llvm::reverse(bounds)) {
+ auto dataBound =
+ mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
+ argsTy.push_back(dataBound.getLowerbound().getType());
+ argsLoc.push_back(dataBound.getLowerbound().getLoc());
+ argsTy.push_back(dataBound.getUpperbound().getType());
+ argsLoc.push_back(dataBound.getUpperbound().getLoc());
+ argsTy.push_back(dataBound.getStartIdx().getType());
+ argsLoc.push_back(dataBound.getStartIdx().getLoc());
+ }
+ }
builder.createBlock(&recipe.getCopyRegion(), recipe.getCopyRegion().end(),
- {ty, ty}, {loc, loc});
+ argsTy, argsLoc);
builder.setInsertionPointToEnd(&recipe.getCopyRegion().back());
- if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(ty)) {
- if (fir::isa_trivial(refTy.getEleTy())) {
- mlir::Value initValue = builder.create<fir::LoadOp>(
- loc, recipe.getCopyRegion().front().getArgument(0));
- builder.create<fir::StoreOp>(
- loc, initValue, recipe.getCopyRegion().front().getArgument(1));
- } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(
- refTy.getEleTy())) {
- if (seqTy.hasDynamicExtents())
- TODO(loc, "private 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<fir::DoLoopOp> loops;
- llvm::SmallVector<mlir::Value> ivs;
- for (auto ext : llvm::reverse(seqTy.getShape())) {
- auto lb = builder.create<mlir::arith::ConstantOp>(
- loc, idxTy, builder.getIntegerAttr(idxTy, 0));
- auto ub = builder.create<mlir::arith::ConstantOp>(
- loc, idxTy, builder.getIntegerAttr(idxTy, ext - 1));
- auto step = builder.create<mlir::arith::ConstantOp>(
- loc, idxTy, builder.getIntegerAttr(idxTy, 1));
- auto loop = builder.create<fir::DoLoopOp>(loc, lb, ub, step,
- /*unordered=*/false);
- builder.setInsertionPointToStart(loop.getBody());
- loops.push_back(loop);
- ivs.push_back(loop.getInductionVar());
+ ty = fir::unwrapRefType(ty);
+ if (fir::isa_trivial(ty)) {
+ mlir::Value initValue = builder.create<fir::LoadOp>(
+ loc, recipe.getCopyRegion().front().getArgument(0));
+ builder.create<fir::StoreOp>(loc, initValue,
+ recipe.getCopyRegion().front().getArgument(1));
+ } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) {
+ if (seqTy.hasDynamicExtents())
+ TODO(loc, "private 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<fir::DoLoopOp> loops;
+ llvm::SmallVector<mlir::Value> ivs;
+ for (auto ext : llvm::reverse(seqTy.getShape())) {
+ auto lb = builder.create<mlir::arith::ConstantOp>(
+ loc, idxTy, builder.getIntegerAttr(idxTy, 0));
+ auto ub = builder.create<mlir::arith::ConstantOp>(
+ loc, idxTy, builder.getIntegerAttr(idxTy, ext - 1));
+ auto step = builder.create<mlir::arith::ConstantOp>(
+ loc, idxTy, builder.getIntegerAttr(idxTy, 1));
+ auto loop = builder.create<fir::DoLoopOp>(loc, lb, ub, step,
+ /*unordered=*/false);
+ builder.setInsertionPointToStart(loop.getBody());
+ loops.push_back(loop);
+ ivs.push_back(loop.getInductionVar());
+ }
+ auto addr1 = builder.create<fir::CoordinateOp>(loc, refTy, arraySrc, ivs);
+ auto addr2 = builder.create<fir::CoordinateOp>(loc, refTy, arrayDst, ivs);
+ auto loadedValue = builder.create<fir::LoadOp>(loc, addr1);
+ builder.create<fir::StoreOp>(loc, loadedValue, addr2);
+ builder.setInsertionPointAfter(loops[0]);
+ } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) {
+ fir::FirOpBuilder firBuilder{builder, recipe.getOperation()};
+ llvm::SmallVector<mlir::Value> tripletArgs;
+ mlir::Type innerTy = extractSequenceType(boxTy);
+ fir::SequenceType seqTy =
+ mlir::dyn_cast_or_null<fir::SequenceType>(innerTy);
+ if (!seqTy)
+ TODO(loc, "Unsupported boxed type in OpenACC reduction");
+
+ if (allConstantBound) {
+ for (auto bound : llvm::reverse(bounds)) {
+ auto dataBound =
+ mlir::cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
+ tripletArgs.append(genConstantBounds(firBuilder, loc, dataBound));
}
- auto addr1 = builder.create<fir::CoordinateOp>(loc, refTy, arraySrc, ivs);
- auto addr2 = builder.create<fir::CoordinateOp>(loc, refTy, arrayDst, ivs);
- auto loadedValue = builder.create<fir::LoadOp>(loc, addr1);
- builder.create<fir::StoreOp>(loc, loadedValue, addr2);
- builder.setInsertionPointAfter(loops[0]);
+ } else {
+ assert(((recipe.getCopyRegion().getArguments().size() - 2) / 3 ==
+ seqTy.getDimension()) &&
+ "Expect 3 block arguments per dimension");
+ for (auto arg : recipe.getCopyRegion().getArguments().drop_front(2))
+ tripletArgs.push_back(arg);
}
+ auto shape = genShapeFromBounds(loc, firBuilder, tripletArgs);
+ hlfir::DesignateOp::Subscripts triplets;
+ for (unsigned i = 2; i < recipe.getCopyRegion().getArguments().size();
+ i += 3)
+ triplets.emplace_back(hlfir::DesignateOp::Triplet{
+ recipe.getCopyRegion().getArgument(i),
+ recipe.getCopyRegion().getArgument(i + 1),
+ recipe.getCopyRegion().getArgument(i + 2)});
+
+ llvm::SmallVector<mlir::Value> lenParamsLeft;
+ auto leftEntity = hlfir::Entity{recipe.getCopyRegion().getArgument(0)};
+ hlfir::genLengthParameters(loc, firBuilder, leftEntity, lenParamsLeft);
+ auto leftDesignate = firBuilder.create<hlfir::DesignateOp>(
+ loc, leftEntity.getBase().getType(), leftEntity, /*component=*/"",
+ /*componentShape=*/mlir::Value{}, triplets,
+ /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt,
+ shape, lenParamsLeft);
+ auto left = hlfir::Entity{leftDesignate.getResult()};
+
+ llvm::SmallVector<mlir::Value> lenParamsRight;
+ auto rightEntity = hlfir::Entity{recipe.getCopyRegion().getArgument(1)};
+ hlfir::genLengthParameters(loc, firBuilder, rightEntity, lenParamsRight);
+ auto rightDesignate = firBuilder.create<hlfir::DesignateOp>(
+ loc, rightEntity.getBase().getType(), rightEntity, /*component=*/"",
+ /*componentShape=*/mlir::Value{}, triplets,
+ /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt,
+ shape, lenParamsRight);
+ auto right = hlfir::Entity{rightDesignate.getResult()};
+ firBuilder.create<hlfir::AssignOp>(loc, left, right);
}
+
builder.create<mlir::acc::TerminatorOp>(loc);
builder.restoreInsertionPoint(crtPos);
return recipe;
@@ -584,10 +717,12 @@ genPrivatizations(const Fortran::parser::AccObjectList &objectList,
/*implicit=*/false, mlir::acc::DataClause::acc_private, retTy);
dataOperands.push_back(op.getAccPtr());
} else {
+ std::string suffix =
+ areAllBoundConstant(bounds) ? getBoundsString(bounds) : "";
std::string recipeName = fir::getTypeAsString(
- retTy, converter.getKindMap(), "firstprivatization");
+ retTy, converter.getKindMap(), "firstprivatization" + suffix);
recipe = Fortran::lower::createOrGetFirstprivateRecipe(
- builder, recipeName, operandLocation, retTy);
+ builder, recipeName, operandLocation, retTy, bounds);
auto op = createDataEntryOp<mlir::acc::FirstprivateOp>(
builder, operandLocation, baseAddr, asFortran, bounds, true,
/*implicit=*/false, mlir::acc::DataClause::acc_firstprivate, retTy);
@@ -683,29 +818,6 @@ static R getReductionInitValue(mlir::acc::ReductionOperator op, mlir::Type ty) {
llvm_unreachable("OpenACC reduction unsupported type");
}
-/// Check if the DataBoundsOp is a constant bound (lb and ub are constants or
-/// extent is a constant).
-bool isConstantBound(mlir::acc::DataBoundsOp &op) {
- if (op.getLowerbound() && fir::getIntIfConstant(op.getLowerbound()) &&
- op.getUpperbound() && fir::getIntIfConstant(op.getUpperbound()))
- return true;
- if (op.getExtent() && fir::getIntIfConstant(op.getExtent()))
- return true;
- return false;
-}
-
-/// Return true iff all the bounds are expressed with constant values.
-bool areAllBoundConstant(llvm::SmallVector<mlir::Value> &bounds) {
- for (auto bound : bounds) {
- auto dataBound =
- mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
- assert(dataBound && "Must be DataBoundOp operation");
- if (!isConstantBound(dataBound))
- return false;
- }
- return true;
-}
-
/// Return a constant with the initial value for the reduction operator and
/// type combination.
static mlir::Value getReductionInitValue(fir::FirOpBuilder &builder,
@@ -911,52 +1023,6 @@ static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder,
TODO(loc, "reduction operator");
}
-static fir::ShapeOp
-genShapeFromBounds(mlir::Location loc, fir::FirOpBuilder &builder,
- const llvm::SmallVector<mlir::Value> &args) {
- assert(args.size() % 3 == 0 && "Triplets must be a multiple of 3");
- llvm::SmallVector<mlir::Value> extents;
- mlir::Type idxTy = builder.getIndexType();
- mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
- mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
- for (unsigned i = 0; i < args.size(); i += 3) {
- mlir::Value s1 =
- builder.create<mlir::arith::SubIOp>(loc, args[i + 1], args[0]);
- mlir::Value s2 = builder.create<mlir::arith::AddIOp>(loc, s1, one);
- mlir::Value s3 = builder.create<mlir::arith::DivSIOp>(loc, s2, args[i + 2]);
- mlir::Value cmp = builder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::sgt, s3, zero);
- mlir::Value ext = builder.create<mlir::arith::SelectOp>(loc, cmp, s3, zero);
- extents.push_back(ext);
- }
- return builder.create<fir::ShapeOp>(loc, extents);
-}
-
-static llvm::SmallVector<mlir::Value>
-genConstantBounds(fir::FirOpBuilder &builder, mlir::Location loc,
- mlir::acc::DataBoundsOp &dataBound) {
- mlir::Type idxTy = builder.getIndexType();
- mlir::Value lb, ub, step;
- if (dataBound.getLowerbound() &&
- fir::getIntIfConstant(dataBound.getLowerbound()) &&
- dataBound.getUpperbound() &&
- fir::getIntIfConstant(dataBound.getUpperbound())) {
- lb = builder.createIntegerConstant(
- loc, idxTy, *fir::getIntIfConstant(dataBound.getLowerbound()));
- ub = builder.createIntegerConstant(
- loc, idxTy, *fir::getIntIfConstant(dataBound.getUpperbound()));
- step = builder.createIntegerConstant(loc, idxTy, 1);
- } else if (dataBound.getExtent()) {
- lb = builder.createIntegerConstant(loc, idxTy, 0);
- ub = builder.createIntegerConstant(
- loc, idxTy, *fir::getIntIfConstant(dataBound.getExtent()) - 1);
- step = builder.createIntegerConstant(loc, idxTy, 1);
- } else {
- llvm::report_fatal_error("Expect constant lb/ub or extent");
- }
- return {lb, ub, step};
-}
-
static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::acc::ReductionOperator op, mlir::Type ty,
mlir::Value value1, mlir::Value value2,
diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90
index 22726b0f4909414..ac028fcf877b4a3 100644
--- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90
+++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90
@@ -3,7 +3,7 @@
! 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_10xf32 : !fir.ref<!fir.array<10xf32>> init {
+! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext10_ref_10xf32 : !fir.ref<!fir.array<10xf32>> init {
! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<10xf32>>):
! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32>
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
@@ -514,7 +514,7 @@ subroutine acc_parallel_loop
! HLFIR: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#1 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"}
! FIR: %[[ACC_PRIVATE_B:.*]] = acc.firstprivate varPtr(%[[B]] : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"}
! HLFIR: %[[ACC_PRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#1 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"}
-! CHECK: acc.parallel firstprivate(@firstprivatization_ref_10xf32 -> %[[ACC_PRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) private(@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) {
+! CHECK: acc.parallel firstprivate(@firstprivatization_section_ext10_ref_10xf32 -> %[[ACC_PRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) private(@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) {
! FIR: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[A]] : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"}
! HLFIR: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#1 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"}
! CHECK: acc.loop private(@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) {
diff --git a/flang/test/Lower/OpenACC/acc-parallel.f90 b/flang/test/Lower/OpenACC/acc-parallel.f90
index cdde9128d70c9be..56f225b7b603fa4 100644
--- a/flang/test/Lower/OpenACC/acc-parallel.f90
+++ b/flang/test/Lower/OpenACC/acc-parallel.f90
@@ -3,7 +3,7 @@
! 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_10x10xf32 : !fir.ref<!fir.array<10x10xf32>> init {
+! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext10xext10_ref_10x10xf32 : !fir.ref<!fir.array<10x10xf32>> init {
! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<10x10xf32>>):
! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10x10xf32>
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2>
@@ -371,7 +371,7 @@ subroutine acc_parallel
! HLFIR: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#1 : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {name = "b"}
! FIR: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[C]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"}
! HLFIR: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[DECLC]]#1 : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"}
-! CHECK: acc.parallel firstprivate(@firstprivatization_ref_10x10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10x10xf32>>) private(@privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_C]] : !fir.ref<!fir.array<10x10xf32>>) {
+! CHECK: acc.parallel firstprivate(@firstprivatization_section_ext10xext10_ref_10x10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10x10xf32>>) private(@privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_C]] : !fir.ref<!fir.array<10x10xf32>>) {
! CHECK: acc.yield
! CHECK-NEXT: }{{$}}
diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90
index ac9e38e596044a1..040309685277ee2 100644
--- a/flang/test/Lower/OpenACC/acc-private.f90
+++ b/flang/test/Lower/OpenACC/acc-private.f90
@@ -3,6 +3,44 @@
! 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_lb4.ub9_box_Uxi32 : !fir.box<!fir.array<?xi32>> init {
+! CHECK: ^bb0(%{{.*}}: !fir.box<!fir.array<?xi32>>):
+! CHECK: } copy {
+! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>):
+! HLFIR: %[[LB:.*]] = arith.constant 4 : index
+! HLFIR: %[[UB:.*]] = arith.constant 9 : index
+! HLFIR: %[[STEP:.*]] = arith.constant 1 : index
+! HLFIR: %[[C1:.*]] = arith.constant 1 : index
+! HLFIR: %[[C0:.*]] = arith.constant 0 : index
+! HLFIR: %[[EXT0:.*]] = arith.subi %[[UB]], %[[LB]] : index
+! HLFIR: %[[EXT1:.*]] = arith.addi %[[EXT0]], %[[C1]] : index
+! HLFIR: %[[EXT2:.*]] = arith.divsi %[[EXT1]], %[[STEP]] : index
+! HLFIR: %[[CMP:.*]] = arith.cmpi sgt, %[[EXT2]], %[[C0]] : index
+! HLFIR: %[[SELECT:.*]] = arith.select %[[CMP]], %[[EXT2]], %[[C0]] : index
+! HLFIR: %[[SHAPE:.*]] = fir.shape %[[SELECT]] : (index) -> !fir.shape<1>
+! HLFIR: %[[LEFT:.*]] = hlfir.designate %[[ARG0]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
+! HLFIR: %[[RIGHT:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
+! HLFIR: hlfir.assign %[[LEFT]] to %[[RIGHT]] : !fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>
+! HLFIR: acc.terminator
+! CHECK: }
+
+! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_box_Uxi32 : !fir.box<!fir.array<?xi32>> init {
+! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>):
+! HLFIR: %[[C0:.*]] = arith.constant 0 : index
+! HLFIR: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %c0 : (!fir.box<!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: %[[DECL:.*]]: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 %[[DECL]]#0 : !fir.box<!fir.array<?xi32>>
+! CHECK: } copy {
+! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index, %[[ARG4:.*]]: index):
+! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
+! HLFIR: %[[DES_V1:.*]] = hlfir.designate %[[ARG0]] (%{{.*}}:%{{.*}}:%{{.*}}) shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
+! HLFIR: %[[DES_V2:.*]] = hlfir.designate %[[ARG1]] (%{{.*}}:%{{.*}}:%{{.*}}) shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
+! HLFIR: hlfir.assign %[[DES_V1]] to %[[DES_V2]] : !fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>
+! HLFIR: acc.terminator
+! CHECK: }
+
! 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
@@ -33,7 +71,7 @@
! HLFIR: acc.yield %[[DECLARE:.*]]#0 : !fir.box<!fir.array<?xi32>>
! CHECK: }
-! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_50xf32 : !fir.ref<!fir.array<50xf32>> init {
+! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_lb50.ub99_ref_50xf32 : !fir.ref<!fir.array<50xf32>> init {
! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<50xf32>>):
! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<50xf32>
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
@@ -53,7 +91,7 @@
! CHECK: acc.terminator
! CHECK: }
-! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_100xf32 : !fir.ref<!fir.array<100xf32>> init {
+! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext100_ref_100xf32 : !fir.ref<!fir.array<100xf32>> init {
! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<100xf32>>):
! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32>
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
@@ -181,7 +219,7 @@ program acc_private
! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index)
! FIR: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[B]] : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<100xf32>> {name = "b"}
! HLFIR: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#1 : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<100xf32>> {name = "b"}
-! CHECK: acc.parallel firstprivate(@firstprivatization_ref_100xf32 -> %[[FP_B]] : !fir.ref<!fir.array<100xf32>>)
+! CHECK: acc.parallel firstprivate(@firstprivatization_section_ext100_ref_100xf32 -> %[[FP_B]] : !fir.ref<!fir.array<100xf32>>)
! CHECK: acc.yield
!$acc parallel loop firstprivate(b(51:100))
@@ -196,7 +234,7 @@ program acc_private
! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index)
! FIR: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[B]] : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<50xf32>> {name = "b(51:100)"}
! HLFIR: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#1 : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<50xf32>> {name = "b(51:100)"}
-! CHECK: acc.parallel firstprivate(@firstprivatization_ref_50xf32 -> %[[FP_B]] : !fir.ref<!fir.array<50xf32>>)
+! CHECK: acc.parallel firstprivate(@firstprivatization_section_lb50.ub99_ref_50xf32 -> %[[FP_B]] : !fir.ref<!fir.array<50xf32>>)
end program
@@ -251,3 +289,21 @@ subroutine acc_private_pointer_array(a, n)
! 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>>)
+
+subroutine acc_firstprivate_assumed_shape(a, n)
+ integer :: a(:), i, n
+
+ !$acc parallel loop firstprivate(a)
+ do i = 1, n
+ a(i) = i
+ end do
+end subroutine
+
+subroutine acc_firstprivate_assumed_shape_with_section(a, n)
+ integer :: a(:), i, n
+
+ !$acc parallel loop firstprivate(a(5:10))
+ do i = 1, n
+ a(i) = i
+ end do
+end subroutine
diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90
index c9d556b91cb6c3e..0b2fdd6a3347d51 100644
--- a/flang/test/Lower/OpenACC/acc-serial-loop.f90
+++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90
@@ -3,7 +3,7 @@
! 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_10xf32 : !fir.ref<!fir.array<10xf32>> init {
+! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext10_ref_10xf32 : !fir.ref<!fir.array<10xf32>> init {
! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<10xf32>>):
! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32>
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
@@ -421,7 +421,7 @@ subroutine acc_serial_loop
! HLFIR: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#1 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"}
! FIR: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[B]] : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"}
! HLFIR: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#1 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"}
-! CHECK: acc.serial firstprivate(@firstprivatization_ref_10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) private(@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) {
+! CHECK: acc.serial firstprivate(@firstprivatization_section_ext10_ref_10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) private(@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) {
! FIR: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[A]] : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"}
! HLFIR: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#1 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"}
! CHECK: acc.loop private(@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) {
diff --git a/flang/test/Lower/OpenACC/acc-serial.f90 b/flang/test/Lower/OpenACC/acc-serial.f90
index e538cee1407a25f..75d6a7d68588823 100644
--- a/flang/test/Lower/OpenACC/acc-serial.f90
+++ b/flang/test/Lower/OpenACC/acc-serial.f90
@@ -3,7 +3,7 @@
! 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_10x10xf32 : !fir.ref<!fir.array<10x10xf32>> init {
+! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext10xext10_ref_10x10xf32 : !fir.ref<!fir.array<10x10xf32>> init {
! CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.array<10x10xf32>>):
! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10x10xf32>
! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2>
@@ -304,7 +304,7 @@ subroutine acc_serial
! HLFIR: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#1 : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {name = "b"}
! FIR: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[C]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"}
! HLFIR: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[DECLC]]#1 : !fir.ref<!fir.array<10x10xf32>>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<10x10xf32>> {name = "c"}
-! CHECK: acc.serial firstprivate(@firstprivatization_ref_10x10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10x10xf32>>) private(@privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_C]] : !fir.ref<!fir.array<10x10xf32>>) {
+! CHECK: acc.serial firstprivate(@firstprivatization_section_ext10xext10_ref_10x10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10x10xf32>>) private(@privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10x10xf32>>, @privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_C]] : !fir.ref<!fir.array<10x10xf32>>) {
! CHECK: acc.yield
! CHECK-NEXT: }{{$}}
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 69a413305b825e9..7bbbe3f99ad064b 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -458,7 +458,7 @@ LogicalResult acc::FirstprivateRecipeOp::verifyRegions() {
return emitOpError() << "expects non-empty copy region";
Block &firstBlock = getCopyRegion().front();
- if (firstBlock.getNumArguments() != 2 ||
+ if (firstBlock.getNumArguments() < 2 ||
firstBlock.getArgument(0).getType() != getType())
return emitOpError() << "expects copy region with two arguments of the "
"privatization type";
More information about the flang-commits
mailing list