xref: /llvm-project/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp (revision 12ba74e181bd6641b532e271f3bfabf53066b1c0)
1 //===-- Reduction.cpp -- generate reduction intrinsics runtime calls- -----===//
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 #include "flang/Optimizer/Builder/Runtime/Reduction.h"
10 #include "flang/Optimizer/Builder/BoxValue.h"
11 #include "flang/Optimizer/Builder/Character.h"
12 #include "flang/Optimizer/Builder/FIRBuilder.h"
13 #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
14 #include "flang/Optimizer/Support/Utils.h"
15 #include "flang/Runtime/reduce.h"
16 #include "flang/Runtime/reduction.h"
17 #include "mlir/Dialect/Func/IR/FuncOps.h"
18 
19 using namespace Fortran::runtime;
20 
21 #define STRINGIFY(S) #S
22 #define JOIN2(A, B) A##B
23 #define JOIN3(A, B, C) A##B##C
24 
25 /// Placeholder for real*10 version of Maxval Intrinsic
26 struct ForcedMaxvalReal10 {
27   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MaxvalReal10));
28   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
29     return [](mlir::MLIRContext *ctx) {
30       auto ty = mlir::Float80Type::get(ctx);
31       auto boxTy =
32           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
33       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
34       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
35       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
36                                      {ty});
37     };
38   }
39 };
40 
41 /// Placeholder for real*16 version of Maxval Intrinsic
42 struct ForcedMaxvalReal16 {
43   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MaxvalReal16));
44   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
45     return [](mlir::MLIRContext *ctx) {
46       auto ty = mlir::Float128Type::get(ctx);
47       auto boxTy =
48           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
49       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
50       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
51       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
52                                      {ty});
53     };
54   }
55 };
56 
57 /// Placeholder for integer*16 version of Maxval Intrinsic
58 struct ForcedMaxvalInteger16 {
59   static constexpr const char *name =
60       ExpandAndQuoteKey(RTNAME(MaxvalInteger16));
61   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
62     return [](mlir::MLIRContext *ctx) {
63       auto ty = mlir::IntegerType::get(ctx, 128);
64       auto boxTy =
65           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
66       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
67       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
68       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
69                                      {ty});
70     };
71   }
72 };
73 
74 /// Placeholder for unsigned*16 version of Maxval Intrinsic
75 struct ForcedMaxvalUnsigned16 {
76   static constexpr const char *name =
77       ExpandAndQuoteKey(RTNAME(MaxvalUnsigned16));
78   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
79     return [](mlir::MLIRContext *ctx) {
80       auto ty = mlir::IntegerType::get(
81           ctx, 128, mlir::IntegerType::SignednessSemantics::Unsigned);
82       auto boxTy =
83           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
84       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
85       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
86       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
87                                      {ty});
88     };
89   }
90 };
91 
92 /// Placeholder for real*10 version of Minval Intrinsic
93 struct ForcedMinvalReal10 {
94   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MinvalReal10));
95   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
96     return [](mlir::MLIRContext *ctx) {
97       auto ty = mlir::Float80Type::get(ctx);
98       auto boxTy =
99           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
100       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
101       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
102       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
103                                      {ty});
104     };
105   }
106 };
107 
108 /// Placeholder for real*16 version of Minval Intrinsic
109 struct ForcedMinvalReal16 {
110   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MinvalReal16));
111   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
112     return [](mlir::MLIRContext *ctx) {
113       auto ty = mlir::Float128Type::get(ctx);
114       auto boxTy =
115           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
116       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
117       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
118       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
119                                      {ty});
120     };
121   }
122 };
123 
124 /// Placeholder for integer*16 version of Minval Intrinsic
125 struct ForcedMinvalInteger16 {
126   static constexpr const char *name =
127       ExpandAndQuoteKey(RTNAME(MinvalInteger16));
128   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
129     return [](mlir::MLIRContext *ctx) {
130       auto ty = mlir::IntegerType::get(ctx, 128);
131       auto boxTy =
132           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
133       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
134       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
135       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
136                                      {ty});
137     };
138   }
139 };
140 
141 /// Placeholder for unsigned*16 version of Minval Intrinsic
142 struct ForcedMinvalUnsigned16 {
143   static constexpr const char *name =
144       ExpandAndQuoteKey(RTNAME(MinvalUnsigned16));
145   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
146     return [](mlir::MLIRContext *ctx) {
147       auto ty = mlir::IntegerType::get(
148           ctx, 128, mlir::IntegerType::SignednessSemantics::Unsigned);
149       auto boxTy =
150           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
151       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
152       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
153       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
154                                      {ty});
155     };
156   }
157 };
158 
159 // Maxloc/Minloc take descriptor, so these runtime signature are not ifdef
160 // and the mkRTKey can safely be used here. Define alias so that the
161 // REAL_INTRINSIC_INSTANCES macro works with them too
162 using ForcedMaxlocReal10 = mkRTKey(MaxlocReal10);
163 using ForcedMaxlocReal16 = mkRTKey(MaxlocReal16);
164 using ForcedMaxlocInteger16 = mkRTKey(MaxlocInteger16);
165 using ForcedMaxlocUnsigned16 = mkRTKey(MaxlocUnsigned16);
166 using ForcedMinlocReal10 = mkRTKey(MinlocReal10);
167 using ForcedMinlocReal16 = mkRTKey(MinlocReal16);
168 using ForcedMinlocInteger16 = mkRTKey(MinlocInteger16);
169 using ForcedMinlocUnsigned16 = mkRTKey(MinlocUnsigned16);
170 
171 /// Placeholder for real*10 version of Norm2 Intrinsic
172 struct ForcedNorm2Real10 {
173   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Norm2_10));
174   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
175     return [](mlir::MLIRContext *ctx) {
176       auto ty = mlir::Float80Type::get(ctx);
177       auto boxTy =
178           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
179       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
180       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
181       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy}, {ty});
182     };
183   }
184 };
185 
186 /// Placeholder for real*16 version of Norm2 Intrinsic
187 struct ForcedNorm2Real16 {
188   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Norm2_16));
189   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
190     return [](mlir::MLIRContext *ctx) {
191       auto ty = mlir::Float128Type::get(ctx);
192       auto boxTy =
193           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
194       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
195       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
196       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy}, {ty});
197     };
198   }
199 };
200 
201 /// Placeholder for real*16 version of Norm2Dim Intrinsic
202 struct ForcedNorm2DimReal16 {
203   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Norm2DimReal16));
204   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
205     return [](mlir::MLIRContext *ctx) {
206       auto boxTy =
207           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
208       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
209       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
210       return mlir::FunctionType::get(
211           ctx, {fir::ReferenceType::get(boxTy), boxTy, intTy, strTy, intTy},
212           {});
213     };
214   }
215 };
216 
217 /// Placeholder for real*10 version of Product Intrinsic
218 struct ForcedProductReal10 {
219   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ProductReal10));
220   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
221     return [](mlir::MLIRContext *ctx) {
222       auto ty = mlir::Float80Type::get(ctx);
223       auto boxTy =
224           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
225       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
226       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
227       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
228                                      {ty});
229     };
230   }
231 };
232 
233 /// Placeholder for real*16 version of Product Intrinsic
234 struct ForcedProductReal16 {
235   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ProductReal16));
236   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
237     return [](mlir::MLIRContext *ctx) {
238       auto ty = mlir::Float128Type::get(ctx);
239       auto boxTy =
240           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
241       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
242       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
243       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
244                                      {ty});
245     };
246   }
247 };
248 
249 /// Placeholder for integer*16 version of Product Intrinsic
250 struct ForcedProductInteger16 {
251   static constexpr const char *name =
252       ExpandAndQuoteKey(RTNAME(ProductInteger16));
253   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
254     return [](mlir::MLIRContext *ctx) {
255       auto ty = mlir::IntegerType::get(ctx, 128);
256       auto boxTy =
257           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
258       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
259       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
260       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
261                                      {ty});
262     };
263   }
264 };
265 
266 /// Placeholder for unsigned*16 version of Product Intrinsic
267 struct ForcedProductUnsigned16 {
268   static constexpr const char *name =
269       ExpandAndQuoteKey(RTNAME(ProductUnsigned16));
270   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
271     return [](mlir::MLIRContext *ctx) {
272       auto ty = mlir::IntegerType::get(
273           ctx, 128, mlir::IntegerType::SignednessSemantics::Unsigned);
274       auto boxTy =
275           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
276       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
277       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
278       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
279                                      {ty});
280     };
281   }
282 };
283 
284 /// Placeholder for complex(10) version of Product Intrinsic
285 struct ForcedProductComplex10 {
286   static constexpr const char *name =
287       ExpandAndQuoteKey(RTNAME(CppProductComplex10));
288   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
289     return [](mlir::MLIRContext *ctx) {
290       auto ty = mlir::ComplexType::get(mlir::Float80Type::get(ctx));
291       auto boxTy =
292           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
293       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
294       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
295       auto resTy = fir::ReferenceType::get(ty);
296       return mlir::FunctionType::get(
297           ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {});
298     };
299   }
300 };
301 
302 /// Placeholder for complex(16) version of Product Intrinsic
303 struct ForcedProductComplex16 {
304   static constexpr const char *name =
305       ExpandAndQuoteKey(RTNAME(CppProductComplex16));
306   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
307     return [](mlir::MLIRContext *ctx) {
308       auto ty = mlir::ComplexType::get(mlir::Float128Type::get(ctx));
309       auto boxTy =
310           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
311       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
312       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
313       auto resTy = fir::ReferenceType::get(ty);
314       return mlir::FunctionType::get(
315           ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {});
316     };
317   }
318 };
319 
320 /// Placeholder for real*10 version of DotProduct Intrinsic
321 struct ForcedDotProductReal10 {
322   static constexpr const char *name =
323       ExpandAndQuoteKey(RTNAME(DotProductReal10));
324   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
325     return [](mlir::MLIRContext *ctx) {
326       auto ty = mlir::Float80Type::get(ctx);
327       auto boxTy =
328           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
329       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
330       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
331       return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty});
332     };
333   }
334 };
335 
336 /// Placeholder for real*16 version of DotProduct Intrinsic
337 struct ForcedDotProductReal16 {
338   static constexpr const char *name =
339       ExpandAndQuoteKey(RTNAME(DotProductReal16));
340   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
341     return [](mlir::MLIRContext *ctx) {
342       auto ty = mlir::Float128Type::get(ctx);
343       auto boxTy =
344           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
345       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
346       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
347       return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty});
348     };
349   }
350 };
351 
352 /// Placeholder for complex(10) version of DotProduct Intrinsic
353 struct ForcedDotProductComplex10 {
354   static constexpr const char *name =
355       ExpandAndQuoteKey(RTNAME(CppDotProductComplex10));
356   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
357     return [](mlir::MLIRContext *ctx) {
358       auto ty = mlir::ComplexType::get(mlir::Float80Type::get(ctx));
359       auto boxTy =
360           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
361       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
362       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
363       auto resTy = fir::ReferenceType::get(ty);
364       return mlir::FunctionType::get(ctx, {resTy, boxTy, boxTy, strTy, intTy},
365                                      {});
366     };
367   }
368 };
369 
370 /// Placeholder for complex(16) version of DotProduct Intrinsic
371 struct ForcedDotProductComplex16 {
372   static constexpr const char *name =
373       ExpandAndQuoteKey(RTNAME(CppDotProductComplex16));
374   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
375     return [](mlir::MLIRContext *ctx) {
376       auto ty = mlir::ComplexType::get(mlir::Float128Type::get(ctx));
377       auto boxTy =
378           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
379       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
380       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
381       auto resTy = fir::ReferenceType::get(ty);
382       return mlir::FunctionType::get(ctx, {resTy, boxTy, boxTy, strTy, intTy},
383                                      {});
384     };
385   }
386 };
387 
388 /// Placeholder for integer*16 version of DotProduct Intrinsic
389 struct ForcedDotProductInteger16 {
390   static constexpr const char *name =
391       ExpandAndQuoteKey(RTNAME(DotProductInteger16));
392   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
393     return [](mlir::MLIRContext *ctx) {
394       auto ty = mlir::IntegerType::get(ctx, 128);
395       auto boxTy =
396           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
397       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
398       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
399       return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty});
400     };
401   }
402 };
403 
404 /// Placeholder for unsigned*16 version of DotProduct Intrinsic
405 struct ForcedDotProductUnsigned16 {
406   static constexpr const char *name =
407       ExpandAndQuoteKey(RTNAME(DotProductUnsigned16));
408   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
409     return [](mlir::MLIRContext *ctx) {
410       auto ty = mlir::IntegerType::get(
411           ctx, 128, mlir::IntegerType::SignednessSemantics::Unsigned);
412       auto boxTy =
413           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
414       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
415       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
416       return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty});
417     };
418   }
419 };
420 
421 /// Placeholder for real*10 version of Sum Intrinsic
422 struct ForcedSumReal10 {
423   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumReal10));
424   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
425     return [](mlir::MLIRContext *ctx) {
426       auto ty = mlir::Float80Type::get(ctx);
427       auto boxTy =
428           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
429       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
430       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
431       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
432                                      {ty});
433     };
434   }
435 };
436 
437 /// Placeholder for real*16 version of Sum Intrinsic
438 struct ForcedSumReal16 {
439   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumReal16));
440   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
441     return [](mlir::MLIRContext *ctx) {
442       auto ty = mlir::Float128Type::get(ctx);
443       auto boxTy =
444           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
445       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
446       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
447       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
448                                      {ty});
449     };
450   }
451 };
452 
453 /// Placeholder for integer*16 version of Sum Intrinsic
454 struct ForcedSumInteger16 {
455   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumInteger16));
456   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
457     return [](mlir::MLIRContext *ctx) {
458       auto ty = mlir::IntegerType::get(ctx, 128);
459       auto boxTy =
460           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
461       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
462       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
463       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
464                                      {ty});
465     };
466   }
467 };
468 
469 /// Placeholder for unsigned*16 version of Sum Intrinsic
470 struct ForcedSumUnsigned16 {
471   static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumUnsigned16));
472   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
473     return [](mlir::MLIRContext *ctx) {
474       auto ty = mlir::IntegerType::get(
475           ctx, 128, mlir::IntegerType::SignednessSemantics::Unsigned);
476       auto boxTy =
477           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
478       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
479       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
480       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
481                                      {ty});
482     };
483   }
484 };
485 
486 /// Placeholder for complex(10) version of Sum Intrinsic
487 struct ForcedSumComplex10 {
488   static constexpr const char *name =
489       ExpandAndQuoteKey(RTNAME(CppSumComplex10));
490   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
491     return [](mlir::MLIRContext *ctx) {
492       auto ty = mlir::ComplexType::get(mlir::Float80Type::get(ctx));
493       auto boxTy =
494           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
495       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
496       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
497       auto resTy = fir::ReferenceType::get(ty);
498       return mlir::FunctionType::get(
499           ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {});
500     };
501   }
502 };
503 
504 /// Placeholder for complex(16) version of Sum Intrinsic
505 struct ForcedSumComplex16 {
506   static constexpr const char *name =
507       ExpandAndQuoteKey(RTNAME(CppSumComplex16));
508   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
509     return [](mlir::MLIRContext *ctx) {
510       auto ty = mlir::ComplexType::get(mlir::Float128Type::get(ctx));
511       auto boxTy =
512           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
513       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
514       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
515       auto resTy = fir::ReferenceType::get(ty);
516       return mlir::FunctionType::get(
517           ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {});
518     };
519   }
520 };
521 
522 /// Placeholder for integer(16) version of IAll Intrinsic
523 struct ForcedIAll16 {
524   static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IAll16);
525   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
526     return [](mlir::MLIRContext *ctx) {
527       auto ty = mlir::IntegerType::get(ctx, 128);
528       auto boxTy =
529           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
530       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
531       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
532       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
533                                      {ty});
534     };
535   }
536 };
537 
538 /// Placeholder for integer(16) version of IAny Intrinsic
539 struct ForcedIAny16 {
540   static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IAny16);
541   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
542     return [](mlir::MLIRContext *ctx) {
543       auto ty = mlir::IntegerType::get(ctx, 128);
544       auto boxTy =
545           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
546       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
547       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
548       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
549                                      {ty});
550     };
551   }
552 };
553 
554 /// Placeholder for integer(16) version of IParity Intrinsic
555 struct ForcedIParity16 {
556   static constexpr const char *name = EXPAND_AND_QUOTE_KEY(IParity16);
557   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
558     return [](mlir::MLIRContext *ctx) {
559       auto ty = mlir::IntegerType::get(ctx, 128);
560       auto boxTy =
561           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
562       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
563       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
564       return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
565                                      {ty});
566     };
567   }
568 };
569 
570 /// Placeholder for real*10 version of Reduce Intrinsic
571 struct ForcedReduceReal10Ref {
572   static constexpr const char *name =
573       ExpandAndQuoteKey(RTNAME(ReduceReal10Ref));
574   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
575     return [](mlir::MLIRContext *ctx) {
576       auto ty = mlir::Float80Type::get(ctx);
577       auto boxTy =
578           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
579       auto refTy = fir::ReferenceType::get(ty);
580       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
581       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
582       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
583       auto i1Ty = mlir::IntegerType::get(ctx, 1);
584       return mlir::FunctionType::get(
585           ctx, {boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty}, {ty});
586     };
587   }
588 };
589 
590 /// Placeholder for real*10 version of Reduce Intrinsic
591 struct ForcedReduceReal10Value {
592   static constexpr const char *name =
593       ExpandAndQuoteKey(RTNAME(ReduceReal10Value));
594   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
595     return [](mlir::MLIRContext *ctx) {
596       auto ty = mlir::Float80Type::get(ctx);
597       auto boxTy =
598           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
599       auto refTy = fir::ReferenceType::get(ty);
600       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
601       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
602       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
603       auto i1Ty = mlir::IntegerType::get(ctx, 1);
604       return mlir::FunctionType::get(
605           ctx, {boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty}, {ty});
606     };
607   }
608 };
609 
610 /// Placeholder for real*16 version of Reduce Intrinsic
611 struct ForcedReduceReal16Ref {
612   static constexpr const char *name =
613       ExpandAndQuoteKey(RTNAME(ReduceReal16Ref));
614   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
615     return [](mlir::MLIRContext *ctx) {
616       auto ty = mlir::Float128Type::get(ctx);
617       auto boxTy =
618           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
619       auto refTy = fir::ReferenceType::get(ty);
620       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
621       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
622       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
623       auto i1Ty = mlir::IntegerType::get(ctx, 1);
624       return mlir::FunctionType::get(
625           ctx, {boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty}, {ty});
626     };
627   }
628 };
629 
630 /// Placeholder for real*16 version of Reduce Intrinsic
631 struct ForcedReduceReal16Value {
632   static constexpr const char *name =
633       ExpandAndQuoteKey(RTNAME(ReduceReal16Value));
634   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
635     return [](mlir::MLIRContext *ctx) {
636       auto ty = mlir::Float128Type::get(ctx);
637       auto boxTy =
638           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
639       auto refTy = fir::ReferenceType::get(ty);
640       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
641       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
642       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
643       auto i1Ty = mlir::IntegerType::get(ctx, 1);
644       return mlir::FunctionType::get(
645           ctx, {boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty}, {ty});
646     };
647   }
648 };
649 
650 /// Placeholder for DIM real*10 version of Reduce Intrinsic
651 struct ForcedReduceReal10DimRef {
652   static constexpr const char *name =
653       ExpandAndQuoteKey(RTNAME(ReduceReal10DimRef));
654   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
655     return [](mlir::MLIRContext *ctx) {
656       auto ty = mlir::Float80Type::get(ctx);
657       auto boxTy =
658           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
659       auto refTy = fir::ReferenceType::get(ty);
660       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
661       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
662       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
663       auto refBoxTy = fir::ReferenceType::get(boxTy);
664       auto i1Ty = mlir::IntegerType::get(ctx, 1);
665       return mlir::FunctionType::get(
666           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
667           {});
668     };
669   }
670 };
671 
672 /// Placeholder for DIM real*10 with value version of Reduce Intrinsic
673 struct ForcedReduceReal10DimValue {
674   static constexpr const char *name =
675       ExpandAndQuoteKey(RTNAME(ReduceReal10DimValue));
676   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
677     return [](mlir::MLIRContext *ctx) {
678       auto ty = mlir::Float80Type::get(ctx);
679       auto boxTy =
680           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
681       auto refTy = fir::ReferenceType::get(ty);
682       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
683       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
684       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
685       auto refBoxTy = fir::ReferenceType::get(boxTy);
686       auto i1Ty = mlir::IntegerType::get(ctx, 1);
687       return mlir::FunctionType::get(
688           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
689           {});
690     };
691   }
692 };
693 
694 /// Placeholder for DIM real*16 version of Reduce Intrinsic
695 struct ForcedReduceReal16DimRef {
696   static constexpr const char *name =
697       ExpandAndQuoteKey(RTNAME(ReduceReal16DimRef));
698   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
699     return [](mlir::MLIRContext *ctx) {
700       auto ty = mlir::Float128Type::get(ctx);
701       auto boxTy =
702           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
703       auto refTy = fir::ReferenceType::get(ty);
704       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
705       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
706       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
707       auto refBoxTy = fir::ReferenceType::get(boxTy);
708       auto i1Ty = mlir::IntegerType::get(ctx, 1);
709       return mlir::FunctionType::get(
710           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
711           {});
712     };
713   }
714 };
715 
716 /// Placeholder for DIM real*16 with value version of Reduce Intrinsic
717 struct ForcedReduceReal16DimValue {
718   static constexpr const char *name =
719       ExpandAndQuoteKey(RTNAME(ReduceReal16DimValue));
720   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
721     return [](mlir::MLIRContext *ctx) {
722       auto ty = mlir::Float128Type::get(ctx);
723       auto boxTy =
724           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
725       auto refTy = fir::ReferenceType::get(ty);
726       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
727       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
728       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
729       auto refBoxTy = fir::ReferenceType::get(boxTy);
730       auto i1Ty = mlir::IntegerType::get(ctx, 1);
731       return mlir::FunctionType::get(
732           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
733           {});
734     };
735   }
736 };
737 
738 /// Placeholder for integer*16 version of Reduce Intrinsic
739 struct ForcedReduceInteger16Ref {
740   static constexpr const char *name =
741       ExpandAndQuoteKey(RTNAME(ReduceInteger16Ref));
742   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
743     return [](mlir::MLIRContext *ctx) {
744       auto ty = mlir::IntegerType::get(ctx, 128);
745       auto boxTy =
746           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
747       auto refTy = fir::ReferenceType::get(ty);
748       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
749       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
750       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
751       auto i1Ty = mlir::IntegerType::get(ctx, 1);
752       return mlir::FunctionType::get(
753           ctx, {boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty}, {ty});
754     };
755   }
756 };
757 
758 /// Placeholder for unsigned*16 version of Reduce Intrinsic
759 struct ForcedReduceUnsigned16Ref {
760   static constexpr const char *name =
761       ExpandAndQuoteKey(RTNAME(ReduceUnsigned16Ref));
762   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
763     return [](mlir::MLIRContext *ctx) {
764       auto ty = mlir::IntegerType::get(ctx, 128);
765       auto boxTy =
766           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
767       auto refTy = fir::ReferenceType::get(ty);
768       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
769       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
770       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
771       auto i1Ty = mlir::IntegerType::get(ctx, 1);
772       return mlir::FunctionType::get(
773           ctx, {boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty}, {ty});
774     };
775   }
776 };
777 
778 /// Placeholder for integer*16 with value version of Reduce Intrinsic
779 struct ForcedReduceInteger16Value {
780   static constexpr const char *name =
781       ExpandAndQuoteKey(RTNAME(ReduceInteger16Value));
782   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
783     return [](mlir::MLIRContext *ctx) {
784       auto ty = mlir::IntegerType::get(ctx, 128);
785       auto boxTy =
786           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
787       auto refTy = fir::ReferenceType::get(ty);
788       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
789       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
790       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
791       auto i1Ty = mlir::IntegerType::get(ctx, 1);
792       return mlir::FunctionType::get(
793           ctx, {boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty}, {ty});
794     };
795   }
796 };
797 
798 /// Placeholder for unsigned*16 with value version of Reduce Intrinsic
799 struct ForcedReduceUnsigned16Value {
800   static constexpr const char *name =
801       ExpandAndQuoteKey(RTNAME(ReduceUnsigned16Value));
802   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
803     return [](mlir::MLIRContext *ctx) {
804       auto ty = mlir::IntegerType::get(ctx, 128);
805       auto boxTy =
806           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
807       auto refTy = fir::ReferenceType::get(ty);
808       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
809       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
810       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
811       auto i1Ty = mlir::IntegerType::get(ctx, 1);
812       return mlir::FunctionType::get(
813           ctx, {boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty}, {ty});
814     };
815   }
816 };
817 
818 /// Placeholder for DIM integer*16 version of Reduce Intrinsic
819 struct ForcedReduceInteger16DimRef {
820   static constexpr const char *name =
821       ExpandAndQuoteKey(RTNAME(ReduceInteger16DimRef));
822   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
823     return [](mlir::MLIRContext *ctx) {
824       auto ty = mlir::IntegerType::get(ctx, 128);
825       auto boxTy =
826           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
827       auto refTy = fir::ReferenceType::get(ty);
828       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
829       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
830       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
831       auto refBoxTy = fir::ReferenceType::get(boxTy);
832       auto i1Ty = mlir::IntegerType::get(ctx, 1);
833       return mlir::FunctionType::get(
834           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
835           {});
836     };
837   }
838 };
839 
840 /// Placeholder for DIM unsigned*16 version of Reduce Intrinsic
841 struct ForcedReduceUnsigned16DimRef {
842   static constexpr const char *name =
843       ExpandAndQuoteKey(RTNAME(ReduceUnsigned16DimRef));
844   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
845     return [](mlir::MLIRContext *ctx) {
846       auto ty = mlir::IntegerType::get(
847           ctx, 128, mlir::IntegerType::SignednessSemantics::Unsigned);
848       auto boxTy =
849           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
850       auto refTy = fir::ReferenceType::get(ty);
851       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
852       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
853       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
854       auto refBoxTy = fir::ReferenceType::get(boxTy);
855       auto i1Ty = mlir::IntegerType::get(ctx, 1);
856       return mlir::FunctionType::get(
857           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
858           {});
859     };
860   }
861 };
862 
863 /// Placeholder for DIM integer*16 with value version of Reduce Intrinsic
864 struct ForcedReduceInteger16DimValue {
865   static constexpr const char *name =
866       ExpandAndQuoteKey(RTNAME(ReduceInteger16DimValue));
867   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
868     return [](mlir::MLIRContext *ctx) {
869       auto ty = mlir::IntegerType::get(ctx, 128);
870       auto boxTy =
871           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
872       auto refTy = fir::ReferenceType::get(ty);
873       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
874       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
875       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
876       auto refBoxTy = fir::ReferenceType::get(boxTy);
877       auto i1Ty = mlir::IntegerType::get(ctx, 1);
878       return mlir::FunctionType::get(
879           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
880           {});
881     };
882   }
883 };
884 
885 /// Placeholder for DIM unsigned*16 with value version of Reduce Intrinsic
886 struct ForcedReduceUnsigned16DimValue {
887   static constexpr const char *name =
888       ExpandAndQuoteKey(RTNAME(ReduceUnsigned16DimValue));
889   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
890     return [](mlir::MLIRContext *ctx) {
891       auto ty = mlir::IntegerType::get(
892           ctx, 128, mlir::IntegerType::SignednessSemantics::Unsigned);
893       auto boxTy =
894           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
895       auto refTy = fir::ReferenceType::get(ty);
896       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
897       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
898       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
899       auto refBoxTy = fir::ReferenceType::get(boxTy);
900       auto i1Ty = mlir::IntegerType::get(ctx, 1);
901       return mlir::FunctionType::get(
902           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
903           {});
904     };
905   }
906 };
907 
908 /// Placeholder for complex(10) version of Reduce Intrinsic
909 struct ForcedReduceComplex10Ref {
910   static constexpr const char *name =
911       ExpandAndQuoteKey(RTNAME(CppReduceComplex10Ref));
912   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
913     return [](mlir::MLIRContext *ctx) {
914       auto ty = mlir::ComplexType::get(mlir::Float80Type::get(ctx));
915       auto boxTy =
916           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
917       auto refTy = fir::ReferenceType::get(ty);
918       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
919       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
920       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
921       auto i1Ty = mlir::IntegerType::get(ctx, 1);
922       return mlir::FunctionType::get(
923           ctx, {refTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
924           {});
925     };
926   }
927 };
928 
929 /// Placeholder for complex(10) with value version of Reduce Intrinsic
930 struct ForcedReduceComplex10Value {
931   static constexpr const char *name =
932       ExpandAndQuoteKey(RTNAME(CppReduceComplex10Value));
933   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
934     return [](mlir::MLIRContext *ctx) {
935       auto ty = mlir::ComplexType::get(mlir::Float80Type::get(ctx));
936       auto boxTy =
937           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
938       auto refTy = fir::ReferenceType::get(ty);
939       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
940       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
941       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
942       auto i1Ty = mlir::IntegerType::get(ctx, 1);
943       return mlir::FunctionType::get(
944           ctx, {refTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
945           {});
946     };
947   }
948 };
949 
950 /// Placeholder for Dim complex(10) version of Reduce Intrinsic
951 struct ForcedReduceComplex10DimRef {
952   static constexpr const char *name =
953       ExpandAndQuoteKey(RTNAME(CppReduceComplex10DimRef));
954   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
955     return [](mlir::MLIRContext *ctx) {
956       auto ty = mlir::ComplexType::get(mlir::Float80Type::get(ctx));
957       auto boxTy =
958           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
959       auto refTy = fir::ReferenceType::get(ty);
960       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
961       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
962       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
963       auto refBoxTy = fir::ReferenceType::get(boxTy);
964       auto i1Ty = mlir::IntegerType::get(ctx, 1);
965       return mlir::FunctionType::get(
966           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
967           {});
968     };
969   }
970 };
971 
972 /// Placeholder for Dim complex(10) with value version of Reduce Intrinsic
973 struct ForcedReduceComplex10DimValue {
974   static constexpr const char *name =
975       ExpandAndQuoteKey(RTNAME(CppReduceComplex10DimValue));
976   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
977     return [](mlir::MLIRContext *ctx) {
978       auto ty = mlir::ComplexType::get(mlir::Float80Type::get(ctx));
979       auto boxTy =
980           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
981       auto refTy = fir::ReferenceType::get(ty);
982       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
983       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
984       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
985       auto refBoxTy = fir::ReferenceType::get(boxTy);
986       auto i1Ty = mlir::IntegerType::get(ctx, 1);
987       return mlir::FunctionType::get(
988           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
989           {});
990     };
991   }
992 };
993 
994 /// Placeholder for complex(16) version of Reduce Intrinsic
995 struct ForcedReduceComplex16Ref {
996   static constexpr const char *name =
997       ExpandAndQuoteKey(RTNAME(CppReduceComplex16Ref));
998   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
999     return [](mlir::MLIRContext *ctx) {
1000       auto ty = mlir::ComplexType::get(mlir::Float128Type::get(ctx));
1001       auto boxTy =
1002           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
1003       auto refTy = fir::ReferenceType::get(ty);
1004       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
1005       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
1006       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
1007       auto i1Ty = mlir::IntegerType::get(ctx, 1);
1008       return mlir::FunctionType::get(
1009           ctx, {refTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
1010           {});
1011     };
1012   }
1013 };
1014 
1015 /// Placeholder for complex(16) with value version of Reduce Intrinsic
1016 struct ForcedReduceComplex16Value {
1017   static constexpr const char *name =
1018       ExpandAndQuoteKey(RTNAME(CppReduceComplex16Value));
1019   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
1020     return [](mlir::MLIRContext *ctx) {
1021       auto ty = mlir::ComplexType::get(mlir::Float128Type::get(ctx));
1022       auto boxTy =
1023           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
1024       auto refTy = fir::ReferenceType::get(ty);
1025       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
1026       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
1027       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
1028       auto i1Ty = mlir::IntegerType::get(ctx, 1);
1029       return mlir::FunctionType::get(
1030           ctx, {refTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
1031           {});
1032     };
1033   }
1034 };
1035 
1036 /// Placeholder for Dim complex(16) version of Reduce Intrinsic
1037 struct ForcedReduceComplex16DimRef {
1038   static constexpr const char *name =
1039       ExpandAndQuoteKey(RTNAME(CppReduceComplex16DimRef));
1040   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
1041     return [](mlir::MLIRContext *ctx) {
1042       auto ty = mlir::ComplexType::get(mlir::Float128Type::get(ctx));
1043       auto boxTy =
1044           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
1045       auto refTy = fir::ReferenceType::get(ty);
1046       auto opTy = mlir::FunctionType::get(ctx, {refTy, refTy}, refTy);
1047       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
1048       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
1049       auto refBoxTy = fir::ReferenceType::get(boxTy);
1050       auto i1Ty = mlir::IntegerType::get(ctx, 1);
1051       return mlir::FunctionType::get(
1052           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
1053           {});
1054     };
1055   }
1056 };
1057 
1058 /// Placeholder for Dim complex(16) with value version of Reduce Intrinsic
1059 struct ForcedReduceComplex16DimValue {
1060   static constexpr const char *name =
1061       ExpandAndQuoteKey(RTNAME(CppReduceComplex16DimValue));
1062   static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
1063     return [](mlir::MLIRContext *ctx) {
1064       auto ty = mlir::ComplexType::get(mlir::Float128Type::get(ctx));
1065       auto boxTy =
1066           fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
1067       auto refTy = fir::ReferenceType::get(ty);
1068       auto opTy = mlir::FunctionType::get(ctx, {ty, ty}, refTy);
1069       auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
1070       auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
1071       auto refBoxTy = fir::ReferenceType::get(boxTy);
1072       auto i1Ty = mlir::IntegerType::get(ctx, 1);
1073       return mlir::FunctionType::get(
1074           ctx, {refBoxTy, boxTy, opTy, strTy, intTy, intTy, boxTy, refTy, i1Ty},
1075           {});
1076     };
1077   }
1078 };
1079 
1080 #define INTRINSIC_INSTANCE(NAME, CAT, KIND, SUFFIX)                            \
1081   if (!func && cat == TypeCategory::CAT && kind == KIND) {                     \
1082     func = fir::runtime::getRuntimeFunc<mkRTKey(NAME##CAT##KIND##SUFFIX)>(     \
1083         loc, builder);                                                         \
1084   }
1085 #define FORCED_INTRINSIC_INSTANCE(NAME, CAT, KIND, SUFFIX)                     \
1086   if (!func && cat == TypeCategory::CAT && kind == KIND) {                     \
1087     func = fir::runtime::getRuntimeFunc<Forced##NAME##CAT##KIND##SUFFIX>(      \
1088         loc, builder);                                                         \
1089   }
1090 
1091 #define INTEGER_INTRINSIC_INSTANCES(NAME, SUFFIX)                              \
1092   INTRINSIC_INSTANCE(NAME, Integer, 1, SUFFIX)                                 \
1093   INTRINSIC_INSTANCE(NAME, Integer, 2, SUFFIX)                                 \
1094   INTRINSIC_INSTANCE(NAME, Integer, 4, SUFFIX)                                 \
1095   INTRINSIC_INSTANCE(NAME, Integer, 8, SUFFIX)                                 \
1096   FORCED_INTRINSIC_INSTANCE(NAME, Integer, 16, SUFFIX)
1097 
1098 #define UNSIGNED_INTRINSIC_INSTANCES(NAME, SUFFIX)                             \
1099   INTRINSIC_INSTANCE(NAME, Unsigned, 1, SUFFIX)                                \
1100   INTRINSIC_INSTANCE(NAME, Unsigned, 2, SUFFIX)                                \
1101   INTRINSIC_INSTANCE(NAME, Unsigned, 4, SUFFIX)                                \
1102   INTRINSIC_INSTANCE(NAME, Unsigned, 8, SUFFIX)                                \
1103   FORCED_INTRINSIC_INSTANCE(NAME, Unsigned, 16, SUFFIX)
1104 
1105 #define REAL_INTRINSIC_INSTANCES(NAME, SUFFIX)                                 \
1106   INTRINSIC_INSTANCE(NAME, Real, 4, SUFFIX)                                    \
1107   INTRINSIC_INSTANCE(NAME, Real, 8, SUFFIX)                                    \
1108   FORCED_INTRINSIC_INSTANCE(NAME, Real, 10, SUFFIX)                            \
1109   FORCED_INTRINSIC_INSTANCE(NAME, Real, 16, SUFFIX)
1110 
1111 #define COMPLEX_INTRINSIC_INSTANCES(NAME, SUFFIX)                              \
1112   INTRINSIC_INSTANCE(Cpp##NAME, Complex, 4, SUFFIX)                            \
1113   INTRINSIC_INSTANCE(Cpp##NAME, Complex, 8, SUFFIX)                            \
1114   FORCED_INTRINSIC_INSTANCE(NAME, Complex, 10, SUFFIX)                         \
1115   FORCED_INTRINSIC_INSTANCE(NAME, Complex, 16, SUFFIX)
1116 
1117 #define NUMERICAL_INTRINSIC_INSTANCES(NAME)                                    \
1118   INTEGER_INTRINSIC_INSTANCES(NAME, )                                          \
1119   UNSIGNED_INTRINSIC_INSTANCES(NAME, )                                         \
1120   REAL_INTRINSIC_INSTANCES(NAME, )                                             \
1121   COMPLEX_INTRINSIC_INSTANCES(NAME, )
1122 
1123 #define LOGICAL_INTRINSIC_INSTANCES(NAME, SUFFIX)                              \
1124   INTRINSIC_INSTANCE(NAME, Logical, 1, SUFFIX)                                 \
1125   INTRINSIC_INSTANCE(NAME, Logical, 2, SUFFIX)                                 \
1126   INTRINSIC_INSTANCE(NAME, Logical, 4, SUFFIX)                                 \
1127   INTRINSIC_INSTANCE(NAME, Logical, 8, SUFFIX)
1128 
1129 #define NUMERICAL_AND_LOGICAL_INSTANCES(NAME, SUFFIX)                          \
1130   INTEGER_INTRINSIC_INSTANCES(NAME, SUFFIX)                                    \
1131   UNSIGNED_INTRINSIC_INSTANCES(NAME, SUFFIX)                                   \
1132   REAL_INTRINSIC_INSTANCES(NAME, SUFFIX)                                       \
1133   COMPLEX_INTRINSIC_INSTANCES(NAME, SUFFIX)                                    \
1134   LOGICAL_INTRINSIC_INSTANCES(NAME, SUFFIX)
1135 
1136 // REAL/COMPLEX 2 and 3 usually have no runtime implementation, so they have
1137 // special macros.
1138 #define REAL_2_3_INTRINSIC_INSTANCES(NAME, SUFFIX)                             \
1139   INTRINSIC_INSTANCE(NAME, Real, 2, SUFFIX)                                    \
1140   INTRINSIC_INSTANCE(NAME, Real, 3, SUFFIX)
1141 
1142 #define COMPLEX_2_3_INTRINSIC_INSTANCES(NAME, SUFFIX)                          \
1143   INTRINSIC_INSTANCE(Cpp##NAME, Complex, 2, SUFFIX)                            \
1144   INTRINSIC_INSTANCE(Cpp##NAME, Complex, 3, SUFFIX)
1145 
1146 /// Generate call to specialized runtime function that takes a mask and
1147 /// dim argument. The All, Any, and Count intrinsics use this pattern.
1148 template <typename FN>
1149 mlir::Value genSpecial2Args(FN func, fir::FirOpBuilder &builder,
1150                             mlir::Location loc, mlir::Value maskBox,
1151                             mlir::Value dim) {
1152   auto fTy = func.getFunctionType();
1153   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1154   auto sourceLine =
1155       fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
1156   auto args = fir::runtime::createArguments(builder, loc, fTy, maskBox,
1157                                             sourceFile, sourceLine, dim);
1158   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
1159 }
1160 
1161 /// Generate calls to reduction intrinsics such as All and Any.
1162 /// These are the descriptor based implementations that take two
1163 /// arguments (mask, dim).
1164 template <typename FN>
1165 static void genReduction2Args(FN func, fir::FirOpBuilder &builder,
1166                               mlir::Location loc, mlir::Value resultBox,
1167                               mlir::Value maskBox, mlir::Value dim) {
1168   auto fTy = func.getFunctionType();
1169   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1170   auto sourceLine =
1171       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
1172   auto args = fir::runtime::createArguments(
1173       builder, loc, fTy, resultBox, maskBox, dim, sourceFile, sourceLine);
1174   builder.create<fir::CallOp>(loc, func, args);
1175 }
1176 
1177 /// Generate calls to reduction intrinsics such as Maxval and Minval.
1178 /// These take arguments such as (array, dim, mask).
1179 template <typename FN>
1180 static void genReduction3Args(FN func, fir::FirOpBuilder &builder,
1181                               mlir::Location loc, mlir::Value resultBox,
1182                               mlir::Value arrayBox, mlir::Value dim,
1183                               mlir::Value maskBox) {
1184 
1185   auto fTy = func.getFunctionType();
1186   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1187   auto sourceLine =
1188       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
1189   auto args =
1190       fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, dim,
1191                                     sourceFile, sourceLine, maskBox);
1192   builder.create<fir::CallOp>(loc, func, args);
1193 }
1194 
1195 /// Generate calls to reduction intrinsics such as Maxloc and Minloc.
1196 /// These take arguments such as (array, mask, kind, back).
1197 template <typename FN>
1198 static void genReduction4Args(FN func, fir::FirOpBuilder &builder,
1199                               mlir::Location loc, mlir::Value resultBox,
1200                               mlir::Value arrayBox, mlir::Value maskBox,
1201                               mlir::Value kind, mlir::Value back) {
1202   auto fTy = func.getFunctionType();
1203   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1204   auto sourceLine =
1205       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
1206   auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
1207                                             arrayBox, kind, sourceFile,
1208                                             sourceLine, maskBox, back);
1209   builder.create<fir::CallOp>(loc, func, args);
1210 }
1211 
1212 /// Generate calls to reduction intrinsics such as Maxloc and Minloc.
1213 /// These take arguments such as (array, dim, mask, kind, back).
1214 template <typename FN>
1215 static void
1216 genReduction5Args(FN func, fir::FirOpBuilder &builder, mlir::Location loc,
1217                   mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
1218                   mlir::Value maskBox, mlir::Value kind, mlir::Value back) {
1219   auto fTy = func.getFunctionType();
1220   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1221   auto sourceLine =
1222       fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
1223   auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
1224                                             arrayBox, kind, dim, sourceFile,
1225                                             sourceLine, maskBox, back);
1226   builder.create<fir::CallOp>(loc, func, args);
1227 }
1228 
1229 /// Generate call to `AllDim` runtime routine.
1230 /// This calls the descriptor based runtime call implementation of the `all`
1231 /// intrinsic.
1232 void fir::runtime::genAllDescriptor(fir::FirOpBuilder &builder,
1233                                     mlir::Location loc, mlir::Value resultBox,
1234                                     mlir::Value maskBox, mlir::Value dim) {
1235   auto allFunc = fir::runtime::getRuntimeFunc<mkRTKey(AllDim)>(loc, builder);
1236   genReduction2Args(allFunc, builder, loc, resultBox, maskBox, dim);
1237 }
1238 
1239 /// Generate call to `AnyDim` runtime routine.
1240 /// This calls the descriptor based runtime call implementation of the `any`
1241 /// intrinsic.
1242 void fir::runtime::genAnyDescriptor(fir::FirOpBuilder &builder,
1243                                     mlir::Location loc, mlir::Value resultBox,
1244                                     mlir::Value maskBox, mlir::Value dim) {
1245   auto anyFunc = fir::runtime::getRuntimeFunc<mkRTKey(AnyDim)>(loc, builder);
1246   genReduction2Args(anyFunc, builder, loc, resultBox, maskBox, dim);
1247 }
1248 
1249 /// Generate call to `ParityDim` runtime routine.
1250 /// This calls the descriptor based runtime call implementation of the `parity`
1251 /// intrinsic.
1252 void fir::runtime::genParityDescriptor(fir::FirOpBuilder &builder,
1253                                        mlir::Location loc,
1254                                        mlir::Value resultBox,
1255                                        mlir::Value maskBox, mlir::Value dim) {
1256   auto parityFunc =
1257       fir::runtime::getRuntimeFunc<mkRTKey(ParityDim)>(loc, builder);
1258   genReduction2Args(parityFunc, builder, loc, resultBox, maskBox, dim);
1259 }
1260 
1261 /// Generate call to `All` intrinsic runtime routine. This routine is
1262 /// specialized for mask arguments with rank == 1.
1263 mlir::Value fir::runtime::genAll(fir::FirOpBuilder &builder, mlir::Location loc,
1264                                  mlir::Value maskBox, mlir::Value dim) {
1265   auto allFunc = fir::runtime::getRuntimeFunc<mkRTKey(All)>(loc, builder);
1266   return genSpecial2Args(allFunc, builder, loc, maskBox, dim);
1267 }
1268 
1269 /// Generate call to `Any` intrinsic runtime routine. This routine is
1270 /// specialized for mask arguments with rank == 1.
1271 mlir::Value fir::runtime::genAny(fir::FirOpBuilder &builder, mlir::Location loc,
1272                                  mlir::Value maskBox, mlir::Value dim) {
1273   auto anyFunc = fir::runtime::getRuntimeFunc<mkRTKey(Any)>(loc, builder);
1274   return genSpecial2Args(anyFunc, builder, loc, maskBox, dim);
1275 }
1276 
1277 /// Generate call to `Count` runtime routine. This routine is a specialized
1278 /// version when mask is a rank one array or the dim argument is not
1279 /// specified by the user.
1280 mlir::Value fir::runtime::genCount(fir::FirOpBuilder &builder,
1281                                    mlir::Location loc, mlir::Value maskBox,
1282                                    mlir::Value dim) {
1283   auto countFunc = fir::runtime::getRuntimeFunc<mkRTKey(Count)>(loc, builder);
1284   return genSpecial2Args(countFunc, builder, loc, maskBox, dim);
1285 }
1286 
1287 /// Generate call to general `CountDim` runtime routine. This routine has a
1288 /// descriptor result.
1289 void fir::runtime::genCountDim(fir::FirOpBuilder &builder, mlir::Location loc,
1290                                mlir::Value resultBox, mlir::Value maskBox,
1291                                mlir::Value dim, mlir::Value kind) {
1292   auto func = fir::runtime::getRuntimeFunc<mkRTKey(CountDim)>(loc, builder);
1293   auto fTy = func.getFunctionType();
1294   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1295   auto sourceLine =
1296       fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
1297   auto args = fir::runtime::createArguments(
1298       builder, loc, fTy, resultBox, maskBox, dim, kind, sourceFile, sourceLine);
1299   builder.create<fir::CallOp>(loc, func, args);
1300 }
1301 
1302 /// Generate call to `Findloc` intrinsic runtime routine. This is the version
1303 /// that does not take a dim argument.
1304 void fir::runtime::genFindloc(fir::FirOpBuilder &builder, mlir::Location loc,
1305                               mlir::Value resultBox, mlir::Value arrayBox,
1306                               mlir::Value valBox, mlir::Value maskBox,
1307                               mlir::Value kind, mlir::Value back) {
1308   auto func = fir::runtime::getRuntimeFunc<mkRTKey(Findloc)>(loc, builder);
1309   auto fTy = func.getFunctionType();
1310   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1311   auto sourceLine =
1312       fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
1313   auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
1314                                             arrayBox, valBox, kind, sourceFile,
1315                                             sourceLine, maskBox, back);
1316   builder.create<fir::CallOp>(loc, func, args);
1317 }
1318 
1319 /// Generate call to `FindlocDim` intrinsic runtime routine. This is the version
1320 /// that takes a dim argument.
1321 void fir::runtime::genFindlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
1322                                  mlir::Value resultBox, mlir::Value arrayBox,
1323                                  mlir::Value valBox, mlir::Value dim,
1324                                  mlir::Value maskBox, mlir::Value kind,
1325                                  mlir::Value back) {
1326   auto func = fir::runtime::getRuntimeFunc<mkRTKey(FindlocDim)>(loc, builder);
1327   auto fTy = func.getFunctionType();
1328   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1329   auto sourceLine =
1330       fir::factory::locationToLineNo(builder, loc, fTy.getInput(6));
1331   auto args = fir::runtime::createArguments(
1332       builder, loc, fTy, resultBox, arrayBox, valBox, kind, dim, sourceFile,
1333       sourceLine, maskBox, back);
1334   builder.create<fir::CallOp>(loc, func, args);
1335 }
1336 
1337 /// Generate call to `Maxloc` intrinsic runtime routine. This is the version
1338 /// that does not take a dim argument.
1339 void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,
1340                              mlir::Value resultBox, mlir::Value arrayBox,
1341                              mlir::Value maskBox, mlir::Value kindVal,
1342                              mlir::Value back) {
1343   auto ty = arrayBox.getType();
1344   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1345   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1346   fir::factory::CharacterExprHelper charHelper{builder, loc};
1347   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1348   mlir::func::FuncOp func;
1349   REAL_INTRINSIC_INSTANCES(Maxloc, )
1350   INTEGER_INTRINSIC_INSTANCES(Maxloc, )
1351   UNSIGNED_INTRINSIC_INSTANCES(Maxloc, )
1352   if (charHelper.isCharacterScalar(eleTy))
1353     func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocCharacter)>(loc, builder);
1354   if (!func)
1355     fir::intrinsicTypeTODO(builder, eleTy, loc, "MAXLOC");
1356   genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kindVal,
1357                     back);
1358 }
1359 
1360 /// Generate call to `MaxlocDim` intrinsic runtime routine. This is the version
1361 /// that takes a dim argument.
1362 void fir::runtime::genMaxlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
1363                                 mlir::Value resultBox, mlir::Value arrayBox,
1364                                 mlir::Value dim, mlir::Value maskBox,
1365                                 mlir::Value kind, mlir::Value back) {
1366   auto func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocDim)>(loc, builder);
1367   genReduction5Args(func, builder, loc, resultBox, arrayBox, dim, maskBox, kind,
1368                     back);
1369 }
1370 
1371 /// Generate call to `Maxval` intrinsic runtime routine. This is the version
1372 /// that does not take a dim argument.
1373 mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder,
1374                                     mlir::Location loc, mlir::Value arrayBox,
1375                                     mlir::Value maskBox) {
1376   auto ty = arrayBox.getType();
1377   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1378   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1379   auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
1380   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1381   mlir::func::FuncOp func;
1382   REAL_INTRINSIC_INSTANCES(Maxval, )
1383   INTEGER_INTRINSIC_INSTANCES(Maxval, )
1384   UNSIGNED_INTRINSIC_INSTANCES(Maxval, )
1385   if (!func)
1386     fir::intrinsicTypeTODO(builder, eleTy, loc, "MAXVAL");
1387 
1388   auto fTy = func.getFunctionType();
1389   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1390   auto sourceLine =
1391       fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
1392   auto args = fir::runtime::createArguments(
1393       builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);
1394 
1395   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
1396 }
1397 
1398 /// Generate call to `MaxvalDim` intrinsic runtime routine. This is the version
1399 /// that handles any rank array with the dim argument specified.
1400 void fir::runtime::genMaxvalDim(fir::FirOpBuilder &builder, mlir::Location loc,
1401                                 mlir::Value resultBox, mlir::Value arrayBox,
1402                                 mlir::Value dim, mlir::Value maskBox) {
1403   auto func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalDim)>(loc, builder);
1404   genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
1405 }
1406 
1407 /// Generate call to `MaxvalCharacter` intrinsic runtime routine. This is the
1408 /// version that handles character arrays of rank 1 and without a DIM argument.
1409 void fir::runtime::genMaxvalChar(fir::FirOpBuilder &builder, mlir::Location loc,
1410                                  mlir::Value resultBox, mlir::Value arrayBox,
1411                                  mlir::Value maskBox) {
1412   auto func =
1413       fir::runtime::getRuntimeFunc<mkRTKey(MaxvalCharacter)>(loc, builder);
1414   auto fTy = func.getFunctionType();
1415   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1416   auto sourceLine =
1417       fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
1418   auto args = fir::runtime::createArguments(
1419       builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, maskBox);
1420   builder.create<fir::CallOp>(loc, func, args);
1421 }
1422 
1423 /// Generate call to `Minloc` intrinsic runtime routine. This is the version
1424 /// that does not take a dim argument.
1425 void fir::runtime::genMinloc(fir::FirOpBuilder &builder, mlir::Location loc,
1426                              mlir::Value resultBox, mlir::Value arrayBox,
1427                              mlir::Value maskBox, mlir::Value kindVal,
1428                              mlir::Value back) {
1429   auto ty = arrayBox.getType();
1430   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1431   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1432   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1433   mlir::func::FuncOp func;
1434   REAL_INTRINSIC_INSTANCES(Minloc, )
1435   INTEGER_INTRINSIC_INSTANCES(Minloc, )
1436   UNSIGNED_INTRINSIC_INSTANCES(Minloc, )
1437   fir::factory::CharacterExprHelper charHelper{builder, loc};
1438   if (charHelper.isCharacterScalar(eleTy))
1439     func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocCharacter)>(loc, builder);
1440   if (!func)
1441     fir::intrinsicTypeTODO(builder, eleTy, loc, "MINLOC");
1442   genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kindVal,
1443                     back);
1444 }
1445 
1446 /// Generate call to `MinlocDim` intrinsic runtime routine. This is the version
1447 /// that takes a dim argument.
1448 void fir::runtime::genMinlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
1449                                 mlir::Value resultBox, mlir::Value arrayBox,
1450                                 mlir::Value dim, mlir::Value maskBox,
1451                                 mlir::Value kind, mlir::Value back) {
1452   auto func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocDim)>(loc, builder);
1453   genReduction5Args(func, builder, loc, resultBox, arrayBox, dim, maskBox, kind,
1454                     back);
1455 }
1456 
1457 /// Generate call to `MinvalDim` intrinsic runtime routine. This is the version
1458 /// that handles any rank array with the dim argument specified.
1459 void fir::runtime::genMinvalDim(fir::FirOpBuilder &builder, mlir::Location loc,
1460                                 mlir::Value resultBox, mlir::Value arrayBox,
1461                                 mlir::Value dim, mlir::Value maskBox) {
1462   auto func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalDim)>(loc, builder);
1463   genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
1464 }
1465 
1466 /// Generate call to `MinvalCharacter` intrinsic runtime routine. This is the
1467 /// version that handles character arrays of rank 1 and without a DIM argument.
1468 void fir::runtime::genMinvalChar(fir::FirOpBuilder &builder, mlir::Location loc,
1469                                  mlir::Value resultBox, mlir::Value arrayBox,
1470                                  mlir::Value maskBox) {
1471   auto func =
1472       fir::runtime::getRuntimeFunc<mkRTKey(MinvalCharacter)>(loc, builder);
1473   auto fTy = func.getFunctionType();
1474   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1475   auto sourceLine =
1476       fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
1477   auto args = fir::runtime::createArguments(
1478       builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, maskBox);
1479   builder.create<fir::CallOp>(loc, func, args);
1480 }
1481 
1482 /// Generate call to `Minval` intrinsic runtime routine. This is the version
1483 /// that does not take a dim argument.
1484 mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder,
1485                                     mlir::Location loc, mlir::Value arrayBox,
1486                                     mlir::Value maskBox) {
1487   auto ty = arrayBox.getType();
1488   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1489   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1490   auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
1491   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1492 
1493   mlir::func::FuncOp func;
1494   REAL_INTRINSIC_INSTANCES(Minval, )
1495   INTEGER_INTRINSIC_INSTANCES(Minval, )
1496   UNSIGNED_INTRINSIC_INSTANCES(Minval, )
1497   if (!func)
1498     fir::intrinsicTypeTODO(builder, eleTy, loc, "MINVAL");
1499 
1500   auto fTy = func.getFunctionType();
1501   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1502   auto sourceLine =
1503       fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
1504   auto args = fir::runtime::createArguments(
1505       builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);
1506 
1507   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
1508 }
1509 
1510 /// Generate call to `Norm2Dim` intrinsic runtime routine. This is the version
1511 /// that takes a dim argument.
1512 void fir::runtime::genNorm2Dim(fir::FirOpBuilder &builder, mlir::Location loc,
1513                                mlir::Value resultBox, mlir::Value arrayBox,
1514                                mlir::Value dim) {
1515   mlir::func::FuncOp func;
1516   auto ty = arrayBox.getType();
1517   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1518   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1519   if (eleTy.isF128())
1520     func = fir::runtime::getRuntimeFunc<ForcedNorm2DimReal16>(loc, builder);
1521   else
1522     func = fir::runtime::getRuntimeFunc<mkRTKey(Norm2Dim)>(loc, builder);
1523   auto fTy = func.getFunctionType();
1524   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1525   auto sourceLine =
1526       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
1527   auto args = fir::runtime::createArguments(
1528       builder, loc, fTy, resultBox, arrayBox, dim, sourceFile, sourceLine);
1529 
1530   builder.create<fir::CallOp>(loc, func, args);
1531 }
1532 
1533 /// Generate call to `Norm2` intrinsic runtime routine. This is the version
1534 /// that does not take a dim argument.
1535 mlir::Value fir::runtime::genNorm2(fir::FirOpBuilder &builder,
1536                                    mlir::Location loc, mlir::Value arrayBox) {
1537   mlir::func::FuncOp func;
1538   auto ty = arrayBox.getType();
1539   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1540   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1541   auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
1542 
1543   if (eleTy.isF32())
1544     func = fir::runtime::getRuntimeFunc<mkRTKey(Norm2_4)>(loc, builder);
1545   else if (eleTy.isF64())
1546     func = fir::runtime::getRuntimeFunc<mkRTKey(Norm2_8)>(loc, builder);
1547   else if (eleTy.isF80())
1548     func = fir::runtime::getRuntimeFunc<ForcedNorm2Real10>(loc, builder);
1549   else if (eleTy.isF128())
1550     func = fir::runtime::getRuntimeFunc<ForcedNorm2Real16>(loc, builder);
1551   else
1552     fir::intrinsicTypeTODO(builder, eleTy, loc, "NORM2");
1553 
1554   auto fTy = func.getFunctionType();
1555   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1556   auto sourceLine =
1557       fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
1558   auto args = fir::runtime::createArguments(builder, loc, fTy, arrayBox,
1559                                             sourceFile, sourceLine, dim);
1560 
1561   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
1562 }
1563 
1564 /// Generate call to `Parity` intrinsic runtime routine. This routine is
1565 /// specialized for mask arguments with rank == 1.
1566 mlir::Value fir::runtime::genParity(fir::FirOpBuilder &builder,
1567                                     mlir::Location loc, mlir::Value maskBox,
1568                                     mlir::Value dim) {
1569   auto parityFunc = fir::runtime::getRuntimeFunc<mkRTKey(Parity)>(loc, builder);
1570   return genSpecial2Args(parityFunc, builder, loc, maskBox, dim);
1571 }
1572 
1573 /// Generate call to `ProductDim` intrinsic runtime routine. This is the version
1574 /// that handles any rank array with the dim argument specified.
1575 void fir::runtime::genProductDim(fir::FirOpBuilder &builder, mlir::Location loc,
1576                                  mlir::Value resultBox, mlir::Value arrayBox,
1577                                  mlir::Value dim, mlir::Value maskBox) {
1578   auto func = fir::runtime::getRuntimeFunc<mkRTKey(ProductDim)>(loc, builder);
1579   genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
1580 }
1581 
1582 /// Generate call to `Product` intrinsic runtime routine. This is the version
1583 /// that does not take a dim argument.
1584 mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder,
1585                                      mlir::Location loc, mlir::Value arrayBox,
1586                                      mlir::Value maskBox,
1587                                      mlir::Value resultBox) {
1588   auto ty = arrayBox.getType();
1589   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1590   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1591   auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
1592 
1593   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1594   mlir::func::FuncOp func;
1595   NUMERICAL_INTRINSIC_INSTANCES(Product)
1596   if (!func)
1597     fir::intrinsicTypeTODO(builder, eleTy, loc, "PRODUCT");
1598 
1599   auto fTy = func.getFunctionType();
1600   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1601   if (fir::isa_complex(eleTy)) {
1602     auto sourceLine =
1603         fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
1604     auto args =
1605         fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
1606                                       sourceFile, sourceLine, dim, maskBox);
1607     builder.create<fir::CallOp>(loc, func, args);
1608     return resultBox;
1609   }
1610 
1611   auto sourceLine =
1612       fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
1613   auto args = fir::runtime::createArguments(
1614       builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);
1615 
1616   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
1617 }
1618 
1619 /// Generate call to `DotProduct` intrinsic runtime routine.
1620 mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder,
1621                                         mlir::Location loc,
1622                                         mlir::Value vectorABox,
1623                                         mlir::Value vectorBBox,
1624                                         mlir::Value resultBox) {
1625   // For complex data types, resultBox is !fir.ref<!fir.complex<N>>,
1626   // otherwise it is !fir.box<T>.
1627   auto ty = resultBox.getType();
1628   auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1629 
1630   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1631   mlir::func::FuncOp func;
1632   NUMERICAL_INTRINSIC_INSTANCES(DotProduct)
1633   if (cat == Fortran::common::TypeCategory::Logical)
1634     func =
1635         fir::runtime::getRuntimeFunc<mkRTKey(DotProductLogical)>(loc, builder);
1636   if (!func)
1637     fir::intrinsicTypeTODO(builder, eleTy, loc, "DOTPRODUCT");
1638 
1639   auto fTy = func.getFunctionType();
1640   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1641 
1642   if (fir::isa_complex(eleTy)) {
1643     auto sourceLine =
1644         fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
1645     auto args =
1646         fir::runtime::createArguments(builder, loc, fTy, resultBox, vectorABox,
1647                                       vectorBBox, sourceFile, sourceLine);
1648     builder.create<fir::CallOp>(loc, func, args);
1649     return resultBox;
1650   }
1651 
1652   auto sourceLine =
1653       fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
1654   auto args = fir::runtime::createArguments(builder, loc, fTy, vectorABox,
1655                                             vectorBBox, sourceFile, sourceLine);
1656   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
1657 }
1658 /// Generate call to `SumDim` intrinsic runtime routine. This is the version
1659 /// that handles any rank array with the dim argument specified.
1660 void fir::runtime::genSumDim(fir::FirOpBuilder &builder, mlir::Location loc,
1661                              mlir::Value resultBox, mlir::Value arrayBox,
1662                              mlir::Value dim, mlir::Value maskBox) {
1663   auto func = fir::runtime::getRuntimeFunc<mkRTKey(SumDim)>(loc, builder);
1664   genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
1665 }
1666 
1667 /// Generate call to `Sum` intrinsic runtime routine. This is the version
1668 /// that does not take a dim argument.
1669 mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc,
1670                                  mlir::Value arrayBox, mlir::Value maskBox,
1671                                  mlir::Value resultBox) {
1672   auto ty = arrayBox.getType();
1673   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1674   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1675   auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
1676 
1677   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1678   mlir::func::FuncOp func;
1679   NUMERICAL_INTRINSIC_INSTANCES(Sum)
1680   if (!func)
1681     fir::intrinsicTypeTODO(builder, eleTy, loc, "SUM");
1682 
1683   auto fTy = func.getFunctionType();
1684   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1685   if (fir::isa_complex(eleTy)) {
1686     auto sourceLine =
1687         fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
1688     auto args =
1689         fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
1690                                       sourceFile, sourceLine, dim, maskBox);
1691     builder.create<fir::CallOp>(loc, func, args);
1692     return resultBox;
1693   }
1694 
1695   auto sourceLine =
1696       fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
1697   auto args = fir::runtime::createArguments(
1698       builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);
1699 
1700   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
1701 }
1702 
1703 // The IAll, IAny and IParity intrinsics have essentially the same
1704 // implementation. This macro will generate the function body given the
1705 // intrinsic name.
1706 #define GEN_IALL_IANY_IPARITY(F)                                               \
1707   mlir::Value fir::runtime::JOIN2(gen, F)(                                     \
1708       fir::FirOpBuilder & builder, mlir::Location loc, mlir::Value arrayBox,   \
1709       mlir::Value maskBox, mlir::Value resultBox) {                            \
1710     mlir::func::FuncOp func;                                                   \
1711     auto ty = arrayBox.getType();                                              \
1712     auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);                              \
1713     auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();        \
1714     auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);  \
1715                                                                                \
1716     if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1)))            \
1717       func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 1))>(loc, builder); \
1718     else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2)))       \
1719       func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 2))>(loc, builder); \
1720     else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4)))       \
1721       func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 4))>(loc, builder); \
1722     else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8)))       \
1723       func = fir::runtime::getRuntimeFunc<mkRTKey(JOIN2(F, 8))>(loc, builder); \
1724     else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16)))      \
1725       func = fir::runtime::getRuntimeFunc<JOIN3(Forced, F, 16)>(loc, builder); \
1726     else                                                                       \
1727       fir::emitFatalError(loc, "invalid type in " STRINGIFY(F));               \
1728                                                                                \
1729     auto fTy = func.getFunctionType();                                         \
1730     auto sourceFile = fir::factory::locationToFilename(builder, loc);          \
1731     auto sourceLine =                                                          \
1732         fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));         \
1733     auto args = fir::runtime::createArguments(                                 \
1734         builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);    \
1735                                                                                \
1736     return builder.create<fir::CallOp>(loc, func, args).getResult(0);          \
1737   }
1738 
1739 /// Generate call to `IAllDim` intrinsic runtime routine. This is the version
1740 /// that handles any rank array with the dim argument specified.
1741 void fir::runtime::genIAllDim(fir::FirOpBuilder &builder, mlir::Location loc,
1742                               mlir::Value resultBox, mlir::Value arrayBox,
1743                               mlir::Value dim, mlir::Value maskBox) {
1744   auto func = fir::runtime::getRuntimeFunc<mkRTKey(IAllDim)>(loc, builder);
1745   genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
1746 }
1747 
1748 /// Generate call to `IAll` intrinsic runtime routine. This is the version
1749 /// that does not take a dim argument.
1750 GEN_IALL_IANY_IPARITY(IAll)
1751 
1752 /// Generate call to `IAnyDim` intrinsic runtime routine. This is the version
1753 /// that handles any rank array with the dim argument specified.
1754 void fir::runtime::genIAnyDim(fir::FirOpBuilder &builder, mlir::Location loc,
1755                               mlir::Value resultBox, mlir::Value arrayBox,
1756                               mlir::Value dim, mlir::Value maskBox) {
1757   auto func = fir::runtime::getRuntimeFunc<mkRTKey(IAnyDim)>(loc, builder);
1758   genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
1759 }
1760 
1761 /// Generate call to `IAny` intrinsic runtime routine. This is the version
1762 /// that does not take a dim argument.
1763 GEN_IALL_IANY_IPARITY(IAny)
1764 
1765 /// Generate call to `IParityDim` intrinsic runtime routine. This is the version
1766 /// that handles any rank array with the dim argument specified.
1767 void fir::runtime::genIParityDim(fir::FirOpBuilder &builder, mlir::Location loc,
1768                                  mlir::Value resultBox, mlir::Value arrayBox,
1769                                  mlir::Value dim, mlir::Value maskBox) {
1770   auto func = fir::runtime::getRuntimeFunc<mkRTKey(IParityDim)>(loc, builder);
1771   genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
1772 }
1773 
1774 /// Generate call to `IParity` intrinsic runtime routine. This is the version
1775 /// that does not take a dim argument.
1776 GEN_IALL_IANY_IPARITY(IParity)
1777 
1778 /// Generate call to `Reduce` intrinsic runtime routine. This is the version
1779 /// that does not take a DIM argument and store result in the passed result
1780 /// value.
1781 void fir::runtime::genReduce(fir::FirOpBuilder &builder, mlir::Location loc,
1782                              mlir::Value arrayBox, mlir::Value operation,
1783                              mlir::Value maskBox, mlir::Value identity,
1784                              mlir::Value ordered, mlir::Value resultBox,
1785                              bool argByRef) {
1786   auto ty = arrayBox.getType();
1787   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1788   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1789   auto dim = builder.createIntegerConstant(loc, builder.getI32Type(), 1);
1790 
1791   assert(resultBox && "expect non null value for the result");
1792   assert((fir::isa_char(eleTy) || fir::isa_complex(eleTy) ||
1793           fir::isa_derived(eleTy)) &&
1794          "expect character, complex or derived-type");
1795 
1796   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1797   mlir::func::FuncOp func;
1798   if (argByRef) {
1799     COMPLEX_2_3_INTRINSIC_INSTANCES(Reduce, Ref)
1800     COMPLEX_INTRINSIC_INSTANCES(Reduce, Ref)
1801   } else {
1802     COMPLEX_2_3_INTRINSIC_INSTANCES(Reduce, Value)
1803     COMPLEX_INTRINSIC_INSTANCES(Reduce, Value)
1804   }
1805   fir::factory::CharacterExprHelper charHelper{builder, loc};
1806   if (fir::isa_char(eleTy) && charHelper.getCharacterKind(eleTy) == 1)
1807     func = fir::runtime::getRuntimeFunc<mkRTKey(ReduceChar1)>(loc, builder);
1808   else if (fir::isa_char(eleTy) && charHelper.getCharacterKind(eleTy) == 2)
1809     func = fir::runtime::getRuntimeFunc<mkRTKey(ReduceChar2)>(loc, builder);
1810   else if (fir::isa_char(eleTy) && charHelper.getCharacterKind(eleTy) == 4)
1811     func = fir::runtime::getRuntimeFunc<mkRTKey(ReduceChar4)>(loc, builder);
1812   else if (fir::isa_derived(eleTy))
1813     func =
1814         fir::runtime::getRuntimeFunc<mkRTKey(ReduceDerivedType)>(loc, builder);
1815   if (!func)
1816     fir::intrinsicTypeTODO(builder, eleTy, loc, "REDUCE");
1817 
1818   auto fTy = func.getFunctionType();
1819   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1820   auto sourceLine =
1821       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
1822   auto opAddr = builder.create<fir::BoxAddrOp>(loc, fTy.getInput(2), operation);
1823   auto args = fir::runtime::createArguments(
1824       builder, loc, fTy, resultBox, arrayBox, opAddr, sourceFile, sourceLine,
1825       dim, maskBox, identity, ordered);
1826   builder.create<fir::CallOp>(loc, func, args);
1827 }
1828 
1829 /// Generate call to `Reduce` intrinsic runtime routine. This is the version
1830 /// that does not take DIM argument and return a scalar result.
1831 mlir::Value fir::runtime::genReduce(fir::FirOpBuilder &builder,
1832                                     mlir::Location loc, mlir::Value arrayBox,
1833                                     mlir::Value operation, mlir::Value maskBox,
1834                                     mlir::Value identity, mlir::Value ordered,
1835                                     bool argByRef) {
1836   auto ty = arrayBox.getType();
1837   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1838   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1839   auto dim = builder.createIntegerConstant(loc, builder.getI32Type(), 1);
1840 
1841   assert((fir::isa_real(eleTy) || fir::isa_integer(eleTy) ||
1842           mlir::isa<fir::LogicalType>(eleTy)) &&
1843          "expect real, interger or logical");
1844 
1845   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1846   mlir::func::FuncOp func;
1847   if (argByRef) {
1848     REAL_2_3_INTRINSIC_INSTANCES(Reduce, Ref)
1849     REAL_INTRINSIC_INSTANCES(Reduce, Ref)
1850     INTEGER_INTRINSIC_INSTANCES(Reduce, Ref)
1851     UNSIGNED_INTRINSIC_INSTANCES(Reduce, Ref)
1852     LOGICAL_INTRINSIC_INSTANCES(Reduce, Ref)
1853   } else {
1854     REAL_2_3_INTRINSIC_INSTANCES(Reduce, Value)
1855     REAL_INTRINSIC_INSTANCES(Reduce, Value)
1856     INTEGER_INTRINSIC_INSTANCES(Reduce, Value)
1857     UNSIGNED_INTRINSIC_INSTANCES(Reduce, Value)
1858     LOGICAL_INTRINSIC_INSTANCES(Reduce, Value)
1859   }
1860   if (!func)
1861     fir::intrinsicTypeTODO(builder, eleTy, loc, "REDUCE");
1862 
1863   auto fTy = func.getFunctionType();
1864   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1865   auto sourceLine =
1866       fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
1867   auto opAddr = builder.create<fir::BoxAddrOp>(loc, fTy.getInput(1), operation);
1868   auto args = fir::runtime::createArguments(builder, loc, fTy, arrayBox, opAddr,
1869                                             sourceFile, sourceLine, dim,
1870                                             maskBox, identity, ordered);
1871   return builder.create<fir::CallOp>(loc, func, args).getResult(0);
1872 }
1873 
1874 void fir::runtime::genReduceDim(fir::FirOpBuilder &builder, mlir::Location loc,
1875                                 mlir::Value arrayBox, mlir::Value operation,
1876                                 mlir::Value dim, mlir::Value maskBox,
1877                                 mlir::Value identity, mlir::Value ordered,
1878                                 mlir::Value resultBox, bool argByRef) {
1879   auto ty = arrayBox.getType();
1880   auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
1881   auto eleTy = mlir::cast<fir::SequenceType>(arrTy).getElementType();
1882   auto [cat, kind] = fir::mlirTypeToCategoryKind(loc, eleTy);
1883 
1884   mlir::func::FuncOp func;
1885   if (argByRef) {
1886     REAL_2_3_INTRINSIC_INSTANCES(Reduce, DimRef)
1887     COMPLEX_2_3_INTRINSIC_INSTANCES(Reduce, DimRef)
1888     NUMERICAL_AND_LOGICAL_INSTANCES(Reduce, DimRef)
1889   } else {
1890     REAL_2_3_INTRINSIC_INSTANCES(Reduce, DimValue)
1891     COMPLEX_2_3_INTRINSIC_INSTANCES(Reduce, DimValue)
1892     NUMERICAL_AND_LOGICAL_INSTANCES(Reduce, DimValue)
1893   }
1894   fir::factory::CharacterExprHelper charHelper{builder, loc};
1895   if (fir::isa_char(eleTy) && charHelper.getCharacterKind(eleTy) == 1)
1896     func = fir::runtime::getRuntimeFunc<mkRTKey(ReduceCharacter1Dim)>(loc,
1897                                                                       builder);
1898   else if (fir::isa_char(eleTy) && charHelper.getCharacterKind(eleTy) == 2)
1899     func = fir::runtime::getRuntimeFunc<mkRTKey(ReduceCharacter2Dim)>(loc,
1900                                                                       builder);
1901   else if (fir::isa_char(eleTy) && charHelper.getCharacterKind(eleTy) == 4)
1902     func = fir::runtime::getRuntimeFunc<mkRTKey(ReduceCharacter4Dim)>(loc,
1903                                                                       builder);
1904   else if (fir::isa_derived(eleTy))
1905     func = fir::runtime::getRuntimeFunc<mkRTKey(ReduceDerivedTypeDim)>(loc,
1906                                                                        builder);
1907   if (!func)
1908     fir::intrinsicTypeTODO(builder, eleTy, loc, "REDUCE");
1909 
1910   auto fTy = func.getFunctionType();
1911   auto sourceFile = fir::factory::locationToFilename(builder, loc);
1912 
1913   auto sourceLine =
1914       fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
1915   auto opAddr = builder.create<fir::BoxAddrOp>(loc, fTy.getInput(2), operation);
1916   auto args = fir::runtime::createArguments(
1917       builder, loc, fTy, resultBox, arrayBox, opAddr, sourceFile, sourceLine,
1918       dim, maskBox, identity, ordered);
1919   builder.create<fir::CallOp>(loc, func, args);
1920 }
1921