[Mlir-commits] [flang] [mlir] [flang][openacc] support array section privatization in lowering (PR #175184)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Jan 9 07:20:35 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
@llvm/pr-subscribers-mlir
Author: None (jeanPerier)
<details>
<summary>Changes</summary>
Add support array section in private, firstprivate, and reduction.
Key changes:
- Change the related data operation result type to return the same type as the array base (same type as the acc variable input in the operation), while it was the type of the section before. This allows remapping the base the to result value (to use the data operation result as the base when generating addressing inside the compute region).
- The generatePrivateInit implementation of FIROpenACCTypeInterfaces is modified to allocate storage only for the section, and to return the mock base address (that is the address of the allocation minus the offset/lower bound of the privatized section).
- The code generating the copy and combiner region is moved from OpenACC.cpp to FIROpenACCTypeInterfaces.cpp via the addition of new generateCopy and generateCombiner interface in the MappableTypeInterface. This allows sharing all the addressing helper with generatePrivateInit, and will allow late generation of all recipes with Fortran.
- Update generatePrivateDestroy to deallocate the beginning of the section if any.
In the process, the generatePrivateInit implementation is greatly modified so that it is more uniform to make it easier to deal with the section. This also allowed removing runtime calls when initializing the private for array reduction.
Note that all of generatePrivateInit/generateCopy/generateCombiner/generatePrivateDestroy will generate hlfir operations (hlfir.designate) to deal with the sections, making it harder to use these helpers in late stages when HLFIR has already been lowered. I will circle back when there is more need for this late generation.
---
Patch is 261.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/175184.diff
21 Files Affected:
- (modified) flang/include/flang/Lower/OpenACC.h (+8-8)
- (modified) flang/include/flang/Optimizer/Builder/FIRBuilder.h (+1-1)
- (modified) flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h (+16-1)
- (modified) flang/lib/Lower/OpenACC.cpp (+139-374)
- (modified) flang/lib/Optimizer/Builder/FIRBuilder.cpp (+22-11)
- (modified) flang/lib/Optimizer/Builder/HLFIRTools.cpp (+7-6)
- (modified) flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp (+500-137)
- (modified) flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp (+3-9)
- (modified) flang/test/Fir/OpenACC/recipe-populate-firstprivate.mlir (+7-19)
- (modified) flang/test/Fir/OpenACC/recipe-populate-private.mlir (+15-32)
- (modified) flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 (+8-4)
- (modified) flang/test/Lower/OpenACC/acc-firstprivate-derived-user-assign.f90 (+2-4)
- (modified) flang/test/Lower/OpenACC/acc-firstprivate-derived.f90 (+2-4)
- (modified) flang/test/Lower/OpenACC/acc-parallel.f90 (+3-6)
- (modified) flang/test/Lower/OpenACC/acc-private.f90 (+369-228)
- (modified) flang/test/Lower/OpenACC/acc-reduction.f90 (+424-324)
- (modified) flang/test/Lower/OpenACC/acc-serial-loop.f90 (+2-6)
- (modified) flang/test/Lower/OpenACC/acc-serial.f90 (+3-6)
- (modified) flang/test/Transforms/OpenACC/acc-implicit-firstprivate.fir (+9-18)
- (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td (+38-2)
- (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+1-1)
``````````diff
diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index 69f1f5be753e6..c2a950f36c5a7 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -88,23 +88,23 @@ void genOpenACCRoutineConstruct(
/// Get a acc.private.recipe op for the given type or create it if it does not
/// exist yet.
-mlir::acc::PrivateRecipeOp createOrGetPrivateRecipe(fir::FirOpBuilder &,
- llvm::StringRef,
- mlir::Location, mlir::Type);
+mlir::acc::PrivateRecipeOp
+createOrGetPrivateRecipe(fir::FirOpBuilder &, llvm::StringRef, mlir::Location,
+ mlir::Type,
+ llvm::SmallVector<mlir::Value> &dataOperationBounds);
/// Get a acc.reduction.recipe op for the given type or create it if it does not
/// exist yet.
mlir::acc::ReductionRecipeOp
createOrGetReductionRecipe(fir::FirOpBuilder &, llvm::StringRef, mlir::Location,
mlir::Type, mlir::acc::ReductionOperator,
- llvm::SmallVector<mlir::Value> &);
+ llvm::SmallVector<mlir::Value> &dataOperationBounds);
/// Get a acc.firstprivate.recipe op for the given type or create it if it does
/// not exist yet.
-mlir::acc::FirstprivateRecipeOp
-createOrGetFirstprivateRecipe(fir::FirOpBuilder &, llvm::StringRef,
- mlir::Location, mlir::Type,
- llvm::SmallVector<mlir::Value> &);
+mlir::acc::FirstprivateRecipeOp createOrGetFirstprivateRecipe(
+ fir::FirOpBuilder &, llvm::StringRef, mlir::Location, mlir::Type,
+ llvm::SmallVector<mlir::Value> &dataOperationBounds);
void attachDeclarePostAllocAction(AbstractConverter &, fir::FirOpBuilder &,
const Fortran::semantics::Symbol &);
diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index 48a72d73c03bd..c6531ac3d0559 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -576,7 +576,7 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
/// Fortran 2018 9.5.3.3.2 section for more details.
mlir::Value genExtentFromTriplet(mlir::Location loc, mlir::Value lb,
mlir::Value ub, mlir::Value step,
- mlir::Type type);
+ mlir::Type type, bool fold = false);
/// Create an AbsentOp of \p argTy type and handle special cases, such as
/// Character Procedure Tuple arguments.
diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
index 0f133623475f8..9db67afeda5e9 100644
--- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
+++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
@@ -86,7 +86,22 @@ struct OpenACCMappableModel
bool &needsDestroy) const;
bool generatePrivateDestroy(mlir::Type type, mlir::OpBuilder &builder,
- mlir::Location loc, mlir::Value privatized) const;
+ mlir::Location loc, mlir::Value privatized,
+ mlir::ValueRange bounds) const;
+
+ bool generateCopy(mlir::Type type, mlir::OpBuilder &mlirBuilder,
+ mlir::Location loc,
+ mlir::TypedValue<mlir::acc::MappableType> source,
+ mlir::TypedValue<mlir::acc::MappableType> dest,
+ mlir::ValueRange bounds) const;
+
+ bool generateCombiner(mlir::Type type, mlir::OpBuilder &mlirBuilder,
+ mlir::Location loc,
+ mlir::TypedValue<mlir::acc::MappableType> dest,
+ mlir::TypedValue<mlir::acc::MappableType> source,
+ mlir::ValueRange bounds,
+ mlir::acc::ReductionOperator op,
+ mlir::Attribute fastmathFlags) const;
};
} // namespace fir::acc
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 52fee7baf9de1..0bd2024a3b29b 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -27,14 +27,17 @@
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include "flang/Optimizer/Builder/IntrinsicCall.h"
#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h"
+#include "flang/Optimizer/Support/Utils.h"
#include "flang/Parser/parse-tree-visitor.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Parser/tools.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/scope.h"
#include "flang/Semantics/tools.h"
+#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
#include "mlir/Dialect/OpenACC/OpenACCUtils.h"
#include "mlir/IR/IRMapping.h"
@@ -643,54 +646,19 @@ void genAtomicCapture(Fortran::lower::AbstractConverter &converter,
firOpBuilder.setInsertionPointAfter(atomicCaptureOp);
}
-/// Rebuild the array type from the acc.bounds operation with constant
-/// lowerbound/upperbound or extent.
-static mlir::Type getTypeFromBounds(llvm::SmallVector<mlir::Value> &bounds,
- mlir::Type ty) {
- auto seqTy =
- mlir::dyn_cast_or_null<fir::SequenceType>(fir::unwrapRefType(ty));
- if (!bounds.empty() && seqTy) {
- llvm::SmallVector<int64_t> shape;
- for (auto b : bounds) {
- auto boundsOp =
- mlir::dyn_cast<mlir::acc::DataBoundsOp>(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<fir::ReferenceType, fir::PointerType>(ty))
- return fir::ReferenceType::get(newSeqTy);
- return newSeqTy;
- }
- return ty;
-}
-
static mlir::SymbolRefAttr
createOrGetRecipe(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::acc::RecipeKind kind, mlir::Value addr,
llvm::SmallVector<mlir::Value> &bounds) {
- mlir::Type ty = getTypeFromBounds(bounds, addr.getType());
+ mlir::Type ty = addr.getType();
// Compute the canonical recipe name for the given kind, type, address and
// bounds so that recipes are shared wherever possible.
std::string recipeName = fir::acc::getRecipeName(kind, ty, addr, bounds);
switch (kind) {
case mlir::acc::RecipeKind::private_recipe: {
- auto recipe =
- Fortran::lower::createOrGetPrivateRecipe(builder, recipeName, loc, ty);
+ auto recipe = Fortran::lower::createOrGetPrivateRecipe(builder, recipeName,
+ loc, ty, bounds);
return mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName());
}
case mlir::acc::RecipeKind::firstprivate_recipe: {
@@ -788,6 +756,9 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
dataRef->u);
}
+ bool isPrivate = std::is_same_v<Op, mlir::acc::PrivateOp> ||
+ std::is_same_v<Op, mlir::acc::FirstprivateOp>;
+
fir::factory::AddrAndBoundsInfo info =
Fortran::lower::gatherDataOperandAddrAndBounds<
mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
@@ -804,8 +775,6 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
// For privatization, absent OPTIONAL are illegal as per OpenACC 3.3
// section 2.17.1 and the descriptor must be used to drive the creation of
// the temporary and the copy.
- bool isPrivate = std::is_same_v<Op, mlir::acc::PrivateOp> ||
- std::is_same_v<Op, mlir::acc::FirstprivateOp>;
mlir::Value baseAddr = (!isPrivate &&
(fir::unwrapRefType(info.addr.getType()) !=
fir::unwrapRefType(info.rawInput.getType())) &&
@@ -813,17 +782,9 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
? info.rawInput
: info.addr;
- // TODO: update privatization of array section to return the base
- // address and update the recipe generation to "offset back" the returned
- // address. Then it will be possible to remap them like in other cases.
- bool isPrivateArraySection = isPrivate && !bounds.empty();
- mlir::Type resTy = isPrivateArraySection
- ? getTypeFromBounds(bounds, baseAddr.getType())
- : baseAddr.getType();
-
Op op = createDataEntryOp<Op>(
builder, operandLocation, baseAddr, asFortran, bounds, structured,
- implicit, dataClause, resTy, async, asyncDeviceTypes,
+ implicit, dataClause, baseAddr.getType(), async, asyncDeviceTypes,
asyncOnlyDeviceTypes, unwrapBoxAddr, info.isPresent);
dataOperands.push_back(op.getAccVar());
@@ -841,7 +802,7 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
// Track the symbol and its corresponding mlir::Value if requested so that
// accesses inside regions can be remapped.
- if (dataMap && !isPrivateArraySection && !isNoCreateWithBounds) {
+ if (dataMap && !isNoCreateWithBounds) {
if (componentRef)
dataMap->emplaceComponent(op.getAccVar(), std::move(*componentRef),
baseAddr);
@@ -1081,16 +1042,6 @@ genDataExitOperations(fir::FirOpBuilder &builder,
}
}
-fir::ShapeOp genShapeOp(mlir::OpBuilder &builder, fir::SequenceType seqTy,
- mlir::Location loc) {
- llvm::SmallVector<mlir::Value> extents;
- mlir::Type idxTy = builder.getIndexType();
- for (auto extent : seqTy.getShape())
- extents.push_back(mlir::arith::ConstantOp::create(
- builder, loc, idxTy, builder.getIntegerAttr(idxTy, extent)));
- return fir::ShapeOp::create(builder, loc, extents);
-}
-
/// Get the initial value for reduction operator.
template <typename R>
static R getReductionInitValue(mlir::acc::ReductionOperator op, mlir::Type ty) {
@@ -1204,10 +1155,71 @@ static mlir::Value getReductionInitValue(fir::FirOpBuilder &builder,
llvm::report_fatal_error("Unsupported OpenACC reduction type");
}
+static llvm::SmallVector<mlir::Value>
+getRecipeBounds(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::ValueRange dataBoundOps,
+ mlir::ValueRange blockBoundArgs) {
+ if (dataBoundOps.empty())
+ return {};
+ mlir::Type idxTy = builder.getIndexType();
+ mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
+ llvm::SmallVector<mlir::Value> bounds;
+ if (!blockBoundArgs.empty()) {
+ for (unsigned i = 0; i + 2 < blockBoundArgs.size(); i += 3) {
+ bounds.push_back(blockBoundArgs[i]);
+ bounds.push_back(blockBoundArgs[i + 1]);
+ // acc data bound strides is the inner size in bytes or elements, but
+ // sections are always 1-based, so there is no need to try to compute
+ // that back from the acc bounds.
+ bounds.push_back(one);
+ }
+ return bounds;
+ }
+ for (auto bound : dataBoundOps) {
+ auto dataBound = llvm::dyn_cast_if_present<mlir::acc::DataBoundsOp>(
+ bound.getDefiningOp());
+ assert(dataBound && "expect acc bounds to be produced by DataBoundsOp");
+ assert(
+ dataBound.getLowerbound() && dataBound.getUpperbound() &&
+ "expect acc bounds for Fortran to always have lower and upper bounds");
+ std::optional<std::int64_t> lb =
+ fir::getIntIfConstant(dataBound.getLowerbound());
+ std::optional<std::int64_t> ub =
+ fir::getIntIfConstant(dataBound.getUpperbound());
+ assert(lb.has_value() && ub.has_value() &&
+ "must get constant bounds when there are no bound block arguments");
+ bounds.push_back(builder.createIntegerConstant(loc, idxTy, *lb));
+ bounds.push_back(builder.createIntegerConstant(loc, idxTy, *ub));
+ bounds.push_back(one);
+ }
+ return bounds;
+}
+
+static void addRecipeBoundsArgs(llvm::SmallVector<mlir::Value> &bounds,
+ bool allConstantBound,
+ llvm::SmallVector<mlir::Type> &argsTy,
+ llvm::SmallVector<mlir::Location> &argsLoc) {
+ 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());
+ }
+ }
+}
+
+using MappableValue = mlir::TypedValue<mlir::acc::MappableType>;
+
template <typename RecipeOp>
static RecipeOp genRecipeOp(
fir::FirOpBuilder &builder, mlir::ModuleOp mod, llvm::StringRef recipeName,
mlir::Location loc, mlir::Type ty,
+ llvm::SmallVector<mlir::Value> &dataOperationBounds, bool allConstantBound,
mlir::acc::ReductionOperator op = mlir::acc::ReductionOperator::AccNone) {
mlir::OpBuilder modBuilder(mod.getBodyRegion());
RecipeOp recipe;
@@ -1218,20 +1230,13 @@ static RecipeOp genRecipeOp(
recipe = RecipeOp::create(modBuilder, loc, recipeName, ty);
}
+ assert(hlfir::isFortranVariableType(ty) && "expect Fortran variable type");
+
llvm::SmallVector<mlir::Type> argsTy{ty};
llvm::SmallVector<mlir::Location> argsLoc{loc};
- if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(ty)) {
- if (auto seqTy =
- mlir::dyn_cast_or_null<fir::SequenceType>(refTy.getEleTy())) {
- if (seqTy.hasDynamicExtents()) {
- mlir::Type idxTy = builder.getIndexType();
- for (unsigned i = 0; i < seqTy.getDimension(); ++i) {
- argsTy.push_back(idxTy);
- argsLoc.push_back(loc);
- }
- }
- }
- }
+ if (!dataOperationBounds.empty())
+ addRecipeBoundsArgs(dataOperationBounds, allConstantBound, argsTy, argsLoc);
+
auto initBlock = builder.createBlock(
&recipe.getInitRegion(), recipe.getInitRegion().end(), argsTy, argsLoc);
builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
@@ -1253,15 +1258,13 @@ static RecipeOp genRecipeOp(
assert(mappableTy &&
"Expected that all variable types are considered mappable");
bool needsDestroy = false;
- auto retVal = mappableTy.generatePrivateInit(
- builder, loc,
- mlir::cast<mlir::TypedValue<mlir::acc::MappableType>>(
- initBlock->getArgument(0)),
- initName,
- initBlock->getArguments().take_back(initBlock->getArguments().size() - 1),
- initValue, needsDestroy);
- mlir::acc::YieldOp::create(builder, loc,
- retVal ? retVal : initBlock->getArgument(0));
+ llvm::SmallVector<mlir::Value> initBounds =
+ getRecipeBounds(builder, loc, dataOperationBounds,
+ initBlock->getArguments().drop_front(1));
+ mlir::Value retVal = mappableTy.generatePrivateInit(
+ builder, loc, mlir::cast<MappableValue>(initBlock->getArgument(0)),
+ initName, initBounds, initValue, needsDestroy);
+ mlir::acc::YieldOp::create(builder, loc, retVal);
// Create destroy region and generate destruction if requested.
if (needsDestroy) {
llvm::SmallVector<mlir::Type> destroyArgsTy;
@@ -1277,189 +1280,59 @@ static RecipeOp genRecipeOp(
destroyArgsLoc.insert(destroyArgsLoc.end(), argsTy.size() - 1, loc);
}
- builder.createBlock(&recipe.getDestroyRegion(),
- recipe.getDestroyRegion().end(), destroyArgsTy,
- destroyArgsLoc);
- builder.setInsertionPointToEnd(&recipe.getDestroyRegion().back());
- // Call interface on the privatized/reduction value (2nd argument).
- (void)mappableTy.generatePrivateDestroy(
- builder, loc, recipe.getDestroyRegion().front().getArgument(1));
+ mlir::Block *destroyBlock = builder.createBlock(
+ &recipe.getDestroyRegion(), recipe.getDestroyRegion().end(),
+ destroyArgsTy, destroyArgsLoc);
+ builder.setInsertionPointToEnd(destroyBlock);
+
+ llvm::SmallVector<mlir::Value> destroyBounds =
+ getRecipeBounds(builder, loc, dataOperationBounds,
+ destroyBlock->getArguments().drop_front(2));
+ [[maybe_unused]] bool success = mappableTy.generatePrivateDestroy(
+ builder, loc, destroyBlock->getArgument(1), destroyBounds);
+ assert(success && "failed to generate destroy region");
mlir::acc::TerminatorOp::create(builder, loc);
}
return recipe;
}
-mlir::acc::PrivateRecipeOp
-Fortran::lower::createOrGetPrivateRecipe(fir::FirOpBuilder &builder,
- llvm::StringRef recipeName,
- mlir::Location loc, mlir::Type ty) {
+mlir::acc::PrivateRecipeOp Fortran::lower::createOrGetPrivateRecipe(
+ fir::FirOpBuilder &builder, llvm::StringRef recipeName, mlir::Location loc,
+ mlir::Type ty, llvm::SmallVector<mlir::Value> &bounds) {
mlir::ModuleOp mod =
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
if (auto recipe = mod.lookupSymbol<mlir::acc::PrivateRecipeOp>(recipeName))
return recipe;
auto ip = builder.saveInsertionPoint();
- auto recipe = genRecipeOp<mlir::acc::PrivateRecipeOp>(builder, mod,
- recipeName, loc, ty);
+ bool allConstantBound = fir::acc::areAllBoundsConstant(bounds);
+ auto recipe = genRecipeOp<mlir::acc::PrivateRecipeOp>(
+ builder, mod, recipeName, loc, ty, bounds, allConstantBound);
builder.restoreInsertionPoint(ip);
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;
-}
-
-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 hlfir::Entity genDesignateWithTriplets(...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/175184
More information about the Mlir-commits
mailing list