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/Common/idioms.h"
23#include "flang/Optimizer/HLFIR/HLFIROps.h"
24
25namespace fir {
26class FirOpBuilder;
27}
28
29namespace hlfir {
30class Entity;
31}
32
33namespace fir::factory {
34
45struct Counter {
47 Counter(mlir::Location loc, fir::FirOpBuilder &builder,
48 mlir::Value initialValue, bool canCountThroughLoops = true);
50 mlir::Value getAndIncrementIndex(mlir::Location loc,
51 fir::FirOpBuilder &builder);
53 void reset(mlir::Location loc, fir::FirOpBuilder &builder);
54 const bool canCountThroughLoops;
55
56private:
58 mlir::Value initialValue;
60 mlir::Value one;
62 mlir::Value index;
63};
64
69class HomogeneousScalarStack {
70public:
71 HomogeneousScalarStack(mlir::Location loc, fir::FirOpBuilder &builder,
72 fir::SequenceType declaredType, mlir::Value extent,
74 bool allocateOnHeap, bool stackThroughLoops,
75 llvm::StringRef name);
76
77 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
78 mlir::Value value);
79 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
80 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
81 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
82
86 hlfir::Entity moveStackAsArrayExpr(mlir::Location loc,
87 fir::FirOpBuilder &builder);
88
91 bool canBeFetchedAfterPush() const { return false; }
92
93private:
95 const bool allocateOnHeap;
97 Counter counter;
99 mlir::Value temp;
100};
101
108class ArrayTemp {
109public:
110 ArrayTemp(mlir::Location loc, fir::FirOpBuilder &builder,
111 fir::SequenceType declaredType, llvm::ArrayRef<mlir::Value> extents,
112 llvm::ArrayRef<mlir::Value> lowerBounds,
113 llvm::ArrayRef<mlir::Value> lengths, bool allocateOnHeap,
114 llvm::StringRef name);
115
116 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
117 mlir::Value value, mlir::ValueRange indices);
118 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder) {}
119 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder,
120 mlir::ValueRange indices);
121 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
122 bool canBeFetchedAfterPush() const { return true; }
123
124private:
125 const bool allocateOnHeap;
126 mlir::Value temp;
128};
129
131class SimpleCopy {
132public:
133 SimpleCopy(mlir::Location loc, fir::FirOpBuilder &builder,
134 hlfir::Entity source, llvm::StringRef tempName);
135
136 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
137 mlir::Value value) {
138 assert(false && "must not be called: value already set");
139 }
140 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder){};
141 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder) {
142 return copy.getBase();
143 }
144 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
145 bool canBeFetchedAfterPush() const { return true; }
146
147public:
149 hlfir::AssociateOp copy;
150};
151
156class SSARegister {
157public:
158 SSARegister(){};
159
160 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
161 mlir::Value value) {
162 ssaRegister = value;
163 }
164 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder){};
165 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder) {
166 return ssaRegister;
167 }
168 void destroy(mlir::Location loc, fir::FirOpBuilder &builder) {}
169 bool canBeFetchedAfterPush() const { return true; }
170
171public:
173 mlir::Value ssaRegister;
174};
175
181class AnyValueStack {
182public:
183 AnyValueStack(mlir::Location loc, fir::FirOpBuilder &builder,
184 mlir::Type valueStaticType);
185
186 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
187 mlir::Value value);
188 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
189 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
190 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
191 bool canBeFetchedAfterPush() const { return true; }
192
193private:
196 mlir::Type valueStaticType;
199 mlir::Value opaquePtr;
201 Counter counter;
203 mlir::Value retValueBox;
204};
205
213class AnyVariableStack {
214public:
215 AnyVariableStack(mlir::Location loc, fir::FirOpBuilder &builder,
216 mlir::Type valueStaticType);
217
218 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
219 mlir::Value value);
220 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
221 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
222 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
223 bool canBeFetchedAfterPush() const { return true; }
224
225private:
227 mlir::Type variableStaticType;
230 mlir::Value opaquePtr;
232 Counter counter;
234 mlir::Value retValueBox;
235};
236
241class AnyAddressStack : public AnyValueStack {
242public:
243 AnyAddressStack(mlir::Location loc, fir::FirOpBuilder &builder,
244 mlir::Type addressType);
245
246 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
247 mlir::Value value);
248 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);
249
250private:
251 mlir::Type addressType;
252};
253
254class TemporaryStorage;
255
261class AnyVectorSubscriptStack : public AnyVariableStack {
262public:
263 AnyVectorSubscriptStack(mlir::Location loc, fir::FirOpBuilder &builder,
264 mlir::Type valueStaticType,
265 bool shapeCanBeSavedAsRegister, int rank);
266 void pushShape(mlir::Location loc, fir::FirOpBuilder &builder,
267 mlir::Value shape);
268 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder);
269 mlir::Value fetchShape(mlir::Location loc, fir::FirOpBuilder &builder);
270 void destroy(mlir::Location loc, fir::FirOpBuilder &builder);
271 bool canBeFetchedAfterPush() const { return true; }
272
273private:
274 std::unique_ptr<TemporaryStorage> shapeTemp;
275 // If the shape is saved inside a descriptor (as extents),
276 // keep track of the descriptor type.
277 std::optional<mlir::Type> boxType;
278};
279
281class TemporaryStorage {
282public:
283 template <typename T>
284 TemporaryStorage(T &&impl) : impl{std::forward<T>(impl)} {}
285
286 void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
287 mlir::Value value, mlir::ValueRange indices = {}) {
288 // Only ArrayTemp uses the loop indices; other temps don't take them.
289 std::visit(Fortran::common::visitors{
290 [&](ArrayTemp &temp) {
291 temp.pushValue(loc, builder, value, indices);
292 },
293 [&](auto &temp) { temp.pushValue(loc, builder, value); }},
294 impl);
295 }
296 void resetFetchPosition(mlir::Location loc, fir::FirOpBuilder &builder) {
297 std::visit([&](auto &temp) { temp.resetFetchPosition(loc, builder); },
298 impl);
299 }
300 mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder,
301 mlir::ValueRange indices = {}) {
302 return std::visit(
304 [&](ArrayTemp &temp) { return temp.fetch(loc, builder, indices); },
305 [&](auto &temp) { return temp.fetch(loc, builder); }},
306 impl);
307 }
308 void destroy(mlir::Location loc, fir::FirOpBuilder &builder) {
309 std::visit([&](auto &temp) { temp.destroy(loc, builder); }, impl);
310 }
314 return std::visit([&](auto &temp) { return temp.canBeFetchedAfterPush(); },
315 impl);
316 }
317
318 template <typename T>
319 T &cast() {
320 return std::get<T>(impl);
321 }
322
323private:
324 std::variant<HomogeneousScalarStack, ArrayTemp, SimpleCopy, SSARegister,
325 AnyValueStack, AnyVariableStack, AnyVectorSubscriptStack,
326 AnyAddressStack>
327 impl;
328};
329} // namespace fir::factory
330#endif // FORTRAN_OPTIMIZER_BUILDER_TEMPORARYSTORAGE_H
Definition FIRBuilder.h:56
Definition TemporaryStorage.h:108
hlfir::Entity moveStackAsArrayExpr(mlir::Location loc, fir::FirOpBuilder &builder)
Definition TemporaryStorage.cpp:130
bool canBeFetchedAfterPush() const
Definition TemporaryStorage.h:91
mlir::Value ssaRegister
Temporary storage for the copy.
Definition TemporaryStorage.h:173
hlfir::AssociateOp copy
Temporary storage for the copy.
Definition TemporaryStorage.h:149
Generic wrapper over the different sorts of temporary storages.
Definition TemporaryStorage.h:281
bool canBeFetchedAfterPush() const
Definition TemporaryStorage.h:313
Definition HLFIRTools.h:52
Definition FIRType.h:103
Definition OpenACC.h:20
Definition BoxValue.h:445
Definition AbstractConverter.h:37
Definition idioms.h:61
Definition TemporaryStorage.h:45
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