diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -350,12 +350,15 @@ static Op createDataEntryOp(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value baseAddr, std::stringstream &name, mlir::SmallVector bounds, - bool structured, mlir::acc::DataClause dataClause) { + bool structured, mlir::acc::DataClause dataClause, + mlir::Type retTy) { mlir::Value varPtrPtr; - if (auto boxTy = baseAddr.getType().dyn_cast()) + if (auto boxTy = baseAddr.getType().dyn_cast()) { baseAddr = builder.create(loc, baseAddr); + retTy = baseAddr.getType(); + } - Op op = builder.create(loc, baseAddr.getType(), baseAddr); + Op op = builder.create(loc, retTy, baseAddr); op.setNameAttr(builder.getStringAttr(name.str())); op.setStructured(structured); op.setDataClause(dataClause); @@ -388,7 +391,8 @@ converter, builder, semanticsContext, stmtCtx, accObject, operandLocation, asFortran, bounds); Op op = createDataEntryOp(builder, operandLocation, baseAddr, asFortran, - bounds, structured, dataClause); + bounds, structured, dataClause, + baseAddr.getType()); dataOperands.push_back(op.getAccPtr()); } } @@ -474,6 +478,41 @@ return recipe; } +/// Rebuild the array type from the acc.bounds operation with constant +/// lowerbound/upperbound or extent. +mlir::Type getTypeFromBounds(llvm::SmallVector &bounds, + mlir::Type ty) { + auto seqTy = + mlir::dyn_cast_or_null(fir::unwrapRefType(ty)); + if (!bounds.empty() && seqTy) { + llvm::SmallVector shape; + for (auto b : bounds) { + auto boundsOp = + mlir::dyn_cast(b.getDefiningOp()); + if (boundsOp.getLowerbound() && + fir::getIntIfConstant(boundsOp.getLowerbound()) && + boundsOp.getUpperbound() && + fir::getIntIfConstant(boundsOp.getUpperbound())) { + int64_t ext = *fir::getIntIfConstant(boundsOp.getUpperbound()) - + *fir::getIntIfConstant(boundsOp.getLowerbound()) + 1; + shape.push_back(ext); + } else if (boundsOp.getExtent() && + fir::getIntIfConstant(boundsOp.getExtent())) { + shape.push_back(*fir::getIntIfConstant(boundsOp.getExtent())); + } else { + return ty; // TODO: handle dynamic shaped array slice. + } + } + if (shape.empty() || shape.size() != bounds.size()) + return ty; + auto newSeqTy = fir::SequenceType::get(shape, seqTy.getEleTy()); + if (mlir::isa(ty)) + return fir::ReferenceType::get(newSeqTy); + return newSeqTy; + } + return ty; +} + template static void genPrivatizations(const Fortran::parser::AccObjectList &objectList, @@ -493,13 +532,14 @@ RecipeOp recipe; if constexpr (std::is_same_v) { - std::string recipeName = fir::getTypeAsString( - baseAddr.getType(), converter.getKindMap(), "privatization"); - recipe = Fortran::lower::createOrGetPrivateRecipe( - builder, recipeName, operandLocation, baseAddr.getType()); + mlir::Type retTy = getTypeFromBounds(bounds, baseAddr.getType()); + std::string recipeName = + fir::getTypeAsString(retTy, converter.getKindMap(), "privatization"); + recipe = Fortran::lower::createOrGetPrivateRecipe(builder, recipeName, + operandLocation, retTy); auto op = createDataEntryOp( builder, operandLocation, baseAddr, asFortran, bounds, true, - mlir::acc::DataClause::acc_private); + mlir::acc::DataClause::acc_private, retTy); dataOperands.push_back(op.getAccPtr()); } else { std::string recipeName = fir::getTypeAsString( @@ -508,7 +548,7 @@ builder, recipeName, operandLocation, baseAddr.getType()); auto op = createDataEntryOp( builder, operandLocation, baseAddr, asFortran, bounds, true, - mlir::acc::DataClause::acc_firstprivate); + mlir::acc::DataClause::acc_firstprivate, baseAddr.getType()); dataOperands.push_back(op.getAccPtr()); } privatizations.push_back(mlir::SymbolRefAttr::get( @@ -766,7 +806,8 @@ auto op = createDataEntryOp( builder, operandLocation, baseAddr, asFortran, bounds, - /*structured=*/true, mlir::acc::DataClause::acc_reduction); + /*structured=*/true, mlir::acc::DataClause::acc_reduction, + baseAddr.getType()); mlir::Type ty = fir::unwrapRefType(op.getAccPtr().getType()); if (!fir::isa_trivial(ty)) ty = baseAddr.getType(); diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -2,6 +2,12 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s +! CHECK-LABEL: acc.private.recipe @privatization_ref_50xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<50xf32> +! CHECK: acc.yield %[[ALLOCA]] : !fir.ref> +! CHECK: } + ! CHECK-LABEL: acc.private.recipe @privatization_ref_100xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): ! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> @@ -44,5 +50,20 @@ ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) ! CHECK: %[[B_PRIVATE:.*]] = acc.private varPtr(%[[B]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b"} ! CHECK: acc.loop private(@privatization_ref_100xf32 -> %[[B_PRIVATE]] : !fir.ref>) { +! CHECK: acc.yield + + !$acc loop private(b(1:50)) + DO i = 1, n + c = i + a(i) = b(i) + c + END DO + +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.constant 49 : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[B_PRIVATE:.*]] = acc.private varPtr(%[[B]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b(1:50)"} +! CHECK: acc.loop private(@privatization_ref_50xf32 -> %[[B_PRIVATE]] : !fir.ref>) + end program