[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:
parent
9405a81ee7
commit
01a0d212a6
17 changed files with 485 additions and 1 deletions
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ add_flang_library(flangFrontend
|
|||
HLFIRDialect
|
||||
HLFIRTransforms
|
||||
flangPasses
|
||||
FIROpenACCSupport
|
||||
FlangOpenMPTransforms
|
||||
MLIRTransforms
|
||||
MLIRBuiltinToLLVMIRTranslation
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ add_flang_library(FIRDialect
|
|||
FIRDialect.cpp
|
||||
FIROps.cpp
|
||||
FIRType.cpp
|
||||
FortranVariableInterface.cpp
|
||||
FirAliasTagOpInterface.cpp
|
||||
FortranVariableInterface.cpp
|
||||
Inliner.cpp
|
||||
|
||||
DEPENDS
|
||||
|
|
|
|||
22
flang/lib/Optimizer/OpenACC/CMakeLists.txt
Normal file
22
flang/lib/Optimizer/OpenACC/CMakeLists.txt
Normal 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
|
||||
)
|
||||
227
flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp
Normal file
227
flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp
Normal 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
|
||||
28
flang/lib/Optimizer/OpenACC/RegisterOpenACCExtensions.cpp
Normal file
28
flang/lib/Optimizer/OpenACC/RegisterOpenACCExtensions.cpp
Normal 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 ®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
|
||||
25
flang/test/Fir/OpenACC/openacc-mappable.fir
Normal file
25
flang/test/Fir/OpenACC/openacc-mappable.fir
Normal 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
|
||||
|
|
@ -1 +1,2 @@
|
|||
add_subdirectory(Analysis)
|
||||
add_subdirectory(OpenACC)
|
||||
|
|
|
|||
21
flang/test/lib/OpenACC/CMakeLists.txt
Normal file
21
flang/test/lib/OpenACC/CMakeLists.txt
Normal 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
|
||||
)
|
||||
85
flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp
Normal file
85
flang/test/lib/OpenACC/TestOpenACCInterfaces.cpp
Normal 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
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ target_link_libraries(tco PRIVATE
|
|||
HLFIRDialect
|
||||
HLFIRTransforms
|
||||
flangPasses
|
||||
FIROpenACCSupport
|
||||
FlangOpenMPTransforms
|
||||
FortranCommon
|
||||
${dialect_libs}
|
||||
|
|
|
|||
Loading…
Reference in a new issue