[flang-commits] [flang] [flang][acc] Implement cache directive lowering (PR #174897)
Razvan Lupusoru via flang-commits
flang-commits at lists.llvm.org
Thu Jan 8 09:58:14 PST 2026
================
@@ -4837,12 +4837,180 @@ genACC(Fortran::lower::AbstractConverter &converter,
atomicConstruct.u);
}
+/// Generate acc.bounds for cache directive. Handles:
+/// - Single element: arr(i) or arr(5)
+/// - Full range: arr(lower:upper)
+/// - Missing upper: arr(lower:) - uses array's upper bound
+/// - Missing lower: arr(:upper) - uses array's lower bound
+static void
+genCacheBounds(Fortran::lower::AbstractConverter &converter,
+ Fortran::semantics::SemanticsContext &semanticsContext,
+ Fortran::lower::StatementContext &stmtCtx,
+ const Fortran::parser::AccObject &accObject,
+ std::stringstream &asFortran,
+ llvm::SmallVectorImpl<mlir::Value> &bounds) {
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+ mlir::Location loc = converter.getCurrentLocation();
+ mlir::Type idxTy = builder.getIndexType();
+ mlir::Type boundTy = builder.getType<mlir::acc::DataBoundsType>();
+
+ Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
+ Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
+
+ std::optional<Fortran::evaluate::DataRef> dataRef;
+ Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
+ [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
+ if (designator)
+ dataRef = Fortran::evaluate::ExtractDataRef(*designator);
+
+ if (!dataRef)
+ return;
+
+ auto *arrayRef = std::get_if<Fortran::evaluate::ArrayRef>(&dataRef->u);
+ if (!arrayRef)
+ return;
+
+ // Helper to generate index value from expression.
+ // Optimize for compile-time constants to generate index type directly.
+ auto genIndex =
+ [&](const Fortran::semantics::MaybeExpr &expr) -> mlir::Value {
+ if (auto constVal = Fortran::evaluate::ToInt64(*expr))
+ return builder.createIntegerConstant(loc, idxTy, *constVal);
+ return builder.createConvert(
+ loc, idxTy, fir::getBase(converter.genExprValue(loc, *expr, stmtCtx)));
+ };
+
+ const auto &subscripts = arrayRef->subscript();
+ int dimension = 0;
+ mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
+ fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(symbol);
+
+ for (const auto &subscript : subscripts) {
+ if (dimension != 0)
+ asFortran << ',';
+
+ mlir::Value lbound, extent;
+ mlir::Value arrayLb =
+ fir::factory::readLowerBound(builder, loc, dataExv, dimension, one);
+ mlir::Value arrayExtent =
+ fir::factory::readExtent(builder, loc, dataExv, dimension);
+
+ const auto *triplet = std::get_if<Fortran::evaluate::Triplet>(&subscript.u);
+
+ if (triplet) {
+ asFortran << ':';
+
+ // OpenACC spec requires at least one of lower or upper bound to be
+ // specified: arr(lower:upper), arr(lower:), or arr(:upper).
+ // arr(:) with both bounds missing is not allowed.
+ Fortran::semantics::MaybeExpr lowerExpr =
+ Fortran::evaluate::AsGenericExpr(triplet->lower());
+ Fortran::semantics::MaybeExpr upperExpr =
+ Fortran::evaluate::AsGenericExpr(triplet->upper());
+
+ if (!lowerExpr && !upperExpr) {
+ llvm::report_fatal_error("OpenACC cache directive requires at least "
+ "one bound to be specified for array section");
+ }
+
+ // OpenACC cache only supports unit stride (default or explicit 1).
+ auto strideVal = Fortran::evaluate::ToInt64(triplet->stride());
+ if (!strideVal || *strideVal != 1) {
+ llvm::report_fatal_error("OpenACC cache directive does not support "
+ "strided array sections");
+ }
+
+ // Compute lower bound (use array lb if not specified).
+ mlir::Value lb = lowerExpr ? genIndex(lowerExpr) : arrayLb;
+
+ // Compute upper bound (use array ub if not specified).
+ mlir::Value ub;
+ if (upperExpr) {
+ ub = genIndex(upperExpr);
+ } else {
+ // arr(lower:) - upper is array's upper bound
+ ub = mlir::arith::AddIOp::create(
+ builder, loc,
+ mlir::arith::SubIOp::create(builder, loc, arrayLb, one),
+ arrayExtent);
+ }
+
+ // Normalize to zero-based and compute extent.
+ lbound = mlir::arith::SubIOp::create(builder, loc, lb, arrayLb);
+ mlir::Value ubound =
+ mlir::arith::SubIOp::create(builder, loc, ub, arrayLb);
+ extent = mlir::arith::AddIOp::create(
+ builder, loc,
+ mlir::arith::SubIOp::create(builder, loc, ubound, lbound), one);
+ } else {
+ // Single element: arr(elem)
+ Fortran::evaluate::Expr<Fortran::evaluate::SubscriptInteger> scalarExpr =
+ std::get<Fortran::evaluate::IndirectSubscriptIntegerExpr>(subscript.u)
+ .value();
+ Fortran::semantics::MaybeExpr elemExpr =
+ Fortran::evaluate::AsGenericExpr(std::move(scalarExpr));
+ mlir::Value elem = genIndex(elemExpr);
+
+ lbound = mlir::arith::SubIOp::create(builder, loc, elem, arrayLb);
+ extent = one;
+ }
+
+ mlir::Value bound = mlir::acc::DataBoundsOp::create(
+ builder, loc, boundTy, lbound, /*upperbound=*/mlir::Value{}, extent,
+ /*stride=*/one, /*strideInBytes=*/false, arrayLb);
+ bounds.push_back(bound);
+ ++dimension;
+ }
+}
+
static void
genACC(Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semanticsContext,
const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) {
- mlir::Location loc = converter.genLocation(cacheConstruct.source);
- TODO(loc, "OpenACC cache directive");
+ const auto &objectListWithModifier =
+ std::get<Fortran::parser::AccObjectListWithModifier>(cacheConstruct.t);
+ const auto &accObjectList =
+ std::get<Fortran::parser::AccObjectList>(objectListWithModifier.t);
+ const auto &modifier =
+ std::get<std::optional<Fortran::parser::AccDataModifier>>(
+ objectListWithModifier.t);
+ mlir::acc::DataClause dataClause =
+ (modifier &&
+ (*modifier).v == Fortran::parser::AccDataModifier::Modifier::ReadOnly)
----------------
razvanlupusoru wrote:
The acc dialect was updated a few months back for OpenACC 3.4 standard - and now data clause operations (eg. acc.copyin) also have a `modifiers` attribute. Let's update that one as well as it will help our transition from encoding the modifiers in the dataClause to the modifiers attribute. I understand that the lowering of the other data operations may lag - but might as well do this for `cache`.
https://github.com/llvm/llvm-project/pull/174897
More information about the flang-commits
mailing list