[flang-commits] [flang] [flang][acc] Implement MappableType interfaces for fir.box and fir.array (PR #122495)
via flang-commits
flang-commits at lists.llvm.org
Mon Jan 13 02:53:23 PST 2025
================
@@ -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<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 {};
+
+ // 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<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())) {
----------------
jeanPerier wrote:
Would it make sense to add the fir.box as an operand of the acc operation in that case to avoid having to chase it down?
https://github.com/llvm/llvm-project/pull/122495
More information about the flang-commits
mailing list