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
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
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
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
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
183public:
184 AnyVariableStack(mlir::Location loc, fir::FirOpBuilder &builder,
185 mlir::Type valueStaticType);
186
187 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
188 mlir::Value value);
189 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
190 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
191 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
192 bool canBeFetchedAfterPush() const { return true; }
193
194private:
196 mlir::Type variableStaticType;
199 mlir::Value opaquePtr;
201 Counter counter;
203 mlir::Value retValueBox;
204};
205
206class TemporaryStorage;
207
214public:
215 AnyVectorSubscriptStack(mlir::Location loc, fir::FirOpBuilder &builder,
216 mlir::Type valueStaticType,
217 bool shapeCanBeSavedAsRegister, int rank);
218 void pushShape(mlir::Location loc, fir::FirOpBuilder &builder,
219 mlir::Value shape);
220 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
221 mlir::Value fetchShape(mlir::Location loc, fir::FirOpBuilder &builder);
222 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
223 bool canBeFetchedAfterPush() const { return true; }
224
225private:
226 std::unique_ptr<TemporaryStorage> shapeTemp;
227 // If the shape is saved inside a descriptor (as extents),
228 // keep track of the descriptor type.
229 std::optional<mlir::Type> boxType;
230};
231
234public:
235 template <typename T>
236 TemporaryStorage(T &&impl) : impl{std::forward<T>(impl)} {}
237
238 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
239 mlir::Value value) {
240 std::visit([&](auto &temp) { temp.pushValue(loc, builder, value); }, impl);
241 }
242 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder) {
243 std::visit([&](auto &temp) { temp.resetFetchPosition(loc, builder); },
244 impl);
245 }
246 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder) {
247 return std::visit([&](auto &temp) { return temp.fetch(loc, builder); },
248 impl);
249 }
250 void destroy(mlir::Location loc, fir::FirOpBuilder &builder) {
251 std::visit([&](auto &temp) { temp.destroy(loc, builder); }, impl);
252 }
256 return std::visit([&](auto &temp) { return temp.canBeFetchedAfterPush(); },
257 impl);
258 }
259
260 template <typename T>
261 T &cast() {
262 return std::get<T>(impl);
263 }
264
265private:
266 std::variant<HomogeneousScalarStack, SimpleCopy, SSARegister, AnyValueStack,
267 AnyVariableStack, AnyVectorSubscriptStack>
268 impl;
269};
270} // namespace fir::factory
271#endif // FORTRAN_OPTIMIZER_BUILDER_TEMPORARYSTORAGE_H
Definition: FIRBuilder.h:55
Definition: TemporaryStorage.h:152
Definition: TemporaryStorage.h:182
Definition: TemporaryStorage.h:213
Definition: TemporaryStorage.h:68
hlfir::Entity moveStackAsArrayExpr(mlir::Location loc, fir::FirOpBuilder &builder)
Definition: TemporaryStorage.cpp:132
bool canBeFetchedAfterPush() const
Definition: TemporaryStorage.h:90
Definition: TemporaryStorage.h:127
mlir::Value ssaRegister
Temporary storage for the copy.
Definition: TemporaryStorage.h:144
Structure to hold the value of a single entity.
Definition: TemporaryStorage.h:102
hlfir::AssociateOp copy
Temporary storage for the copy.
Definition: TemporaryStorage.h:120
Generic wrapper over the different sorts of temporary storages.
Definition: TemporaryStorage.h:233
bool canBeFetchedAfterPush() const
Definition: TemporaryStorage.h:255
Definition: HLFIRTools.h:51
Definition: FIRType.h:77
Definition: AbstractConverter.h:31
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