[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:13 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 "
----------------
razvanlupusoru wrote:
Would be better to catch in semantics.
https://github.com/llvm/llvm-project/pull/174897
More information about the flang-commits
mailing list