FLANG
Factory.h
1//===-- Optimizer/Builder/Factory.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// Templates to generate more complex code patterns in transformation passes.
10// In transformation passes, front-end information such as is available in
11// lowering is not available.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef FORTRAN_OPTIMIZER_BUILDER_FACTORY_H
16#define FORTRAN_OPTIMIZER_BUILDER_FACTORY_H
17
18#include "flang/Optimizer/Dialect/FIROps.h"
19#include "flang/Optimizer/Dialect/FIRType.h"
20
21namespace mlir {
22class Location;
23class Value;
24} // namespace mlir
25
26namespace fir::factory {
27
28constexpr llvm::StringRef attrFortranArrayOffsets() {
29 return "Fortran.offsets";
30}
31
40template <typename B>
41void genCharacterCopy(mlir::Value src, mlir::Value srcLen, mlir::Value dst,
42 mlir::Value dstLen, B &builder, mlir::Location loc) {
43 auto srcTy =
44 mlir::cast<fir::CharacterType>(fir::dyn_cast_ptrEleTy(src.getType()));
45 auto dstTy =
46 mlir::cast<fir::CharacterType>(fir::dyn_cast_ptrEleTy(dst.getType()));
47 if (!srcLen && !dstLen && srcTy.getFKind() == dstTy.getFKind() &&
48 srcTy.getLen() == dstTy.getLen()) {
49 // same size, so just use load and store
50 auto load = fir::LoadOp::create(builder, loc, src);
51 fir::StoreOp::create(builder, loc, load, dst);
52 return;
53 }
54 auto zero = mlir::arith::ConstantIndexOp::create(builder, loc, 0);
55 auto one = mlir::arith::ConstantIndexOp::create(builder, loc, 1);
56 auto toArrayTy = [&](fir::CharacterType ty) {
57 return fir::ReferenceType::get(fir::SequenceType::get(
58 fir::SequenceType::ShapeRef{fir::SequenceType::getUnknownExtent()},
59 fir::CharacterType::getSingleton(ty.getContext(), ty.getFKind())));
60 };
61 auto toEleTy = [&](fir::ReferenceType ty) {
62 auto seqTy = mlir::cast<fir::SequenceType>(ty.getEleTy());
63 return mlir::cast<fir::CharacterType>(seqTy.getEleTy());
64 };
65 auto toCoorTy = [&](fir::ReferenceType ty) {
66 return fir::ReferenceType::get(toEleTy(ty));
67 };
68 if (!srcLen && !dstLen && srcTy.getLen() >= dstTy.getLen()) {
69 auto upper =
70 mlir::arith::ConstantIndexOp::create(builder, loc, dstTy.getLen() - 1);
71 auto loop = fir::DoLoopOp::create(builder, loc, zero, upper, one);
72 auto insPt = builder.saveInsertionPoint();
73 builder.setInsertionPointToStart(loop.getBody());
74 auto csrcTy = toArrayTy(srcTy);
75 auto csrc = fir::ConvertOp::create(builder, loc, csrcTy, src);
76 auto in = fir::CoordinateOp::create(builder, loc, toCoorTy(csrcTy), csrc,
77 loop.getInductionVar());
78 auto load = fir::LoadOp::create(builder, loc, in);
79 auto cdstTy = toArrayTy(dstTy);
80 auto cdst = fir::ConvertOp::create(builder, loc, cdstTy, dst);
81 auto out = fir::CoordinateOp::create(builder, loc, toCoorTy(cdstTy), cdst,
82 loop.getInductionVar());
83 mlir::Value cast =
84 srcTy.getFKind() == dstTy.getFKind()
85 ? load.getResult()
86 : fir::ConvertOp::create(builder, loc, toEleTy(cdstTy), load)
87 .getResult();
88 fir::StoreOp::create(builder, loc, cast, out);
89 builder.restoreInsertionPoint(insPt);
90 return;
91 }
92 auto minusOne = [&](mlir::Value v) -> mlir::Value {
93 return mlir::arith::SubIOp::create(
94 builder, loc, fir::ConvertOp::create(builder, loc, one.getType(), v),
95 one);
96 };
97 mlir::Value len = dstLen ? minusOne(dstLen)
98 : mlir::arith::ConstantIndexOp::create(
99 builder, loc, dstTy.getLen() - 1)
100 .getResult();
101 auto loop = fir::DoLoopOp::create(builder, loc, zero, len, one);
102 auto insPt = builder.saveInsertionPoint();
103 builder.setInsertionPointToStart(loop.getBody());
104 mlir::Value slen =
105 srcLen
106 ? fir::ConvertOp::create(builder, loc, one.getType(), srcLen)
107 .getResult()
108 : mlir::arith::ConstantIndexOp::create(builder, loc, srcTy.getLen())
109 .getResult();
110 auto cond =
111 mlir::arith::CmpIOp::create(builder, loc, mlir::arith::CmpIPredicate::slt,
112 loop.getInductionVar(), slen);
113 auto ifOp = fir::IfOp::create(builder, loc, cond, /*withElse=*/true);
114 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
115 auto csrcTy = toArrayTy(srcTy);
116 auto csrc = fir::ConvertOp::create(builder, loc, csrcTy, src);
117 auto in = fir::CoordinateOp::create(builder, loc, toCoorTy(csrcTy), csrc,
118 loop.getInductionVar());
119 auto load = fir::LoadOp::create(builder, loc, in);
120 auto cdstTy = toArrayTy(dstTy);
121 auto cdst = fir::ConvertOp::create(builder, loc, cdstTy, dst);
122 auto out = fir::CoordinateOp::create(builder, loc, toCoorTy(cdstTy), cdst,
123 loop.getInductionVar());
124 mlir::Value cast =
125 srcTy.getFKind() == dstTy.getFKind()
126 ? load.getResult()
127 : fir::ConvertOp::create(builder, loc, toEleTy(cdstTy), load)
128 .getResult();
129 fir::StoreOp::create(builder, loc, cast, out);
130 builder.setInsertionPointToStart(&ifOp.getElseRegion().front());
131 auto space = fir::StringLitOp::create(builder, loc, toEleTy(cdstTy),
133 auto cdst2 = fir::ConvertOp::create(builder, loc, cdstTy, dst);
134 auto out2 = fir::CoordinateOp::create(builder, loc, toCoorTy(cdstTy), cdst2,
135 loop.getInductionVar());
136 fir::StoreOp::create(builder, loc, space, out2);
137 builder.restoreInsertionPoint(insPt);
138}
139
142inline llvm::SmallVector<mlir::Value> getExtents(mlir::Value shapeVal) {
143 if (shapeVal)
144 if (auto *shapeOp = shapeVal.getDefiningOp()) {
145 if (auto shOp = mlir::dyn_cast<fir::ShapeOp>(shapeOp)) {
146 auto operands = shOp.getExtents();
147 return {operands.begin(), operands.end()};
148 }
149 if (auto shOp = mlir::dyn_cast<fir::ShapeShiftOp>(shapeOp)) {
150 auto operands = shOp.getExtents();
151 return {operands.begin(), operands.end()};
152 }
153 }
154 return {};
155}
156
159inline llvm::SmallVector<mlir::Value> getOrigins(mlir::Value shapeVal) {
160 if (shapeVal)
161 if (auto *shapeOp = shapeVal.getDefiningOp()) {
162 if (auto shOp = mlir::dyn_cast<fir::ShapeShiftOp>(shapeOp)) {
163 auto operands = shOp.getOrigins();
164 return {operands.begin(), operands.end()};
165 }
166 if (auto shOp = mlir::dyn_cast<fir::ShiftOp>(shapeOp)) {
167 auto operands = shOp.getOrigins();
168 return {operands.begin(), operands.end()};
169 }
170 }
171 return {};
172}
173
179template <typename B>
181originateIndices(mlir::Location loc, B &builder, mlir::Type memTy,
182 mlir::Value shapeVal, mlir::ValueRange indices) {
184 auto origins = getOrigins(shapeVal);
185 if (origins.empty()) {
186 assert(!shapeVal || mlir::isa<fir::ShapeOp>(shapeVal.getDefiningOp()));
187 auto ty = fir::dyn_cast_ptrOrBoxEleTy(memTy);
188 assert(ty && mlir::isa<fir::SequenceType>(ty));
189 auto seqTy = mlir::cast<fir::SequenceType>(ty);
190 auto one = mlir::arith::ConstantIndexOp::create(builder, loc, 1);
191 const auto dimension = seqTy.getDimension();
192 if (shapeVal) {
193 assert(dimension == mlir::cast<fir::ShapeOp>(shapeVal.getDefiningOp())
194 .getType()
195 .getRank());
196 }
197 for (auto i : llvm::enumerate(indices)) {
198 if (i.index() < dimension) {
199 assert(fir::isa_integer(i.value().getType()));
200 result.push_back(
201 mlir::arith::AddIOp::create(builder, loc, i.value(), one));
202 } else {
203 result.push_back(i.value());
204 }
205 }
206 return result;
207 }
208 const auto dimension = origins.size();
209 unsigned origOff = 0;
210 for (auto i : llvm::enumerate(indices)) {
211 if (i.index() < dimension)
212 result.push_back(mlir::arith::AddIOp::create(builder, loc, i.value(),
213 origins[origOff++]));
214 else
215 result.push_back(i.value());
216 }
217 return result;
218}
219
220} // namespace fir::factory
221
222#endif // FORTRAN_OPTIMIZER_BUILDER_FACTORY_H
Definition FIRType.h:106
Definition OpenACC.h:20
Definition BoxValue.h:447
llvm::SmallVector< mlir::Value > originateIndices(mlir::Location loc, B &builder, mlir::Type memTy, mlir::Value shapeVal, mlir::ValueRange indices)
Definition Factory.h:181
llvm::SmallVector< mlir::Value > getOrigins(mlir::Value shapeVal)
Definition Factory.h:159
llvm::SmallVector< mlir::Value > getExtents(mlir::Location loc, FirOpBuilder &builder, const ExtendedValue &box)
Definition FIRBuilder.cpp:1081
void genCharacterCopy(mlir::Value src, mlir::Value srcLen, mlir::Value dst, mlir::Value dstLen, B &builder, mlir::Location loc)
Definition Factory.h:41
mlir::Type dyn_cast_ptrEleTy(mlir::Type t)
Definition FIRType.cpp:257
mlir::Type dyn_cast_ptrOrBoxEleTy(mlir::Type t)
Definition FIRType.cpp:264
bool isa_integer(mlir::Type t)
Is t an integral type?
Definition FIRType.h:203
Definition AbstractConverter.h:32