[MemProf] Use correct print_text value (#125793)
[llvm-project.git] / flang / lib / Optimizer / OpenACC / FIROpenACCTypeInterfaces.cpp
blob94ab31de1763dde61d46c8877a05f99865e54121
1 //===-- FIROpenACCTypeInterfaces.cpp --------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implementation of external dialect interfaces for FIR.
11 //===----------------------------------------------------------------------===//
13 #include "flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h"
14 #include "flang/Optimizer/Builder/BoxValue.h"
15 #include "flang/Optimizer/Builder/DirectivesCommon.h"
16 #include "flang/Optimizer/Builder/FIRBuilder.h"
17 #include "flang/Optimizer/Builder/HLFIRTools.h"
18 #include "flang/Optimizer/Dialect/FIROps.h"
19 #include "flang/Optimizer/Dialect/FIROpsSupport.h"
20 #include "flang/Optimizer/Dialect/FIRType.h"
21 #include "flang/Optimizer/Dialect/Support/FIRContext.h"
22 #include "flang/Optimizer/Dialect/Support/KindMapping.h"
23 #include "mlir/Dialect/Arith/IR/Arith.h"
24 #include "mlir/Dialect/OpenACC/OpenACC.h"
25 #include "mlir/IR/BuiltinOps.h"
26 #include "mlir/Support/LLVM.h"
28 namespace fir::acc {
30 static mlir::TypedValue<mlir::acc::PointerLikeType>
31 getPtrFromVar(mlir::Value var) {
32 if (auto ptr =
33 mlir::dyn_cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(var))
34 return ptr;
36 if (auto load = mlir::dyn_cast_if_present<fir::LoadOp>(var.getDefiningOp())) {
37 // All FIR reference types implement the PointerLikeType interface.
38 return mlir::cast<mlir::TypedValue<mlir::acc::PointerLikeType>>(
39 load.getMemref());
42 return {};
45 template <>
46 mlir::TypedValue<mlir::acc::PointerLikeType>
47 OpenACCMappableModel<fir::SequenceType>::getVarPtr(mlir::Type type,
48 mlir::Value var) const {
49 return getPtrFromVar(var);
52 template <>
53 mlir::TypedValue<mlir::acc::PointerLikeType>
54 OpenACCMappableModel<fir::BaseBoxType>::getVarPtr(mlir::Type type,
55 mlir::Value var) const {
56 return getPtrFromVar(var);
59 template <>
60 std::optional<llvm::TypeSize>
61 OpenACCMappableModel<fir::SequenceType>::getSizeInBytes(
62 mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
63 const mlir::DataLayout &dataLayout) const {
64 // TODO: Bounds operation affect the total size - add support to take them
65 // into account.
66 if (!accBounds.empty())
67 return {};
69 // Dynamic extents or unknown ranks generally do not have compile-time
70 // computable dimensions.
71 auto seqType = mlir::cast<fir::SequenceType>(type);
72 if (seqType.hasDynamicExtents() || seqType.hasUnknownShape())
73 return {};
75 // Attempt to find an operation that a lookup for KindMapping can be done
76 // from.
77 mlir::Operation *kindMapSrcOp = var.getDefiningOp();
78 if (!kindMapSrcOp) {
79 kindMapSrcOp = var.getParentRegion()->getParentOp();
80 if (!kindMapSrcOp)
81 return {};
83 auto kindMap = fir::getKindMapping(kindMapSrcOp);
85 auto sizeAndAlignment =
86 fir::getTypeSizeAndAlignment(var.getLoc(), type, dataLayout, kindMap);
87 if (!sizeAndAlignment.has_value())
88 return {};
90 return {llvm::TypeSize::getFixed(sizeAndAlignment->first)};
93 template <>
94 std::optional<llvm::TypeSize>
95 OpenACCMappableModel<fir::BaseBoxType>::getSizeInBytes(
96 mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
97 const mlir::DataLayout &dataLayout) const {
98 // If we have a box value instead of box reference, the intent is to
99 // get the size of the data not the box itself.
100 if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(var.getType())) {
101 if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(
102 fir::unwrapRefType(boxTy.getEleTy()))) {
103 return mappableTy.getSizeInBytes(var, accBounds, dataLayout);
106 // Size for boxes is not computable until it gets materialized.
107 return {};
110 template <>
111 std::optional<int64_t>
112 OpenACCMappableModel<fir::SequenceType>::getOffsetInBytes(
113 mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
114 const mlir::DataLayout &dataLayout) const {
115 // TODO: Bounds operation affect the offset- add support to take them
116 // into account.
117 if (!accBounds.empty())
118 return {};
120 // Dynamic extents (aka descriptor-based arrays) - may have a offset.
121 // For example, a negative stride may mean a negative offset to compute the
122 // start of array.
123 auto seqType = mlir::cast<fir::SequenceType>(type);
124 if (seqType.hasDynamicExtents() || seqType.hasUnknownShape())
125 return {};
127 // We have non-dynamic extents - but if for some reason the size is not
128 // computable - assume offset is not either. Otherwise, it is an offset of
129 // zero.
130 if (getSizeInBytes(type, var, accBounds, dataLayout).has_value()) {
131 return {0};
133 return {};
136 template <>
137 std::optional<int64_t> OpenACCMappableModel<fir::BaseBoxType>::getOffsetInBytes(
138 mlir::Type type, mlir::Value var, mlir::ValueRange accBounds,
139 const mlir::DataLayout &dataLayout) const {
140 // If we have a box value instead of box reference, the intent is to
141 // get the offset of the data not the offset of the box itself.
142 if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(var.getType())) {
143 if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(
144 fir::unwrapRefType(boxTy.getEleTy()))) {
145 return mappableTy.getOffsetInBytes(var, accBounds, dataLayout);
148 // Until boxes get materialized, the offset is not evident because it is
149 // relative to the pointer being held.
150 return {};
153 template <>
154 llvm::SmallVector<mlir::Value>
155 OpenACCMappableModel<fir::SequenceType>::generateAccBounds(
156 mlir::Type type, mlir::Value var, mlir::OpBuilder &builder) const {
157 assert((mlir::isa<mlir::acc::PointerLikeType>(var.getType()) ||
158 mlir::isa<mlir::acc::MappableType>(var.getType())) &&
159 "must be pointer-like or mappable");
161 fir::FirOpBuilder firBuilder(builder, var.getDefiningOp());
162 auto seqType = mlir::cast<fir::SequenceType>(type);
163 mlir::Location loc = var.getLoc();
165 mlir::Value varPtr =
166 mlir::isa<mlir::acc::PointerLikeType>(var.getType())
167 ? var
168 : mlir::cast<mlir::acc::MappableType>(var.getType()).getVarPtr(var);
170 if (seqType.hasDynamicExtents() || seqType.hasUnknownShape()) {
171 if (auto boxAddr =
172 mlir::dyn_cast_if_present<fir::BoxAddrOp>(varPtr.getDefiningOp())) {
173 mlir::Value box = boxAddr.getVal();
174 auto res =
175 hlfir::translateToExtendedValue(loc, firBuilder, hlfir::Entity(box));
176 fir::ExtendedValue exv = res.first;
177 mlir::Value boxRef = box;
178 if (auto boxPtr = getPtrFromVar(box)) {
179 boxRef = boxPtr;
181 // TODO: Handle Fortran optional.
182 const mlir::Value isPresent;
183 fir::factory::AddrAndBoundsInfo info(box, boxRef, isPresent,
184 box.getType());
185 return fir::factory::genBoundsOpsFromBox<mlir::acc::DataBoundsOp,
186 mlir::acc::DataBoundsType>(
187 firBuilder, loc, exv, info);
189 assert(false && "array with unknown dimension expected to have descriptor");
190 return {};
193 // TODO: Detect assumed-size case.
194 const bool isAssumedSize = false;
195 auto valToCheck = varPtr;
196 if (auto boxAddr =
197 mlir::dyn_cast_if_present<fir::BoxAddrOp>(varPtr.getDefiningOp())) {
198 valToCheck = boxAddr.getVal();
200 auto res = hlfir::translateToExtendedValue(loc, firBuilder,
201 hlfir::Entity(valToCheck));
202 fir::ExtendedValue exv = res.first;
203 return fir::factory::genBaseBoundsOps<mlir::acc::DataBoundsOp,
204 mlir::acc::DataBoundsType>(
205 firBuilder, loc, exv,
206 /*isAssumedSize=*/isAssumedSize);
209 template <>
210 llvm::SmallVector<mlir::Value>
211 OpenACCMappableModel<fir::BaseBoxType>::generateAccBounds(
212 mlir::Type type, mlir::Value var, mlir::OpBuilder &builder) const {
213 // If we have a box value instead of box reference, the intent is to
214 // get the bounds of the data not the bounds of the box itself.
215 if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(var.getType())) {
216 if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(
217 fir::unwrapRefType(boxTy.getEleTy()))) {
218 mlir::Value data = builder.create<fir::BoxAddrOp>(var.getLoc(), var);
219 return mappableTy.generateAccBounds(data, builder);
222 // Box references are not arrays - thus generating acc.bounds does not make
223 // sense.
224 return {};
227 } // namespace fir::acc