1//===-- Transformational.cpp ------------------------------------*- C++ -*-===//
2// Generate transformational intrinsic runtime API calls.
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#include "flang/Optimizer/Builder/Runtime/Transformational.h"
11#include "flang/Optimizer/Builder/BoxValue.h"
12#include "flang/Optimizer/Builder/Character.h"
13#include "flang/Optimizer/Builder/FIRBuilder.h"
14#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
15#include "flang/Optimizer/Support/Utils.h"
16#include "flang/Runtime/matmul-transpose.h"
17#include "flang/Runtime/matmul.h"
18#include "flang/Runtime/transformational.h"
19#include "mlir/Dialect/Func/IR/FuncOps.h"
20
21using namespace Fortran::runtime;
22
23/// Placeholder for real*10 version of BesselJn intrinsic.
24struct ForcedBesselJn_10 {
25 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselJn_10));
26 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
27 return [](mlir::MLIRContext *ctx) {
28 auto ty = mlir::FloatType::getF80(ctx);
29 auto boxTy =
30 fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
31 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
32 auto intTy = mlir::IntegerType::get(ctx, 32);
33 auto noneTy = mlir::NoneType::get(ctx);
34 return mlir::FunctionType::get(
35 ctx, {boxTy, intTy, intTy, ty, ty, ty, strTy, intTy}, {noneTy});
36 };
37 }
38};
39
40/// Placeholder for real*16 version of BesselJn intrinsic.
41struct ForcedBesselJn_16 {
42 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselJn_16));
43 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
44 return [](mlir::MLIRContext *ctx) {
45 auto ty = mlir::FloatType::getF128(ctx);
46 auto boxTy =
47 fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
48 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
49 auto intTy = mlir::IntegerType::get(ctx, 32);
50 auto noneTy = mlir::NoneType::get(ctx);
51 return mlir::FunctionType::get(
52 ctx, {boxTy, intTy, intTy, ty, ty, ty, strTy, intTy}, {noneTy});
53 };
54 }
55};
56
57/// Placeholder for real*10 version of BesselJn intrinsic when `x == 0.0`.
58struct ForcedBesselJnX0_10 {
59 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselJnX0_10));
60 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
61 return [](mlir::MLIRContext *ctx) {
62 auto boxTy =
63 fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
64 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
65 auto intTy = mlir::IntegerType::get(ctx, 32);
66 auto noneTy = mlir::NoneType::get(ctx);
67 return mlir::FunctionType::get(ctx, {boxTy, intTy, intTy, strTy, intTy},
68 {noneTy});
69 };
70 }
71};
72
73/// Placeholder for real*16 version of BesselJn intrinsic when `x == 0.0`.
74struct ForcedBesselJnX0_16 {
75 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselJnX0_16));
76 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
77 return [](mlir::MLIRContext *ctx) {
78 auto boxTy =
79 fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
80 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
81 auto intTy = mlir::IntegerType::get(ctx, 32);
82 auto noneTy = mlir::NoneType::get(ctx);
83 return mlir::FunctionType::get(ctx, {boxTy, intTy, intTy, strTy, intTy},
84 {noneTy});
85 };
86 }
87};
88
89/// Placeholder for real*10 version of BesselYn intrinsic.
90struct ForcedBesselYn_10 {
91 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselYn_10));
92 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
93 return [](mlir::MLIRContext *ctx) {
94 auto ty = mlir::FloatType::getF80(ctx);
95 auto boxTy =
96 fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
97 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
98 auto intTy = mlir::IntegerType::get(ctx, 32);
99 auto noneTy = mlir::NoneType::get(ctx);
100 return mlir::FunctionType::get(
101 ctx, {boxTy, intTy, intTy, ty, ty, ty, strTy, intTy}, {noneTy});
102 };
103 }
104};
105
106/// Placeholder for real*16 version of BesselYn intrinsic.
107struct ForcedBesselYn_16 {
108 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselYn_16));
109 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
110 return [](mlir::MLIRContext *ctx) {
111 auto ty = mlir::FloatType::getF128(ctx);
112 auto boxTy =
113 fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
114 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
115 auto intTy = mlir::IntegerType::get(ctx, 32);
116 auto noneTy = mlir::NoneType::get(ctx);
117 return mlir::FunctionType::get(
118 ctx, {boxTy, intTy, intTy, ty, ty, ty, strTy, intTy}, {noneTy});
119 };
120 }
121};
122
123/// Placeholder for real*10 version of BesselYn intrinsic when `x == 0.0`.
124struct ForcedBesselYnX0_10 {
125 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselYnX0_10));
126 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
127 return [](mlir::MLIRContext *ctx) {
128 auto boxTy =
129 fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
130 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
131 auto intTy = mlir::IntegerType::get(ctx, 32);
132 auto noneTy = mlir::NoneType::get(ctx);
133 return mlir::FunctionType::get(ctx, {boxTy, intTy, intTy, strTy, intTy},
134 {noneTy});
135 };
136 }
137};
138
139/// Placeholder for real*16 version of BesselYn intrinsic when `x == 0.0`.
140struct ForcedBesselYnX0_16 {
141 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(BesselYnX0_16));
142 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
143 return [](mlir::MLIRContext *ctx) {
144 auto boxTy =
145 fir::runtime::getModel<Fortran::runtime::Descriptor &>()(ctx);
146 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
147 auto intTy = mlir::IntegerType::get(ctx, 32);
148 auto noneTy = mlir::NoneType::get(ctx);
149 return mlir::FunctionType::get(ctx, {boxTy, intTy, intTy, strTy, intTy},
150 {noneTy});
151 };
152 }
153};
154
155/// Generate call to `BesselJn` intrinsic.
156void fir::runtime::genBesselJn(fir::FirOpBuilder &builder, mlir::Location loc,
157 mlir::Value resultBox, mlir::Value n1,
158 mlir::Value n2, mlir::Value x, mlir::Value bn2,
159 mlir::Value bn2_1) {
160 mlir::func::FuncOp func;
161 auto xTy = x.getType();
162
163 if (xTy.isF32())
164 func = fir::runtime::getRuntimeFunc<mkRTKey(BesselJn_4)>(loc, builder);
165 else if (xTy.isF64())
166 func = fir::runtime::getRuntimeFunc<mkRTKey(BesselJn_8)>(loc, builder);
167 else if (xTy.isF80())
168 func = fir::runtime::getRuntimeFunc<ForcedBesselJn_10>(loc, builder);
169 else if (xTy.isF128())
170 func = fir::runtime::getRuntimeFunc<ForcedBesselJn_16>(loc, builder);
171 else
172 fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_JN");
173
174 auto fTy = func.getFunctionType();
175 auto sourceFile = fir::factory::locationToFilename(builder, loc);
176 auto sourceLine =
177 fir::factory::locationToLineNo(builder, loc, fTy.getInput(7));
178 auto args =
179 fir::runtime::createArguments(builder, loc, fTy, resultBox, n1, n2, x,
180 bn2, bn2_1, sourceFile, sourceLine);
181 builder.create<fir::CallOp>(loc, func, args);
182}
183
184/// Generate call to `BesselJn` intrinsic. This is used when `x == 0.0`.
185void fir::runtime::genBesselJnX0(fir::FirOpBuilder &builder, mlir::Location loc,
186 mlir::Type xTy, mlir::Value resultBox,
187 mlir::Value n1, mlir::Value n2) {
188 mlir::func::FuncOp func;
189
190 if (xTy.isF32())
191 func = fir::runtime::getRuntimeFunc<mkRTKey(BesselJnX0_4)>(loc, builder);
192 else if (xTy.isF64())
193 func = fir::runtime::getRuntimeFunc<mkRTKey(BesselJnX0_8)>(loc, builder);
194 else if (xTy.isF80())
195 func = fir::runtime::getRuntimeFunc<ForcedBesselJnX0_10>(loc, builder);
196 else if (xTy.isF128())
197 func = fir::runtime::getRuntimeFunc<ForcedBesselJnX0_16>(loc, builder);
198 else
199 fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_JN");
200
201 auto fTy = func.getFunctionType();
202 auto sourceFile = fir::factory::locationToFilename(builder, loc);
203 auto sourceLine =
204 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
205 auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, n1,
206 n2, sourceFile, sourceLine);
207 builder.create<fir::CallOp>(loc, func, args);
208}
209
210/// Generate call to `BesselYn` intrinsic.
211void fir::runtime::genBesselYn(fir::FirOpBuilder &builder, mlir::Location loc,
212 mlir::Value resultBox, mlir::Value n1,
213 mlir::Value n2, mlir::Value x, mlir::Value bn1,
214 mlir::Value bn1_1) {
215 mlir::func::FuncOp func;
216 auto xTy = x.getType();
217
218 if (xTy.isF32())
219 func = fir::runtime::getRuntimeFunc<mkRTKey(BesselYn_4)>(loc, builder);
220 else if (xTy.isF64())
221 func = fir::runtime::getRuntimeFunc<mkRTKey(BesselYn_8)>(loc, builder);
222 else if (xTy.isF80())
223 func = fir::runtime::getRuntimeFunc<ForcedBesselYn_10>(loc, builder);
224 else if (xTy.isF128())
225 func = fir::runtime::getRuntimeFunc<ForcedBesselYn_16>(loc, builder);
226 else
227 fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_YN");
228
229 auto fTy = func.getFunctionType();
230 auto sourceFile = fir::factory::locationToFilename(builder, loc);
231 auto sourceLine =
232 fir::factory::locationToLineNo(builder, loc, fTy.getInput(7));
233 auto args =
234 fir::runtime::createArguments(builder, loc, fTy, resultBox, n1, n2, x,
235 bn1, bn1_1, sourceFile, sourceLine);
236 builder.create<fir::CallOp>(loc, func, args);
237}
238
239/// Generate call to `BesselYn` intrinsic. This is used when `x == 0.0`.
240void fir::runtime::genBesselYnX0(fir::FirOpBuilder &builder, mlir::Location loc,
241 mlir::Type xTy, mlir::Value resultBox,
242 mlir::Value n1, mlir::Value n2) {
243 mlir::func::FuncOp func;
244
245 if (xTy.isF32())
246 func = fir::runtime::getRuntimeFunc<mkRTKey(BesselYnX0_4)>(loc, builder);
247 else if (xTy.isF64())
248 func = fir::runtime::getRuntimeFunc<mkRTKey(BesselYnX0_8)>(loc, builder);
249 else if (xTy.isF80())
250 func = fir::runtime::getRuntimeFunc<ForcedBesselYnX0_10>(loc, builder);
251 else if (xTy.isF128())
252 func = fir::runtime::getRuntimeFunc<ForcedBesselYnX0_16>(loc, builder);
253 else
254 fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_YN");
255
256 auto fTy = func.getFunctionType();
257 auto sourceFile = fir::factory::locationToFilename(builder, loc);
258 auto sourceLine =
259 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
260 auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, n1,
261 n2, sourceFile, sourceLine);
262 builder.create<fir::CallOp>(loc, func, args);
263}
264
265/// Generate call to Cshift intrinsic
266void fir::runtime::genCshift(fir::FirOpBuilder &builder, mlir::Location loc,
267 mlir::Value resultBox, mlir::Value arrayBox,
268 mlir::Value shiftBox, mlir::Value dimBox) {
269 auto cshiftFunc = fir::runtime::getRuntimeFunc<mkRTKey(Cshift)>(loc, builder);
270 auto fTy = cshiftFunc.getFunctionType();
271 auto sourceFile = fir::factory::locationToFilename(builder, loc);
272 auto sourceLine =
273 fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
274 auto args =
275 fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
276 shiftBox, dimBox, sourceFile, sourceLine);
277 builder.create<fir::CallOp>(loc, cshiftFunc, args);
278}
279
280/// Generate call to the vector version of the Cshift intrinsic
281void fir::runtime::genCshiftVector(fir::FirOpBuilder &builder,
282 mlir::Location loc, mlir::Value resultBox,
283 mlir::Value arrayBox, mlir::Value shiftBox) {
284 auto cshiftFunc =
285 fir::runtime::getRuntimeFunc<mkRTKey(CshiftVector)>(loc, builder);
286 auto fTy = cshiftFunc.getFunctionType();
287
288 auto sourceFile = fir::factory::locationToFilename(builder, loc);
289 auto sourceLine =
290 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
291 auto args = fir::runtime::createArguments(
292 builder, loc, fTy, resultBox, arrayBox, shiftBox, sourceFile, sourceLine);
293 builder.create<fir::CallOp>(loc, cshiftFunc, args);
294}
295
296/// Generate call to Eoshift intrinsic
297void fir::runtime::genEoshift(fir::FirOpBuilder &builder, mlir::Location loc,
298 mlir::Value resultBox, mlir::Value arrayBox,
299 mlir::Value shiftBox, mlir::Value boundBox,
300 mlir::Value dimBox) {
301 auto eoshiftFunc =
302 fir::runtime::getRuntimeFunc<mkRTKey(Eoshift)>(loc, builder);
303 auto fTy = eoshiftFunc.getFunctionType();
304 auto sourceFile = fir::factory::locationToFilename(builder, loc);
305 auto sourceLine =
306 fir::factory::locationToLineNo(builder, loc, fTy.getInput(6));
307 auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
308 arrayBox, shiftBox, boundBox,
309 dimBox, sourceFile, sourceLine);
310 builder.create<fir::CallOp>(loc, eoshiftFunc, args);
311}
312
313/// Generate call to the vector version of the Eoshift intrinsic
314void fir::runtime::genEoshiftVector(fir::FirOpBuilder &builder,
315 mlir::Location loc, mlir::Value resultBox,
316 mlir::Value arrayBox, mlir::Value shiftBox,
317 mlir::Value boundBox) {
318 auto eoshiftFunc =
319 fir::runtime::getRuntimeFunc<mkRTKey(EoshiftVector)>(loc, builder);
320 auto fTy = eoshiftFunc.getFunctionType();
321
322 auto sourceFile = fir::factory::locationToFilename(builder, loc);
323 auto sourceLine =
324 fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
325
326 auto args =
327 fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
328 shiftBox, boundBox, sourceFile, sourceLine);
329 builder.create<fir::CallOp>(loc, eoshiftFunc, args);
330}
331
332/// Generate call to Matmul intrinsic runtime routine.
333void fir::runtime::genMatmul(fir::FirOpBuilder &builder, mlir::Location loc,
334 mlir::Value resultBox, mlir::Value matrixABox,
335 mlir::Value matrixBBox) {
336 auto func = fir::runtime::getRuntimeFunc<mkRTKey(Matmul)>(loc, builder);
337 auto fTy = func.getFunctionType();
338 auto sourceFile = fir::factory::locationToFilename(builder, loc);
339 auto sourceLine =
340 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
341 auto args =
342 fir::runtime::createArguments(builder, loc, fTy, resultBox, matrixABox,
343 matrixBBox, sourceFile, sourceLine);
344 builder.create<fir::CallOp>(loc, func, args);
345}
346
347/// Generate call to MatmulTranspose intrinsic runtime routine.
348void fir::runtime::genMatmulTranspose(fir::FirOpBuilder &builder,
349 mlir::Location loc, mlir::Value resultBox,
350 mlir::Value matrixABox,
351 mlir::Value matrixBBox) {
352 auto func =
353 fir::runtime::getRuntimeFunc<mkRTKey(MatmulTranspose)>(loc, builder);
354 auto fTy = func.getFunctionType();
355 auto sourceFile = fir::factory::locationToFilename(builder, loc);
356 auto sourceLine =
357 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
358 auto args =
359 fir::runtime::createArguments(builder, loc, fTy, resultBox, matrixABox,
360 matrixBBox, sourceFile, sourceLine);
361 builder.create<fir::CallOp>(loc, func, args);
362}
363
364/// Generate call to Pack intrinsic runtime routine.
365void fir::runtime::genPack(fir::FirOpBuilder &builder, mlir::Location loc,
366 mlir::Value resultBox, mlir::Value arrayBox,
367 mlir::Value maskBox, mlir::Value vectorBox) {
368 auto packFunc = fir::runtime::getRuntimeFunc<mkRTKey(Pack)>(loc, builder);
369 auto fTy = packFunc.getFunctionType();
370 auto sourceFile = fir::factory::locationToFilename(builder, loc);
371 auto sourceLine =
372 fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
373 auto args =
374 fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
375 maskBox, vectorBox, sourceFile, sourceLine);
376 builder.create<fir::CallOp>(loc, packFunc, args);
377}
378
379/// Generate call to Reshape intrinsic runtime routine.
380void fir::runtime::genReshape(fir::FirOpBuilder &builder, mlir::Location loc,
381 mlir::Value resultBox, mlir::Value sourceBox,
382 mlir::Value shapeBox, mlir::Value padBox,
383 mlir::Value orderBox) {
384 auto func = fir::runtime::getRuntimeFunc<mkRTKey(Reshape)>(loc, builder);
385 auto fTy = func.getFunctionType();
386 auto sourceFile = fir::factory::locationToFilename(builder, loc);
387 auto sourceLine =
388 fir::factory::locationToLineNo(builder, loc, fTy.getInput(6));
389 auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
390 sourceBox, shapeBox, padBox,
391 orderBox, sourceFile, sourceLine);
392 builder.create<fir::CallOp>(loc, func, args);
393}
394
395/// Generate call to Spread intrinsic runtime routine.
396void fir::runtime::genSpread(fir::FirOpBuilder &builder, mlir::Location loc,
397 mlir::Value resultBox, mlir::Value sourceBox,
398 mlir::Value dim, mlir::Value ncopies) {
399 auto func = fir::runtime::getRuntimeFunc<mkRTKey(Spread)>(loc, builder);
400 auto fTy = func.getFunctionType();
401 auto sourceFile = fir::factory::locationToFilename(builder, loc);
402 auto sourceLine =
403 fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
404 auto args =
405 fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox,
406 dim, ncopies, sourceFile, sourceLine);
407 builder.create<fir::CallOp>(loc, func, args);
408}
409
410/// Generate call to Transpose intrinsic runtime routine.
411void fir::runtime::genTranspose(fir::FirOpBuilder &builder, mlir::Location loc,
412 mlir::Value resultBox, mlir::Value sourceBox) {
413 auto func = fir::runtime::getRuntimeFunc<mkRTKey(Transpose)>(loc, builder);
414 auto fTy = func.getFunctionType();
415 auto sourceFile = fir::factory::locationToFilename(builder, loc);
416 auto sourceLine =
417 fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
418 auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
419 sourceBox, sourceFile, sourceLine);
420 builder.create<fir::CallOp>(loc, func, args);
421}
422
423/// Generate call to Unpack intrinsic runtime routine.
424void fir::runtime::genUnpack(fir::FirOpBuilder &builder, mlir::Location loc,
425 mlir::Value resultBox, mlir::Value vectorBox,
426 mlir::Value maskBox, mlir::Value fieldBox) {
427 auto unpackFunc = fir::runtime::getRuntimeFunc<mkRTKey(Unpack)>(loc, builder);
428 auto fTy = unpackFunc.getFunctionType();
429 auto sourceFile = fir::factory::locationToFilename(builder, loc);
430 auto sourceLine =
431 fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
432 auto args =
433 fir::runtime::createArguments(builder, loc, fTy, resultBox, vectorBox,
434 maskBox, fieldBox, sourceFile, sourceLine);
435 builder.create<fir::CallOp>(loc, unpackFunc, args);
436}
437

source code of flang/lib/Optimizer/Builder/Runtime/Transformational.cpp