From 7094f41f60107a8844ed6086a19a0010c0c0690f Mon Sep 17 00:00:00 2001 From: Razvan Lupusoru Date: Fri, 10 Jan 2025 08:56:35 -0800 Subject: [PATCH] [flang][acc] Implement MappableType interfaces for fir.box and fir.array 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>` 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`. --- .../OpenACC/FIROpenACCTypeInterfaces.h | 43 ++++ .../OpenACC/RegisterOpenACCExtensions.h | 22 ++ .../include/flang/Optimizer/Support/InitFIR.h | 2 + flang/lib/Frontend/CMakeLists.txt | 1 + flang/lib/Optimizer/CMakeLists.txt | 1 + flang/lib/Optimizer/Dialect/CMakeLists.txt | 2 +- flang/lib/Optimizer/OpenACC/CMakeLists.txt | 22 ++ .../OpenACC/FIROpenACCTypeInterfaces.cpp | 221 ++++++++++++++++++ .../OpenACC/RegisterOpenACCExtensions.cpp | 28 +++ flang/test/Fir/OpenACC/openacc-mappable.fir | 25 ++ flang/test/lib/CMakeLists.txt | 1 + flang/test/lib/OpenACC/CMakeLists.txt | 21 ++ .../lib/OpenACC/TestOpenACCInterfaces.cpp | 85 +++++++ flang/tools/fir-lsp-server/CMakeLists.txt | 1 + flang/tools/fir-opt/CMakeLists.txt | 2 + flang/tools/fir-opt/fir-opt.cpp | 2 + flang/tools/tco/CMakeLists.txt | 1 + 17 files changed, 479 insertions(+), 1 deletion(-) create mode 100644 flang/include/flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h create mode 100644 flang/include/flang/Optimizer/OpenACC/RegisterOpenACCExtensions.h create mode 100644 flang/lib/Optimizer/OpenACC/CMakeLists.txt create mode 100644 flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp create mode 100644 flang/lib/Optimizer/OpenACC/RegisterOpenACCExtensions.cpp create mode 100644 flang/test/Fir/OpenACC/openacc-mappable.fir create mode 100644 flang/test/lib/OpenACC/CMakeLists.txt create mode 100644 flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp diff --git a/flang/include/flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h b/flang/include/flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h new file mode 100644 index 0000000000000..c1bea32a22361 --- /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 +struct OpenACCMappableModel + : public mlir::acc::MappableType::ExternalModel, + T> { + mlir::TypedValue getVarPtr(::mlir::Type type, + mlir::Value var) const; + + std::optional + getSizeInBytes(mlir::Type type, mlir::Value var, mlir::ValueRange accBounds, + const mlir::DataLayout &dataLayout) const; + + std::optional + getOffsetInBytes(mlir::Type type, mlir::Value var, mlir::ValueRange accBounds, + const mlir::DataLayout &dataLayout) const; + + llvm::SmallVector + 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 0000000000000..efaddd72ebbf2 --- /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 1c61c36719992..94995ac6136ed 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 e954800c3b88b..f00566d779157 100644 --- a/flang/lib/Frontend/CMakeLists.txt +++ b/flang/lib/Frontend/CMakeLists.txt @@ -38,6 +38,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 5354d7181e651..72aba51b85870 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 a8235f841b879..08caa15700d4c 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 0000000000000..ed673121353c1 --- /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 0000000000000..ebcc54add0ed1 --- /dev/null +++ b/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp @@ -0,0 +1,221 @@ +//===-- 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/Support/LLVM.h" + +namespace fir::acc { + +static mlir::TypedValue +getPtrFromVar(mlir::Value var) { + if (auto ptr = + mlir::dyn_cast>(var)) + return ptr; + + if (auto load = mlir::dyn_cast_if_present(var.getDefiningOp())) { + // All FIR reference types implement the PointerLikeType interface. + return mlir::cast>( + load.getMemref()); + } + + return {}; +} + +template <> +mlir::TypedValue +OpenACCMappableModel::getVarPtr(mlir::Type type, + mlir::Value var) const { + return getPtrFromVar(var); +} + +template <> +mlir::TypedValue +OpenACCMappableModel::getVarPtr(mlir::Type type, + mlir::Value var) const { + return getPtrFromVar(var); +} + +template <> +std::optional +OpenACCMappableModel::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(type); + if (seqType.hasDynamicExtents() || seqType.hasUnknownShape()) + return {}; + + // Without a defining op, cannot look up appropriate kindMapping for the + // current context. + if (!var.getDefiningOp()) + return {}; + auto kindMap = fir::getKindMapping(var.getDefiningOp()); + auto sizeAndAlignment = + fir::getTypeSizeAndAlignment(var.getLoc(), type, dataLayout, kindMap); + if (!sizeAndAlignment.has_value()) + return {}; + + return {llvm::TypeSize::getFixed(sizeAndAlignment->first)}; +} + +template <> +std::optional +OpenACCMappableModel::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(var.getType())) { + if (auto mappableTy = mlir::dyn_cast( + fir::unwrapRefType(boxTy.getEleTy()))) { + return mappableTy.getSizeInBytes(var, accBounds, dataLayout); + } + } + // Size for boxes is not computable until it gets materialized. + return {}; +} + +template <> +std::optional +OpenACCMappableModel::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(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 OpenACCMappableModel::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(var.getType())) { + if (auto mappableTy = mlir::dyn_cast( + 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 +OpenACCMappableModel::generateAccBounds( + mlir::Type type, mlir::Value var, mlir::OpBuilder &builder) const { + assert((mlir::isa(var.getType()) || + mlir::isa(var.getType())) && + "must be pointer-like or mappable"); + + fir::FirOpBuilder firBuilder(builder, var.getDefiningOp()); + auto seqType = mlir::cast(type); + mlir::Location loc = var.getLoc(); + + mlir::Value varPtr = + mlir::isa(var.getType()) + ? var + : mlir::cast(var.getType()).getVarPtr(var); + + if (seqType.hasDynamicExtents() || seqType.hasUnknownShape()) { + if (auto boxAddr = + mlir::dyn_cast_if_present(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( + 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(varPtr.getDefiningOp())) { + valToCheck = boxAddr.getVal(); + } + auto res = hlfir::translateToExtendedValue(loc, firBuilder, + hlfir::Entity(valToCheck)); + fir::ExtendedValue exv = res.first; + return Fortran::lower::genBaseBoundsOps( + firBuilder, loc, exv, + /*isAssumedSize=*/isAssumedSize); +} + +template <> +llvm::SmallVector +OpenACCMappableModel::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(var.getType())) { + if (auto mappableTy = mlir::dyn_cast( + fir::unwrapRefType(boxTy.getEleTy()))) { + mlir::Value data = builder.create(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 0000000000000..34ea122f6b997 --- /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>( + *ctx); + fir::BoxType::attachInterface>(*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 0000000000000..438cb29b991c7 --- /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 : 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.shapeshift<1>) -> !fir.ref> + %3 = fir.embox %2(%1) : (!fir.ref>, !fir.shapeshift<1>) -> !fir.box> + %4 = fir.box_addr %3 : (!fir.box>) -> !fir.ref> + %5 = acc.copyin var(%3 : !fir.box>) -> !fir.box> {name = "arr", structured = false} + %6 = acc.copyin varPtr(%4 : !fir.ref>) -> !fir.ref> {name = "arr", structured = false} + acc.enter_data dataOperands(%5, %6 : !fir.box>, !fir.ref>) + return + } +} + +// CHECK: Visiting: %{{.*}} = acc.copyin var(%{{.*}} : !fir.box>) -> !fir.box> {name = "arr", structured = false} +// CHECK: Mappable: !fir.box> +// CHECK: Size: 40 +// CHECK: Visiting: %{{.*}} = acc.copyin varPtr(%{{.*}} : !fir.ref>) -> !fir.ref> {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 fc6ef10fab1f5..96f4c9513b11a 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 0000000000000..54a81373d253f --- /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 0000000000000..a01396748f4c2 --- /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> { + 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(op)) { + Type typeOfVar = acc::getVar(op).getType(); + llvm::errs() << "Visiting: " << *op << "\n"; + auto mappableTy = dyn_cast_if_present(typeOfVar); + if (!mappableTy) { + mappableTy = + dyn_cast_if_present(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(); +} +} // namespace test +} // namespace fir diff --git a/flang/tools/fir-lsp-server/CMakeLists.txt b/flang/tools/fir-lsp-server/CMakeLists.txt index ff0ced6693b97..d5445d8f8e99b 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 4c6dbf7d9c8c3..f0741ca282169 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 5f6a856116bc0..ef510ff77ad25 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 aac80437ee11d..0ac18734be2ce 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}