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 <clement...@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"; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits