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