FLANG
TemporaryStorage.h
1//===-- Optimizer/Builder/TemporaryStorage.h --------------------*- C++ -*-===//
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// Utility to create an manipulate vector like temporary storages holding
10// Fortran values or descriptors in HLFIR.
11//
12// This is useful to deal with array constructors, and temporary storage
13// inside forall and where constructs where it is not known prior to the
14// construct execution how many values will be stored, or where the values
15// at each iteration may have different shapes or type parameters.
16//
17//===----------------------------------------------------------------------===//
18
19#ifndef FORTRAN_OPTIMIZER_BUILDER_TEMPORARYSTORAGE_H
20#define FORTRAN_OPTIMIZER_BUILDER_TEMPORARYSTORAGE_H
21
22#include "flang/Optimizer/HLFIR/HLFIROps.h"
23
24namespace fir {
25class FirOpBuilder;
26}
27
28namespace hlfir {
29class Entity;
30}
31
32namespace fir::factory {
33
44struct Counter {
46 Counter(mlir::Location loc, fir::FirOpBuilder &builder,
47 mlir::Value initialValue, bool canCountThroughLoops = true);
49 mlir::Value getAndIncrementIndex(mlir::Location loc,
50 fir::FirOpBuilder &builder);
52 void reset(mlir::Location loc, fir::FirOpBuilder &builder);
53 const bool canCountThroughLoops;
54
55private:
57 mlir::Value initialValue;
59 mlir::Value one;
61 mlir::Value index;
62};
63
68class HomogeneousScalarStack {
69public:
70 HomogeneousScalarStack(mlir::Location loc, fir::FirOpBuilder &builder,
71 fir::SequenceType declaredType, mlir::Value extent,
73 bool allocateOnHeap, bool stackThroughLoops,
74 llvm::StringRef name);
75
76 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
77 mlir::Value value);
78 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
79 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
80 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
81
85 hlfir::Entity moveStackAsArrayExpr(mlir::Location loc,
86 fir::FirOpBuilder &builder);
87
90 bool canBeFetchedAfterPush() const { return false; }
91
92private:
94 const bool allocateOnHeap;
96 Counter counter;
98 mlir::Value temp;
99};
100
102class SimpleCopy {
103public:
104 SimpleCopy(mlir::Location loc, fir::FirOpBuilder &builder,
105 hlfir::Entity source, llvm::StringRef tempName);
106
107 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
108 mlir::Value value) {
109 assert(false && "must not be called: value already set");
110 }
111 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder){};
112 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder) {
113 return copy.getBase();
114 }
115 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
116 bool canBeFetchedAfterPush() const { return true; }
117
118public:
120 hlfir::AssociateOp copy;
121};
122
127class SSARegister {
128public:
129 SSARegister(){};
130
131 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
132 mlir::Value value) {
133 ssaRegister = value;
134 }
135 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder){};
136 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder) {
137 return ssaRegister;
138 }
139 void destroy(mlir::Location loc, fir::FirOpBuilder &builder) {}
140 bool canBeFetchedAfterPush() const { return true; }
141
142public:
144 mlir::Value ssaRegister;
145};
146
152class AnyValueStack {
153public:
154 AnyValueStack(mlir::Location loc, fir::FirOpBuilder &builder,
155 mlir::Type valueStaticType);
156
157 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
158 mlir::Value value);
159 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
160 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
161 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
162 bool canBeFetchedAfterPush() const { return true; }
163
164private:
167 mlir::Type valueStaticType;
170 mlir::Value opaquePtr;
172 Counter counter;
174 mlir::Value retValueBox;
175};
176
184class AnyVariableStack {
185public:
186 AnyVariableStack(mlir::Location loc, fir::FirOpBuilder &builder,
187 mlir::Type valueStaticType);
188
189 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
190 mlir::Value value);
191 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
192 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
193 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
194 bool canBeFetchedAfterPush() const { return true; }
195
196private:
198 mlir::Type variableStaticType;
201 mlir::Value opaquePtr;
203 Counter counter;
205 mlir::Value retValueBox;
206};
207
212class AnyAddressStack : public AnyValueStack {
213public:
214 AnyAddressStack(mlir::Location loc, fir::FirOpBuilder &builder,
215 mlir::Type addressType);
216
217 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
218 mlir::Value value);
219 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
220
221private:
222 mlir::Type addressType;
223};
224
225class TemporaryStorage;
226
232class AnyVectorSubscriptStack : public AnyVariableStack {
233public:
234 AnyVectorSubscriptStack(mlir::Location loc, fir::FirOpBuilder &builder,
235 mlir::Type valueStaticType,
236 bool shapeCanBeSavedAsRegister, int rank);
237 void pushShape(mlir::Location loc, fir::FirOpBuilder &builder,
238 mlir::Value shape);
239 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
240 mlir::Value fetchShape(mlir::Location loc, fir::FirOpBuilder &builder);
241 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
242 bool canBeFetchedAfterPush() const { return true; }
243
244private:
245 std::unique_ptr<TemporaryStorage> shapeTemp;
246 // If the shape is saved inside a descriptor (as extents),
247 // keep track of the descriptor type.
248 std::optional<mlir::Type> boxType;
249};
250
252class TemporaryStorage {
253public:
254 template <typename T>
255 TemporaryStorage(T &&impl) : impl{std::forward<T>(impl)} {}
256
257 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
258 mlir::Value value) {
259 std::visit([&](auto &temp) { temp.pushValue(loc, builder, value); }, impl);
260 }
261 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder) {
262 std::visit([&](auto &temp) { temp.resetFetchPosition(loc, builder); },
263 impl);
264 }
265 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder) {
266 return std::visit([&](auto &temp) { return temp.fetch(loc, builder); },
267 impl);
268 }
269 void destroy(mlir::Location loc, fir::FirOpBuilder &builder) {
270 std::visit([&](auto &temp) { temp.destroy(loc, builder); }, impl);
271 }
275 return std::visit([&](auto &temp) { return temp.canBeFetchedAfterPush(); },
276 impl);
277 }
278
279 template <typename T>
280 T &cast() {
281 return std::get<T>(impl);
282 }
283
284private:
285 std::variant<HomogeneousScalarStack, SimpleCopy, SSARegister, AnyValueStack,
286 AnyVariableStack, AnyVectorSubscriptStack, AnyAddressStack>
287 impl;
288};
289} // namespace fir::factory
290#endif // FORTRAN_OPTIMIZER_BUILDER_TEMPORARYSTORAGE_H
Definition FIRBuilder.h:55
hlfir::Entity moveStackAsArrayExpr(mlir::Location loc, fir::FirOpBuilder &builder)
Definition TemporaryStorage.cpp:130
bool canBeFetchedAfterPush() const
Definition TemporaryStorage.h:90
mlir::Value ssaRegister
Temporary storage for the copy.
Definition TemporaryStorage.h:144
hlfir::AssociateOp copy
Temporary storage for the copy.
Definition TemporaryStorage.h:120
Generic wrapper over the different sorts of temporary storages.
Definition TemporaryStorage.h:252
bool canBeFetchedAfterPush() const
Definition TemporaryStorage.h:274
Definition HLFIRTools.h:52
Definition FIRType.h:89
Definition BoxValue.h:445
Definition AbstractConverter.h:34
Definition TemporaryStorage.h:44
void reset(mlir::Location loc, fir::FirOpBuilder &builder)
Set the counter to the initial value.
Definition TemporaryStorage.cpp:52
mlir::Value getAndIncrementIndex(mlir::Location loc, fir::FirOpBuilder &builder)
Return "counter++".
Definition TemporaryStorage.cpp:38
Counter(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value initialValue, bool canCountThroughLoops=true)
Create a counter set to the initial value.
Definition TemporaryStorage.cpp:23