[flang-commits] [flang] 01a0d21 - [flang][acc] Implement MappableType interfaces for fir.box and fir.array (#122495)
via flang-commits
flang-commits at lists.llvm.org
Tue Jan 14 10:43:00 PST 2025
Author: Razvan Lupusoru
Date: 2025-01-14T10:42:57-08:00
New Revision: 01a0d212a64919205734706d929db37e503c35ce
URL: https://github.com/llvm/llvm-project/commit/01a0d212a64919205734706d929db37e503c35ce
DIFF: https://github.com/llvm/llvm-project/commit/01a0d212a64919205734706d929db37e503c35ce.diff
LOG: [flang][acc] Implement MappableType interfaces for fir.box and fir.array (#122495)
The newly introduced MappableType interface in `acc` dialect was
primarily intended to allow variables with non-materialized storage to
be used in acc data clauses (previously everything was required to be
`pointer-like`). One motivator for this was `fir.box` since it is
possible to be passed to functions without a wrapping `fir.ref` and also
it can be generated directly via operations like `fir.embox` - and
unlike other variable representations in FIR, the underlying storage for
it does not get materialized until LLVM codegen.
The new interface is being attached to both `fir.box` and `fir.array`.
Strictly speaking, attaching to the latter is primarily for consistency
since the MappableType interface requires implementation of utilities to
compute byte size - and it made sense that a
`fir.box<fir.array<10xi32>>` and `fir.array<10xi32>` would have a
consistently computable size. This decision may be revisited as
MappableType interface evolves.
The new interface attachments are made in a new library named
`FIROpenACCSupport`. The reason for this is to avoid circular
dependencies since the implementation of this library is reusing code
from lowering of OpenACC. More specifically, the types are defined in
`FIRDialect` and `FortranLower` depends on it. Thus we cannot attach
these interfaces in `FIRDialect`.
Added:
flang/include/flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h
flang/include/flang/Optimizer/OpenACC/RegisterOpenACCExtensions.h
flang/lib/Optimizer/OpenACC/CMakeLists.txt
flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp
flang/lib/Optimizer/OpenACC/RegisterOpenACCExtensions.cpp
flang/test/Fir/OpenACC/openacc-mappable.fir
flang/test/lib/OpenACC/CMakeLists.txt
flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp
Modified:
flang/include/flang/Optimizer/Support/InitFIR.h
flang/lib/Frontend/CMakeLists.txt
flang/lib/Optimizer/CMakeLists.txt
flang/lib/Optimizer/Dialect/CMakeLists.txt
flang/test/lib/CMakeLists.txt
flang/tools/fir-lsp-server/CMakeLists.txt
flang/tools/fir-opt/CMakeLists.txt
flang/tools/fir-opt/fir-opt.cpp
flang/tools/tco/CMakeLists.txt
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h b/flang/include/flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h
new file mode 100644
index 00000000000000..c1bea32a22361d
--- /dev/null
+++ b/flang/include/flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h
@@ -0,0 +1,43 @@
+//===- FIROpenACCTypeInterfaces.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains external dialect interfaces for FIR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FLANG_OPTIMIZER_OPENACC_FIROPENACCTYPEINTERFACES_H_
+#define FLANG_OPTIMIZER_OPENACC_FIROPENACCTYPEINTERFACES_H_
+
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+
+namespace fir::acc {
+
+template <typename T>
+struct OpenACCMappableModel
+ : public mlir::acc::MappableType::ExternalModel<OpenACCMappableModel<T>,
+ T> {
+ mlir::TypedValue<mlir::acc::PointerLikeType> getVarPtr(::mlir::Type type,
+ mlir::Value var) const;
+
+ std::optional<llvm::TypeSize>
+ getSizeInBytes(mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
+ const mlir::DataLayout &dataLayout) const;
+
+ std::optional<int64_t>
+ getOffsetInBytes(mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
+ const mlir::DataLayout &dataLayout) const;
+
+ llvm::SmallVector<mlir::Value>
+ generateAccBounds(mlir::Type type, mlir::Value var,
+ mlir::OpBuilder &builder) const;
+};
+
+} // namespace fir::acc
+
+#endif // FLANG_OPTIMIZER_OPENACC_FIROPENACCTYPEINTERFACES_H_
diff --git a/flang/include/flang/Optimizer/OpenACC/RegisterOpenACCExtensions.h b/flang/include/flang/Optimizer/OpenACC/RegisterOpenACCExtensions.h
new file mode 100644
index 00000000000000..efaddd72ebbf2b
--- /dev/null
+++ b/flang/include/flang/Optimizer/OpenACC/RegisterOpenACCExtensions.h
@@ -0,0 +1,22 @@
+//===- RegisterOpenACCExtensions.h - OpenACC Extension Registration --===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FLANG_OPTIMIZER_OPENACC_REGISTEROPENACCEXTENSIONS_H_
+#define FLANG_OPTIMIZER_OPENACC_REGISTEROPENACCEXTENSIONS_H_
+
+namespace mlir {
+class DialectRegistry;
+} // namespace mlir
+
+namespace fir::acc {
+
+void registerOpenACCExtensions(mlir::DialectRegistry ®istry);
+
+} // namespace fir::acc
+
+#endif // FLANG_OPTIMIZER_OPENACC_REGISTEROPENACCEXTENSIONS_H_
diff --git a/flang/include/flang/Optimizer/Support/InitFIR.h b/flang/include/flang/Optimizer/Support/InitFIR.h
index 1c61c367199923..94995ac6136edd 100644
--- a/flang/include/flang/Optimizer/Support/InitFIR.h
+++ b/flang/include/flang/Optimizer/Support/InitFIR.h
@@ -17,6 +17,7 @@
#include "flang/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
+#include "flang/Optimizer/OpenACC/RegisterOpenACCExtensions.h"
#include "mlir/Conversion/Passes.h"
#include "mlir/Dialect/Affine/Passes.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
@@ -63,6 +64,7 @@ inline void addFIRExtensions(mlir::DialectRegistry ®istry,
addFIRInlinerExtension(registry);
addFIRToLLVMIRExtension(registry);
cuf::registerCUFDialectTranslation(registry);
+ fir::acc::registerOpenACCExtensions(registry);
}
inline void loadNonCodegenDialects(mlir::MLIRContext &context) {
diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index 1b90fe826af6c9..0a0482505b747e 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -39,6 +39,7 @@ add_flang_library(flangFrontend
HLFIRDialect
HLFIRTransforms
flangPasses
+ FIROpenACCSupport
FlangOpenMPTransforms
MLIRTransforms
MLIRBuiltinToLLVMIRTranslation
diff --git a/flang/lib/Optimizer/CMakeLists.txt b/flang/lib/Optimizer/CMakeLists.txt
index 5354d7181e6516..72aba51b858708 100644
--- a/flang/lib/Optimizer/CMakeLists.txt
+++ b/flang/lib/Optimizer/CMakeLists.txt
@@ -3,6 +3,7 @@ add_subdirectory(Builder)
add_subdirectory(CodeGen)
add_subdirectory(Dialect)
add_subdirectory(HLFIR)
+add_subdirectory(OpenACC)
add_subdirectory(OpenMP)
add_subdirectory(Passes)
add_subdirectory(Support)
diff --git a/flang/lib/Optimizer/Dialect/CMakeLists.txt b/flang/lib/Optimizer/Dialect/CMakeLists.txt
index a8235f841b879d..08caa15700d4ca 100644
--- a/flang/lib/Optimizer/Dialect/CMakeLists.txt
+++ b/flang/lib/Optimizer/Dialect/CMakeLists.txt
@@ -6,8 +6,8 @@ add_flang_library(FIRDialect
FIRDialect.cpp
FIROps.cpp
FIRType.cpp
- FortranVariableInterface.cpp
FirAliasTagOpInterface.cpp
+ FortranVariableInterface.cpp
Inliner.cpp
DEPENDS
diff --git a/flang/lib/Optimizer/OpenACC/CMakeLists.txt b/flang/lib/Optimizer/OpenACC/CMakeLists.txt
new file mode 100644
index 00000000000000..ed673121353c16
--- /dev/null
+++ b/flang/lib/Optimizer/OpenACC/CMakeLists.txt
@@ -0,0 +1,22 @@
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_flang_library(FIROpenACCSupport
+ FIROpenACCTypeInterfaces.cpp
+ RegisterOpenACCExtensions.cpp
+
+ DEPENDS
+ FIRBuilder
+ FIRDialect
+ FIRDialectSupport
+ FIRSupport
+ HLFIRDialect
+ MLIROpenACCDialect
+
+ LINK_LIBS
+ FIRBuilder
+ FIRDialect
+ FIRDialectSupport
+ FIRSupport
+ HLFIRDialect
+ MLIROpenACCDialect
+)
diff --git a/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp b/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp
new file mode 100644
index 00000000000000..e6a484923c7060
--- /dev/null
+++ b/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp
@@ -0,0 +1,227 @@
+//===-- FIROpenACCTypeInterfaces.cpp --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of external dialect interfaces for FIR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h"
+#include "flang/Lower/DirectivesCommon.h"
+#include "flang/Optimizer/Builder/BoxValue.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/HLFIRTools.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/FIROpsSupport.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/Dialect/Support/FIRContext.h"
+#include "flang/Optimizer/Dialect/Support/KindMapping.h"
+#include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/Support/LLVM.h"
+
+namespace fir::acc {
+
+static mlir::TypedValue<mlir::acc::PointerLikeType>
+getPtrFromVar(mlir::Value var) {
+ if (auto ptr =
+ mlir::dyn_cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(var))
+ return ptr;
+
+ if (auto load = mlir::dyn_cast_if_present<fir::LoadOp>(var.getDefiningOp())) {
+ // All FIR reference types implement the PointerLikeType interface.
+ return mlir::cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(
+ load.getMemref());
+ }
+
+ return {};
+}
+
+template <>
+mlir::TypedValue<mlir::acc::PointerLikeType>
+OpenACCMappableModel<fir::SequenceType>::getVarPtr(mlir::Type type,
+ mlir::Value var) const {
+ return getPtrFromVar(var);
+}
+
+template <>
+mlir::TypedValue<mlir::acc::PointerLikeType>
+OpenACCMappableModel<fir::BaseBoxType>::getVarPtr(mlir::Type type,
+ mlir::Value var) const {
+ return getPtrFromVar(var);
+}
+
+template <>
+std::optional<llvm::TypeSize>
+OpenACCMappableModel<fir::SequenceType>::getSizeInBytes(
+ mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
+ const mlir::DataLayout &dataLayout) const {
+ // TODO: Bounds operation affect the total size - add support to take them
+ // into account.
+ if (!accBounds.empty())
+ return {};
+
+ // Dynamic extents or unknown ranks generally do not have compile-time
+ // computable dimensions.
+ auto seqType = mlir::cast<fir::SequenceType>(type);
+ if (seqType.hasDynamicExtents() || seqType.hasUnknownShape())
+ return {};
+
+ // Attempt to find an operation that a lookup for KindMapping can be done
+ // from.
+ mlir::Operation *kindMapSrcOp = var.getDefiningOp();
+ if (!kindMapSrcOp) {
+ kindMapSrcOp = var.getParentRegion()->getParentOp();
+ if (!kindMapSrcOp)
+ return {};
+ }
+ auto kindMap = fir::getKindMapping(kindMapSrcOp);
+
+ auto sizeAndAlignment =
+ fir::getTypeSizeAndAlignment(var.getLoc(), type, dataLayout, kindMap);
+ if (!sizeAndAlignment.has_value())
+ return {};
+
+ return {llvm::TypeSize::getFixed(sizeAndAlignment->first)};
+}
+
+template <>
+std::optional<llvm::TypeSize>
+OpenACCMappableModel<fir::BaseBoxType>::getSizeInBytes(
+ mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
+ const mlir::DataLayout &dataLayout) const {
+ // If we have a box value instead of box reference, the intent is to
+ // get the size of the data not the box itself.
+ if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(var.getType())) {
+ if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(
+ fir::unwrapRefType(boxTy.getEleTy()))) {
+ return mappableTy.getSizeInBytes(var, accBounds, dataLayout);
+ }
+ }
+ // Size for boxes is not computable until it gets materialized.
+ return {};
+}
+
+template <>
+std::optional<int64_t>
+OpenACCMappableModel<fir::SequenceType>::getOffsetInBytes(
+ mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
+ const mlir::DataLayout &dataLayout) const {
+ // TODO: Bounds operation affect the offset- add support to take them
+ // into account.
+ if (!accBounds.empty())
+ return {};
+
+ // Dynamic extents (aka descriptor-based arrays) - may have a offset.
+ // For example, a negative stride may mean a negative offset to compute the
+ // start of array.
+ auto seqType = mlir::cast<fir::SequenceType>(type);
+ if (seqType.hasDynamicExtents() || seqType.hasUnknownShape())
+ return {};
+
+ // We have non-dynamic extents - but if for some reason the size is not
+ // computable - assume offset is not either. Otherwise, it is an offset of
+ // zero.
+ if (getSizeInBytes(type, var, accBounds, dataLayout).has_value()) {
+ return {0};
+ }
+ return {};
+}
+
+template <>
+std::optional<int64_t> OpenACCMappableModel<fir::BaseBoxType>::getOffsetInBytes(
+ mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
+ const mlir::DataLayout &dataLayout) const {
+ // If we have a box value instead of box reference, the intent is to
+ // get the offset of the data not the offset of the box itself.
+ if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(var.getType())) {
+ if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(
+ fir::unwrapRefType(boxTy.getEleTy()))) {
+ return mappableTy.getOffsetInBytes(var, accBounds, dataLayout);
+ }
+ }
+ // Until boxes get materialized, the offset is not evident because it is
+ // relative to the pointer being held.
+ return {};
+}
+
+template <>
+llvm::SmallVector<mlir::Value>
+OpenACCMappableModel<fir::SequenceType>::generateAccBounds(
+ mlir::Type type, mlir::Value var, mlir::OpBuilder &builder) const {
+ assert((mlir::isa<mlir::acc::PointerLikeType>(var.getType()) ||
+ mlir::isa<mlir::acc::MappableType>(var.getType())) &&
+ "must be pointer-like or mappable");
+
+ fir::FirOpBuilder firBuilder(builder, var.getDefiningOp());
+ auto seqType = mlir::cast<fir::SequenceType>(type);
+ mlir::Location loc = var.getLoc();
+
+ mlir::Value varPtr =
+ mlir::isa<mlir::acc::PointerLikeType>(var.getType())
+ ? var
+ : mlir::cast<mlir::acc::MappableType>(var.getType()).getVarPtr(var);
+
+ if (seqType.hasDynamicExtents() || seqType.hasUnknownShape()) {
+ if (auto boxAddr =
+ mlir::dyn_cast_if_present<fir::BoxAddrOp>(varPtr.getDefiningOp())) {
+ mlir::Value box = boxAddr.getVal();
+ auto res =
+ hlfir::translateToExtendedValue(loc, firBuilder, hlfir::Entity(box));
+ fir::ExtendedValue exv = res.first;
+ mlir::Value boxRef = box;
+ if (auto boxPtr = getPtrFromVar(box)) {
+ boxRef = boxPtr;
+ }
+ // TODO: Handle Fortran optional.
+ const mlir::Value isPresent;
+ Fortran::lower::AddrAndBoundsInfo info(box, boxRef, isPresent,
+ box.getType());
+ return Fortran::lower::genBoundsOpsFromBox<mlir::acc::DataBoundsOp,
+ mlir::acc::DataBoundsType>(
+ firBuilder, loc, exv, info);
+ }
+ assert(false && "array with unknown dimension expected to have descriptor");
+ return {};
+ }
+
+ // TODO: Detect assumed-size case.
+ const bool isAssumedSize = false;
+ auto valToCheck = varPtr;
+ if (auto boxAddr =
+ mlir::dyn_cast_if_present<fir::BoxAddrOp>(varPtr.getDefiningOp())) {
+ valToCheck = boxAddr.getVal();
+ }
+ auto res = hlfir::translateToExtendedValue(loc, firBuilder,
+ hlfir::Entity(valToCheck));
+ fir::ExtendedValue exv = res.first;
+ return Fortran::lower::genBaseBoundsOps<mlir::acc::DataBoundsOp,
+ mlir::acc::DataBoundsType>(
+ firBuilder, loc, exv,
+ /*isAssumedSize=*/isAssumedSize);
+}
+
+template <>
+llvm::SmallVector<mlir::Value>
+OpenACCMappableModel<fir::BaseBoxType>::generateAccBounds(
+ mlir::Type type, mlir::Value var, mlir::OpBuilder &builder) const {
+ // If we have a box value instead of box reference, the intent is to
+ // get the bounds of the data not the bounds of the box itself.
+ if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(var.getType())) {
+ if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(
+ fir::unwrapRefType(boxTy.getEleTy()))) {
+ mlir::Value data = builder.create<fir::BoxAddrOp>(var.getLoc(), var);
+ return mappableTy.generateAccBounds(data, builder);
+ }
+ }
+ // Box references are not arrays - thus generating acc.bounds does not make
+ // sense.
+ return {};
+}
+
+} // namespace fir::acc
diff --git a/flang/lib/Optimizer/OpenACC/RegisterOpenACCExtensions.cpp b/flang/lib/Optimizer/OpenACC/RegisterOpenACCExtensions.cpp
new file mode 100644
index 00000000000000..34ea122f6b997d
--- /dev/null
+++ b/flang/lib/Optimizer/OpenACC/RegisterOpenACCExtensions.cpp
@@ -0,0 +1,28 @@
+//===-- RegisterOpenACCExtensions.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Registration for OpenACC extensions as applied to FIR dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/OpenACC/RegisterOpenACCExtensions.h"
+#include "flang/Optimizer/Dialect/FIRDialect.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h"
+
+namespace fir::acc {
+void registerOpenACCExtensions(mlir::DialectRegistry ®istry) {
+ registry.addExtension(+[](mlir::MLIRContext *ctx,
+ fir::FIROpsDialect *dialect) {
+ fir::SequenceType::attachInterface<OpenACCMappableModel<fir::SequenceType>>(
+ *ctx);
+ fir::BoxType::attachInterface<OpenACCMappableModel<fir::BaseBoxType>>(*ctx);
+ });
+}
+
+} // namespace fir::acc
diff --git a/flang/test/Fir/OpenACC/openacc-mappable.fir b/flang/test/Fir/OpenACC/openacc-mappable.fir
new file mode 100644
index 00000000000000..438cb29b991c7d
--- /dev/null
+++ b/flang/test/Fir/OpenACC/openacc-mappable.fir
@@ -0,0 +1,25 @@
+// Use --mlir-disable-threading so that the diagnostic printing is serialized.
+// RUN: fir-opt %s -pass-pipeline='builtin.module(test-fir-openacc-interfaces)' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s
+
+module attributes {dlti.dl_spec = #dlti.dl_spec<f16 = dense<16> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, f64 = dense<64> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, "dlti.endianness" = "little", "dlti.stack_alignment" = 128 : i64>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"} {
+ func.func @_QPsub() {
+ %c2 = arith.constant 2 : index
+ %c10 = arith.constant 10 : index
+ %0 = fir.alloca !fir.array<10xf32> {bindc_name = "arr", uniq_name = "_QFsubEarr"}
+ %1 = fir.shape_shift %c2, %c10 : (index, index) -> !fir.shapeshift<1>
+ %2 = fir.declare %0(%1) {uniq_name = "_QFsubEarr"} : (!fir.ref<!fir.array<10xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<10xf32>>
+ %3 = fir.embox %2(%1) : (!fir.ref<!fir.array<10xf32>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<10xf32>>
+ %4 = fir.box_addr %3 : (!fir.box<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>>
+ %5 = acc.copyin var(%3 : !fir.box<!fir.array<10xf32>>) -> !fir.box<!fir.array<10xf32>> {name = "arr", structured = false}
+ %6 = acc.copyin varPtr(%4 : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {name = "arr", structured = false}
+ acc.enter_data dataOperands(%5, %6 : !fir.box<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
+ return
+ }
+}
+
+// CHECK: Visiting: %{{.*}} = acc.copyin var(%{{.*}} : !fir.box<!fir.array<10xf32>>) -> !fir.box<!fir.array<10xf32>> {name = "arr", structured = false}
+// CHECK: Mappable: !fir.box<!fir.array<10xf32>>
+// CHECK: Size: 40
+// CHECK: Visiting: %{{.*}} = acc.copyin varPtr(%{{.*}} : !fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>> {name = "arr", structured = false}
+// CHECK: Mappable: !fir.array<10xf32>
+// CHECK: Size: 40
diff --git a/flang/test/lib/CMakeLists.txt b/flang/test/lib/CMakeLists.txt
index fc6ef10fab1f5a..96f4c9513b11a5 100644
--- a/flang/test/lib/CMakeLists.txt
+++ b/flang/test/lib/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(Analysis)
+add_subdirectory(OpenACC)
diff --git a/flang/test/lib/OpenACC/CMakeLists.txt b/flang/test/lib/OpenACC/CMakeLists.txt
new file mode 100644
index 00000000000000..54a81373d253fa
--- /dev/null
+++ b/flang/test/lib/OpenACC/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_flang_library(FIRTestOpenACCInterfaces
+ TestOpenACCInterfaces.cpp
+
+ DEPENDS
+ FIRDialect
+ FIRBuilder
+ FIROpenACCSupport
+ FIRSupport
+ FIRTransforms
+ MLIROpenACCDialect
+
+ LINK_LIBS
+ FIRDialect
+ FIRBuilder
+ FIROpenACCSupport
+ FIRSupport
+ MLIRIR
+ MLIROpenACCDialect
+ MLIRSupport
+ MLIRFuncDialect
+)
diff --git a/flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp b/flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp
new file mode 100644
index 00000000000000..a01396748f4c2c
--- /dev/null
+++ b/flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp
@@ -0,0 +1,85 @@
+//===- TestOpenACCInterfaces.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Support/LLVM.h"
+#include "flang/Optimizer/Support/DataLayout.h"
+
+using namespace mlir;
+
+namespace {
+
+struct TestFIROpenACCInterfaces
+ : public PassWrapper<TestFIROpenACCInterfaces, OperationPass<ModuleOp>> {
+ MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestFIROpenACCInterfaces)
+
+ StringRef getArgument() const final { return "test-fir-openacc-interfaces"; }
+ StringRef getDescription() const final {
+ return "Test FIR implementation of the OpenACC interfaces.";
+ }
+ void runOnOperation() override {
+ mlir::ModuleOp mod = getOperation();
+ auto datalayout =
+ fir::support::getOrSetDataLayout(mod, /*allowDefaultLayout=*/true);
+ mlir::OpBuilder builder(mod);
+ getOperation().walk([&](Operation *op) {
+ if (isa<ACC_DATA_ENTRY_OPS>(op)) {
+ Type typeOfVar = acc::getVar(op).getType();
+ llvm::errs() << "Visiting: " << *op << "\n";
+ auto mappableTy = dyn_cast_if_present<acc::MappableType>(typeOfVar);
+ if (!mappableTy) {
+ mappableTy =
+ dyn_cast_if_present<acc::MappableType>(acc::getVarType(op));
+ }
+ if (mappableTy) {
+ llvm::errs() << "\tMappable: " << mappableTy << "\n";
+ if (datalayout.has_value()) {
+ auto size = mappableTy.getSizeInBytes(
+ acc::getVar(op), acc::getBounds(op), datalayout.value());
+ if (size) {
+ llvm::errs() << "\t\tSize: " << size.value() << "\n";
+ }
+ auto offset = mappableTy.getOffsetInBytes(
+ acc::getVar(op), acc::getBounds(op), datalayout.value());
+ if (offset) {
+ llvm::errs() << "\t\tOffset: " << offset.value() << "\n";
+ }
+ }
+
+ builder.setInsertionPoint(op);
+ auto bounds = mappableTy.generateAccBounds(acc::getVar(op), builder);
+ if (!bounds.empty()) {
+ for (auto [idx, bound] : llvm::enumerate(bounds)) {
+ llvm::errs() << "\t\tBound[" << idx << "]: " << bound << "\n";
+ }
+ }
+ } else {
+ assert(acc::isPointerLikeType(typeOfVar) &&
+ "expected to be pointer-like");
+ llvm::errs() << "\tPointer-like: " << typeOfVar << "\n";
+ }
+ }
+ });
+ }
+};
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// Pass Registration
+//===----------------------------------------------------------------------===//
+
+namespace fir {
+namespace test {
+void registerTestFIROpenACCInterfacesPass() {
+ PassRegistration<TestFIROpenACCInterfaces>();
+}
+} // namespace test
+} // namespace fir
diff --git a/flang/tools/fir-lsp-server/CMakeLists.txt b/flang/tools/fir-lsp-server/CMakeLists.txt
index ff0ced6693b97f..d5445d8f8e99be 100644
--- a/flang/tools/fir-lsp-server/CMakeLists.txt
+++ b/flang/tools/fir-lsp-server/CMakeLists.txt
@@ -11,6 +11,7 @@ get_property(extension_libs GLOBAL PROPERTY MLIR_EXTENSION_LIBS)
target_link_libraries(fir-lsp-server PRIVATE
CUFDialect
FIRDialect
+ FIROpenACCSupport
HLFIRDialect
MLIRLspServerLib
${dialect_libs}
diff --git a/flang/tools/fir-opt/CMakeLists.txt b/flang/tools/fir-opt/CMakeLists.txt
index 4c6dbf7d9c8c37..f0741ca2821695 100644
--- a/flang/tools/fir-opt/CMakeLists.txt
+++ b/flang/tools/fir-opt/CMakeLists.txt
@@ -6,6 +6,7 @@ get_property(extension_libs GLOBAL PROPERTY MLIR_EXTENSION_LIBS)
if(FLANG_INCLUDE_TESTS)
set(test_libs
FIRTestAnalysis
+ FIRTestOpenACCInterfaces
MLIRTestIR
)
endif()
@@ -19,6 +20,7 @@ target_link_libraries(fir-opt PRIVATE
FIRCodeGen
HLFIRDialect
HLFIRTransforms
+ FIROpenACCSupport
FlangOpenMPTransforms
FIRAnalysis
${test_libs}
diff --git a/flang/tools/fir-opt/fir-opt.cpp b/flang/tools/fir-opt/fir-opt.cpp
index 5f6a856116bc04..ef510ff77ad253 100644
--- a/flang/tools/fir-opt/fir-opt.cpp
+++ b/flang/tools/fir-opt/fir-opt.cpp
@@ -22,6 +22,7 @@ using namespace mlir;
namespace fir {
namespace test {
void registerTestFIRAliasAnalysisPass();
+void registerTestFIROpenACCInterfacesPass();
} // namespace test
} // namespace fir
@@ -38,6 +39,7 @@ int main(int argc, char **argv) {
flangomp::registerFlangOpenMPPasses();
#ifdef FLANG_INCLUDE_TESTS
fir::test::registerTestFIRAliasAnalysisPass();
+ fir::test::registerTestFIROpenACCInterfacesPass();
mlir::registerSideEffectTestPasses();
#endif
DialectRegistry registry;
diff --git a/flang/tools/tco/CMakeLists.txt b/flang/tools/tco/CMakeLists.txt
index aac80437ee11d9..0ac18734be2ce9 100644
--- a/flang/tools/tco/CMakeLists.txt
+++ b/flang/tools/tco/CMakeLists.txt
@@ -18,6 +18,7 @@ target_link_libraries(tco PRIVATE
HLFIRDialect
HLFIRTransforms
flangPasses
+ FIROpenACCSupport
FlangOpenMPTransforms
FortranCommon
${dialect_libs}
More information about the flang-commits
mailing list