[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`.
This commit is contained in:
Razvan Lupusoru 2025-01-14 10:42:57 -08:00 committed by GitHub
parent 9405a81ee7
commit 01a0d212a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 485 additions and 1 deletions

View file

@ -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_

View file

@ -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 &registry);
} // namespace fir::acc
#endif // FLANG_OPTIMIZER_OPENACC_REGISTEROPENACCEXTENSIONS_H_

View file

@ -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 &registry,
addFIRInlinerExtension(registry);
addFIRToLLVMIRExtension(registry);
cuf::registerCUFDialectTranslation(registry);
fir::acc::registerOpenACCExtensions(registry);
}
inline void loadNonCodegenDialects(mlir::MLIRContext &context) {

View file

@ -39,6 +39,7 @@ add_flang_library(flangFrontend
HLFIRDialect
HLFIRTransforms
flangPasses
FIROpenACCSupport
FlangOpenMPTransforms
MLIRTransforms
MLIRBuiltinToLLVMIRTranslation

View file

@ -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)

View file

@ -6,8 +6,8 @@ add_flang_library(FIRDialect
FIRDialect.cpp
FIROps.cpp
FIRType.cpp
FortranVariableInterface.cpp
FirAliasTagOpInterface.cpp
FortranVariableInterface.cpp
Inliner.cpp
DEPENDS

View file

@ -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
)

View file

@ -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

View file

@ -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 &registry) {
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

View file

@ -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

View file

@ -1 +1,2 @@
add_subdirectory(Analysis)
add_subdirectory(OpenACC)

View file

@ -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
)

View file

@ -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

View file

@ -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}

View file

@ -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}

View file

@ -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;

View file

@ -18,6 +18,7 @@ target_link_libraries(tco PRIVATE
HLFIRDialect
HLFIRTransforms
flangPasses
FIROpenACCSupport
FlangOpenMPTransforms
FortranCommon
${dialect_libs}