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/Builder/Todo.h" 15 #include "flang/Runtime/reduction.h" 16 #include "mlir/Dialect/Func/IR/FuncOps.h" 17 18 using namespace Fortran::runtime; 19 20 /// Placeholder for real*10 version of Maxval Intrinsic 21 struct ForcedMaxvalReal10 { 22 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MaxvalReal10)); 23 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 24 return [](mlir::MLIRContext *ctx) { 25 auto ty = mlir::FloatType::getF80(ctx); 26 auto boxTy = 27 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 28 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 29 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 30 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 31 {ty}); 32 }; 33 } 34 }; 35 36 /// Placeholder for real*16 version of Maxval Intrinsic 37 struct ForcedMaxvalReal16 { 38 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MaxvalReal16)); 39 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 40 return [](mlir::MLIRContext *ctx) { 41 auto ty = mlir::FloatType::getF128(ctx); 42 auto boxTy = 43 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 44 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 45 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 46 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 47 {ty}); 48 }; 49 } 50 }; 51 52 /// Placeholder for integer*16 version of Maxval Intrinsic 53 struct ForcedMaxvalInteger16 { 54 static constexpr const char *name = 55 ExpandAndQuoteKey(RTNAME(MaxvalInteger16)); 56 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 57 return [](mlir::MLIRContext *ctx) { 58 auto ty = mlir::IntegerType::get(ctx, 128); 59 auto boxTy = 60 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 61 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 62 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 63 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 64 {ty}); 65 }; 66 } 67 }; 68 69 /// Placeholder for real*10 version of Minval Intrinsic 70 struct ForcedMinvalReal10 { 71 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MinvalReal10)); 72 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 73 return [](mlir::MLIRContext *ctx) { 74 auto ty = mlir::FloatType::getF80(ctx); 75 auto boxTy = 76 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 77 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 78 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 79 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 80 {ty}); 81 }; 82 } 83 }; 84 85 /// Placeholder for real*16 version of Minval Intrinsic 86 struct ForcedMinvalReal16 { 87 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MinvalReal16)); 88 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 89 return [](mlir::MLIRContext *ctx) { 90 auto ty = mlir::FloatType::getF128(ctx); 91 auto boxTy = 92 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 93 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 94 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 95 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 96 {ty}); 97 }; 98 } 99 }; 100 101 /// Placeholder for integer*16 version of Minval Intrinsic 102 struct ForcedMinvalInteger16 { 103 static constexpr const char *name = 104 ExpandAndQuoteKey(RTNAME(MinvalInteger16)); 105 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 106 return [](mlir::MLIRContext *ctx) { 107 auto ty = mlir::IntegerType::get(ctx, 128); 108 auto boxTy = 109 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 110 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 111 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 112 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 113 {ty}); 114 }; 115 } 116 }; 117 118 /// Placeholder for real*10 version of Product Intrinsic 119 struct ForcedProductReal10 { 120 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ProductReal10)); 121 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 122 return [](mlir::MLIRContext *ctx) { 123 auto ty = mlir::FloatType::getF80(ctx); 124 auto boxTy = 125 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 126 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 127 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 128 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 129 {ty}); 130 }; 131 } 132 }; 133 134 /// Placeholder for real*16 version of Product Intrinsic 135 struct ForcedProductReal16 { 136 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ProductReal16)); 137 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 138 return [](mlir::MLIRContext *ctx) { 139 auto ty = mlir::FloatType::getF128(ctx); 140 auto boxTy = 141 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 142 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 143 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 144 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 145 {ty}); 146 }; 147 } 148 }; 149 150 /// Placeholder for integer*16 version of Product Intrinsic 151 struct ForcedProductInteger16 { 152 static constexpr const char *name = 153 ExpandAndQuoteKey(RTNAME(ProductInteger16)); 154 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 155 return [](mlir::MLIRContext *ctx) { 156 auto ty = mlir::IntegerType::get(ctx, 128); 157 auto boxTy = 158 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 159 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 160 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 161 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 162 {ty}); 163 }; 164 } 165 }; 166 167 /// Placeholder for complex(10) version of Product Intrinsic 168 struct ForcedProductComplex10 { 169 static constexpr const char *name = 170 ExpandAndQuoteKey(RTNAME(CppProductComplex10)); 171 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 172 return [](mlir::MLIRContext *ctx) { 173 auto ty = mlir::ComplexType::get(mlir::FloatType::getF80(ctx)); 174 auto boxTy = 175 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 176 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 177 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 178 auto resTy = fir::ReferenceType::get(ty); 179 return mlir::FunctionType::get( 180 ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {}); 181 }; 182 } 183 }; 184 185 /// Placeholder for complex(16) version of Product Intrinsic 186 struct ForcedProductComplex16 { 187 static constexpr const char *name = 188 ExpandAndQuoteKey(RTNAME(CppProductComplex16)); 189 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 190 return [](mlir::MLIRContext *ctx) { 191 auto ty = mlir::ComplexType::get(mlir::FloatType::getF128(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 auto resTy = fir::ReferenceType::get(ty); 197 return mlir::FunctionType::get( 198 ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {}); 199 }; 200 } 201 }; 202 203 /// Placeholder for real*10 version of DotProduct Intrinsic 204 struct ForcedDotProductReal10 { 205 static constexpr const char *name = 206 ExpandAndQuoteKey(RTNAME(DotProductReal10)); 207 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 208 return [](mlir::MLIRContext *ctx) { 209 auto ty = mlir::FloatType::getF80(ctx); 210 auto boxTy = 211 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 212 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 213 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 214 return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty}); 215 }; 216 } 217 }; 218 219 /// Placeholder for real*16 version of DotProduct Intrinsic 220 struct ForcedDotProductReal16 { 221 static constexpr const char *name = 222 ExpandAndQuoteKey(RTNAME(DotProductReal16)); 223 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 224 return [](mlir::MLIRContext *ctx) { 225 auto ty = mlir::FloatType::getF128(ctx); 226 auto boxTy = 227 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 228 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 229 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 230 return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty}); 231 }; 232 } 233 }; 234 235 /// Placeholder for complex(10) version of DotProduct Intrinsic 236 struct ForcedDotProductComplex10 { 237 static constexpr const char *name = 238 ExpandAndQuoteKey(RTNAME(CppDotProductComplex10)); 239 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 240 return [](mlir::MLIRContext *ctx) { 241 auto ty = mlir::ComplexType::get(mlir::FloatType::getF80(ctx)); 242 auto boxTy = 243 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 244 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 245 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 246 auto resTy = fir::ReferenceType::get(ty); 247 return mlir::FunctionType::get(ctx, {resTy, boxTy, boxTy, strTy, intTy}, 248 {}); 249 }; 250 } 251 }; 252 253 /// Placeholder for complex(16) version of DotProduct Intrinsic 254 struct ForcedDotProductComplex16 { 255 static constexpr const char *name = 256 ExpandAndQuoteKey(RTNAME(CppDotProductComplex16)); 257 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 258 return [](mlir::MLIRContext *ctx) { 259 auto ty = mlir::ComplexType::get(mlir::FloatType::getF128(ctx)); 260 auto boxTy = 261 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 262 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 263 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 264 auto resTy = fir::ReferenceType::get(ty); 265 return mlir::FunctionType::get(ctx, {resTy, boxTy, boxTy, strTy, intTy}, 266 {}); 267 }; 268 } 269 }; 270 271 /// Placeholder for integer*16 version of DotProduct Intrinsic 272 struct ForcedDotProductInteger16 { 273 static constexpr const char *name = 274 ExpandAndQuoteKey(RTNAME(DotProductInteger16)); 275 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 276 return [](mlir::MLIRContext *ctx) { 277 auto ty = mlir::IntegerType::get(ctx, 128); 278 auto boxTy = 279 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 280 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 281 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 282 return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty}); 283 }; 284 } 285 }; 286 287 /// Placeholder for real*10 version of Sum Intrinsic 288 struct ForcedSumReal10 { 289 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumReal10)); 290 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 291 return [](mlir::MLIRContext *ctx) { 292 auto ty = mlir::FloatType::getF80(ctx); 293 auto boxTy = 294 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 295 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 296 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 297 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 298 {ty}); 299 }; 300 } 301 }; 302 303 /// Placeholder for real*16 version of Sum Intrinsic 304 struct ForcedSumReal16 { 305 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumReal16)); 306 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 307 return [](mlir::MLIRContext *ctx) { 308 auto ty = mlir::FloatType::getF128(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 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 314 {ty}); 315 }; 316 } 317 }; 318 319 /// Placeholder for integer*16 version of Sum Intrinsic 320 struct ForcedSumInteger16 { 321 static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumInteger16)); 322 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 323 return [](mlir::MLIRContext *ctx) { 324 auto ty = mlir::IntegerType::get(ctx, 128); 325 auto boxTy = 326 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 327 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 328 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 329 return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy}, 330 {ty}); 331 }; 332 } 333 }; 334 335 /// Placeholder for complex(10) version of Sum Intrinsic 336 struct ForcedSumComplex10 { 337 static constexpr const char *name = 338 ExpandAndQuoteKey(RTNAME(CppSumComplex10)); 339 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 340 return [](mlir::MLIRContext *ctx) { 341 auto ty = mlir::ComplexType::get(mlir::FloatType::getF80(ctx)); 342 auto boxTy = 343 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 344 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 345 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 346 auto resTy = fir::ReferenceType::get(ty); 347 return mlir::FunctionType::get( 348 ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {}); 349 }; 350 } 351 }; 352 353 /// Placeholder for complex(16) version of Sum Intrinsic 354 struct ForcedSumComplex16 { 355 static constexpr const char *name = 356 ExpandAndQuoteKey(RTNAME(CppSumComplex16)); 357 static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { 358 return [](mlir::MLIRContext *ctx) { 359 auto ty = mlir::ComplexType::get(mlir::FloatType::getF128(ctx)); 360 auto boxTy = 361 fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); 362 auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); 363 auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); 364 auto resTy = fir::ReferenceType::get(ty); 365 return mlir::FunctionType::get( 366 ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {}); 367 }; 368 } 369 }; 370 371 /// Generate call to specialized runtime function that takes a mask and 372 /// dim argument. The All, Any, and Count intrinsics use this pattern. 373 template <typename FN> 374 mlir::Value genSpecial2Args(FN func, fir::FirOpBuilder &builder, 375 mlir::Location loc, mlir::Value maskBox, 376 mlir::Value dim) { 377 auto fTy = func.getFunctionType(); 378 auto sourceFile = fir::factory::locationToFilename(builder, loc); 379 auto sourceLine = 380 fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); 381 auto args = fir::runtime::createArguments(builder, loc, fTy, maskBox, 382 sourceFile, sourceLine, dim); 383 return builder.create<fir::CallOp>(loc, func, args).getResult(0); 384 } 385 386 /// Generate calls to reduction intrinsics such as All and Any. 387 /// These are the descriptor based implementations that take two 388 /// arguments (mask, dim). 389 template <typename FN> 390 static void genReduction2Args(FN func, fir::FirOpBuilder &builder, 391 mlir::Location loc, mlir::Value resultBox, 392 mlir::Value maskBox, mlir::Value dim) { 393 auto fTy = func.getFunctionType(); 394 auto sourceFile = fir::factory::locationToFilename(builder, loc); 395 auto sourceLine = 396 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); 397 auto args = fir::runtime::createArguments( 398 builder, loc, fTy, resultBox, maskBox, dim, sourceFile, sourceLine); 399 builder.create<fir::CallOp>(loc, func, args); 400 } 401 402 /// Generate calls to reduction intrinsics such as Maxval and Minval. 403 /// These take arguments such as (array, dim, mask). 404 template <typename FN> 405 static void genReduction3Args(FN func, fir::FirOpBuilder &builder, 406 mlir::Location loc, mlir::Value resultBox, 407 mlir::Value arrayBox, mlir::Value dim, 408 mlir::Value maskBox) { 409 410 auto fTy = func.getFunctionType(); 411 auto sourceFile = fir::factory::locationToFilename(builder, loc); 412 auto sourceLine = 413 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); 414 auto args = 415 fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, dim, 416 sourceFile, sourceLine, maskBox); 417 builder.create<fir::CallOp>(loc, func, args); 418 } 419 420 /// Generate calls to reduction intrinsics such as Maxloc and Minloc. 421 /// These take arguments such as (array, mask, kind, back). 422 template <typename FN> 423 static void genReduction4Args(FN func, fir::FirOpBuilder &builder, 424 mlir::Location loc, mlir::Value resultBox, 425 mlir::Value arrayBox, mlir::Value maskBox, 426 mlir::Value kind, mlir::Value back) { 427 auto fTy = func.getFunctionType(); 428 auto sourceFile = fir::factory::locationToFilename(builder, loc); 429 auto sourceLine = 430 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); 431 auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, 432 arrayBox, kind, sourceFile, 433 sourceLine, maskBox, back); 434 builder.create<fir::CallOp>(loc, func, args); 435 } 436 437 /// Generate calls to reduction intrinsics such as Maxloc and Minloc. 438 /// These take arguments such as (array, dim, mask, kind, back). 439 template <typename FN> 440 static void 441 genReduction5Args(FN func, fir::FirOpBuilder &builder, mlir::Location loc, 442 mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim, 443 mlir::Value maskBox, mlir::Value kind, mlir::Value back) { 444 auto fTy = func.getFunctionType(); 445 auto sourceFile = fir::factory::locationToFilename(builder, loc); 446 auto sourceLine = 447 fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); 448 auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, 449 arrayBox, kind, dim, sourceFile, 450 sourceLine, maskBox, back); 451 builder.create<fir::CallOp>(loc, func, args); 452 } 453 454 /// Generate call to `AllDim` runtime routine. 455 /// This calls the descriptor based runtime call implementation of the `all` 456 /// intrinsic. 457 void fir::runtime::genAllDescriptor(fir::FirOpBuilder &builder, 458 mlir::Location loc, mlir::Value resultBox, 459 mlir::Value maskBox, mlir::Value dim) { 460 auto allFunc = fir::runtime::getRuntimeFunc<mkRTKey(AllDim)>(loc, builder); 461 genReduction2Args(allFunc, builder, loc, resultBox, maskBox, dim); 462 } 463 464 /// Generate call to `AnyDim` runtime routine. 465 /// This calls the descriptor based runtime call implementation of the `any` 466 /// intrinsic. 467 void fir::runtime::genAnyDescriptor(fir::FirOpBuilder &builder, 468 mlir::Location loc, mlir::Value resultBox, 469 mlir::Value maskBox, mlir::Value dim) { 470 auto anyFunc = fir::runtime::getRuntimeFunc<mkRTKey(AnyDim)>(loc, builder); 471 genReduction2Args(anyFunc, builder, loc, resultBox, maskBox, dim); 472 } 473 474 /// Generate call to `All` intrinsic runtime routine. This routine is 475 /// specialized for mask arguments with rank == 1. 476 mlir::Value fir::runtime::genAll(fir::FirOpBuilder &builder, mlir::Location loc, 477 mlir::Value maskBox, mlir::Value dim) { 478 auto allFunc = fir::runtime::getRuntimeFunc<mkRTKey(All)>(loc, builder); 479 return genSpecial2Args(allFunc, builder, loc, maskBox, dim); 480 } 481 482 /// Generate call to `Any` intrinsic runtime routine. This routine is 483 /// specialized for mask arguments with rank == 1. 484 mlir::Value fir::runtime::genAny(fir::FirOpBuilder &builder, mlir::Location loc, 485 mlir::Value maskBox, mlir::Value dim) { 486 auto anyFunc = fir::runtime::getRuntimeFunc<mkRTKey(Any)>(loc, builder); 487 return genSpecial2Args(anyFunc, builder, loc, maskBox, dim); 488 } 489 490 /// Generate call to `Count` runtime routine. This routine is a specialized 491 /// version when mask is a rank one array or the dim argument is not 492 /// specified by the user. 493 mlir::Value fir::runtime::genCount(fir::FirOpBuilder &builder, 494 mlir::Location loc, mlir::Value maskBox, 495 mlir::Value dim) { 496 auto countFunc = fir::runtime::getRuntimeFunc<mkRTKey(Count)>(loc, builder); 497 return genSpecial2Args(countFunc, builder, loc, maskBox, dim); 498 } 499 500 /// Generate call to general `CountDim` runtime routine. This routine has a 501 /// descriptor result. 502 void fir::runtime::genCountDim(fir::FirOpBuilder &builder, mlir::Location loc, 503 mlir::Value resultBox, mlir::Value maskBox, 504 mlir::Value dim, mlir::Value kind) { 505 auto func = fir::runtime::getRuntimeFunc<mkRTKey(CountDim)>(loc, builder); 506 auto fTy = func.getFunctionType(); 507 auto sourceFile = fir::factory::locationToFilename(builder, loc); 508 auto sourceLine = 509 fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); 510 auto args = fir::runtime::createArguments( 511 builder, loc, fTy, resultBox, maskBox, dim, kind, sourceFile, sourceLine); 512 builder.create<fir::CallOp>(loc, func, args); 513 } 514 515 /// Generate call to `Maxloc` intrinsic runtime routine. This is the version 516 /// that does not take a dim argument. 517 void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc, 518 mlir::Value resultBox, mlir::Value arrayBox, 519 mlir::Value maskBox, mlir::Value kind, 520 mlir::Value back) { 521 auto func = fir::runtime::getRuntimeFunc<mkRTKey(Maxloc)>(loc, builder); 522 genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind, 523 back); 524 } 525 526 /// Generate call to `MaxlocDim` intrinsic runtime routine. This is the version 527 /// that takes a dim argument. 528 void fir::runtime::genMaxlocDim(fir::FirOpBuilder &builder, mlir::Location loc, 529 mlir::Value resultBox, mlir::Value arrayBox, 530 mlir::Value dim, mlir::Value maskBox, 531 mlir::Value kind, mlir::Value back) { 532 auto func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocDim)>(loc, builder); 533 genReduction5Args(func, builder, loc, resultBox, arrayBox, dim, maskBox, kind, 534 back); 535 } 536 537 /// Generate call to `Maxval` intrinsic runtime routine. This is the version 538 /// that does not take a dim argument. 539 mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder, 540 mlir::Location loc, mlir::Value arrayBox, 541 mlir::Value maskBox) { 542 mlir::func::FuncOp func; 543 auto ty = arrayBox.getType(); 544 auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); 545 auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy(); 546 auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); 547 548 if (eleTy.isF16() || eleTy.isBF16()) 549 TODO(loc, "half-precision MAXVAL"); 550 else if (eleTy.isF32()) 551 func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalReal4)>(loc, builder); 552 else if (eleTy.isF64()) 553 func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalReal8)>(loc, builder); 554 else if (eleTy.isF80()) 555 func = fir::runtime::getRuntimeFunc<ForcedMaxvalReal10>(loc, builder); 556 else if (eleTy.isF128()) 557 func = fir::runtime::getRuntimeFunc<ForcedMaxvalReal16>(loc, builder); 558 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) 559 func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalInteger1)>(loc, builder); 560 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) 561 func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalInteger2)>(loc, builder); 562 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) 563 func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalInteger4)>(loc, builder); 564 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) 565 func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalInteger8)>(loc, builder); 566 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) 567 func = fir::runtime::getRuntimeFunc<ForcedMaxvalInteger16>(loc, builder); 568 else 569 fir::emitFatalError(loc, "invalid type in MAXVAL"); 570 571 auto fTy = func.getFunctionType(); 572 auto sourceFile = fir::factory::locationToFilename(builder, loc); 573 auto sourceLine = 574 fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); 575 auto args = fir::runtime::createArguments( 576 builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); 577 578 return builder.create<fir::CallOp>(loc, func, args).getResult(0); 579 } 580 581 /// Generate call to `MaxvalDim` intrinsic runtime routine. This is the version 582 /// that handles any rank array with the dim argument specified. 583 void fir::runtime::genMaxvalDim(fir::FirOpBuilder &builder, mlir::Location loc, 584 mlir::Value resultBox, mlir::Value arrayBox, 585 mlir::Value dim, mlir::Value maskBox) { 586 auto func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalDim)>(loc, builder); 587 genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox); 588 } 589 590 /// Generate call to `MaxvalCharacter` intrinsic runtime routine. This is the 591 /// version that handles character arrays of rank 1 and without a DIM argument. 592 void fir::runtime::genMaxvalChar(fir::FirOpBuilder &builder, mlir::Location loc, 593 mlir::Value resultBox, mlir::Value arrayBox, 594 mlir::Value maskBox) { 595 auto func = 596 fir::runtime::getRuntimeFunc<mkRTKey(MaxvalCharacter)>(loc, builder); 597 auto fTy = func.getFunctionType(); 598 auto sourceFile = fir::factory::locationToFilename(builder, loc); 599 auto sourceLine = 600 fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); 601 auto args = fir::runtime::createArguments( 602 builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, maskBox); 603 builder.create<fir::CallOp>(loc, func, args); 604 } 605 606 /// Generate call to `Minloc` intrinsic runtime routine. This is the version 607 /// that does not take a dim argument. 608 void fir::runtime::genMinloc(fir::FirOpBuilder &builder, mlir::Location loc, 609 mlir::Value resultBox, mlir::Value arrayBox, 610 mlir::Value maskBox, mlir::Value kind, 611 mlir::Value back) { 612 auto func = fir::runtime::getRuntimeFunc<mkRTKey(Minloc)>(loc, builder); 613 genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind, 614 back); 615 } 616 617 /// Generate call to `MinlocDim` intrinsic runtime routine. This is the version 618 /// that takes a dim argument. 619 void fir::runtime::genMinlocDim(fir::FirOpBuilder &builder, mlir::Location loc, 620 mlir::Value resultBox, mlir::Value arrayBox, 621 mlir::Value dim, mlir::Value maskBox, 622 mlir::Value kind, mlir::Value back) { 623 auto func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocDim)>(loc, builder); 624 genReduction5Args(func, builder, loc, resultBox, arrayBox, dim, maskBox, kind, 625 back); 626 } 627 628 /// Generate call to `MinvalDim` intrinsic runtime routine. This is the version 629 /// that handles any rank array with the dim argument specified. 630 void fir::runtime::genMinvalDim(fir::FirOpBuilder &builder, mlir::Location loc, 631 mlir::Value resultBox, mlir::Value arrayBox, 632 mlir::Value dim, mlir::Value maskBox) { 633 auto func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalDim)>(loc, builder); 634 genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox); 635 } 636 637 /// Generate call to `MinvalCharacter` intrinsic runtime routine. This is the 638 /// version that handles character arrays of rank 1 and without a DIM argument. 639 void fir::runtime::genMinvalChar(fir::FirOpBuilder &builder, mlir::Location loc, 640 mlir::Value resultBox, mlir::Value arrayBox, 641 mlir::Value maskBox) { 642 auto func = 643 fir::runtime::getRuntimeFunc<mkRTKey(MinvalCharacter)>(loc, builder); 644 auto fTy = func.getFunctionType(); 645 auto sourceFile = fir::factory::locationToFilename(builder, loc); 646 auto sourceLine = 647 fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); 648 auto args = fir::runtime::createArguments( 649 builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, maskBox); 650 builder.create<fir::CallOp>(loc, func, args); 651 } 652 653 /// Generate call to `Minval` intrinsic runtime routine. This is the version 654 /// that does not take a dim argument. 655 mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder, 656 mlir::Location loc, mlir::Value arrayBox, 657 mlir::Value maskBox) { 658 mlir::func::FuncOp func; 659 auto ty = arrayBox.getType(); 660 auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); 661 auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy(); 662 auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); 663 664 if (eleTy.isF16() || eleTy.isBF16()) 665 TODO(loc, "half-precision MINVAL"); 666 else if (eleTy.isF32()) 667 func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalReal4)>(loc, builder); 668 else if (eleTy.isF64()) 669 func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalReal8)>(loc, builder); 670 else if (eleTy.isF80()) 671 func = fir::runtime::getRuntimeFunc<ForcedMinvalReal10>(loc, builder); 672 else if (eleTy.isF128()) 673 func = fir::runtime::getRuntimeFunc<ForcedMinvalReal16>(loc, builder); 674 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) 675 func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalInteger1)>(loc, builder); 676 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) 677 func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalInteger2)>(loc, builder); 678 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) 679 func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalInteger4)>(loc, builder); 680 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) 681 func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalInteger8)>(loc, builder); 682 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) 683 func = fir::runtime::getRuntimeFunc<ForcedMinvalInteger16>(loc, builder); 684 else 685 fir::emitFatalError(loc, "invalid type in MINVAL"); 686 687 auto fTy = func.getFunctionType(); 688 auto sourceFile = fir::factory::locationToFilename(builder, loc); 689 auto sourceLine = 690 fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); 691 auto args = fir::runtime::createArguments( 692 builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); 693 694 return builder.create<fir::CallOp>(loc, func, args).getResult(0); 695 } 696 697 /// Generate call to `ProductDim` intrinsic runtime routine. This is the version 698 /// that handles any rank array with the dim argument specified. 699 void fir::runtime::genProductDim(fir::FirOpBuilder &builder, mlir::Location loc, 700 mlir::Value resultBox, mlir::Value arrayBox, 701 mlir::Value dim, mlir::Value maskBox) { 702 auto func = fir::runtime::getRuntimeFunc<mkRTKey(ProductDim)>(loc, builder); 703 genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox); 704 } 705 706 /// Generate call to `Product` intrinsic runtime routine. This is the version 707 /// that does not take a dim argument. 708 mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder, 709 mlir::Location loc, mlir::Value arrayBox, 710 mlir::Value maskBox, 711 mlir::Value resultBox) { 712 mlir::func::FuncOp func; 713 auto ty = arrayBox.getType(); 714 auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); 715 auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy(); 716 auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); 717 718 if (eleTy.isF16() || eleTy.isBF16()) 719 TODO(loc, "half-precision PRODUCT"); 720 else if (eleTy.isF32()) 721 func = fir::runtime::getRuntimeFunc<mkRTKey(ProductReal4)>(loc, builder); 722 else if (eleTy.isF64()) 723 func = fir::runtime::getRuntimeFunc<mkRTKey(ProductReal8)>(loc, builder); 724 else if (eleTy.isF80()) 725 func = fir::runtime::getRuntimeFunc<ForcedProductReal10>(loc, builder); 726 else if (eleTy.isF128()) 727 func = fir::runtime::getRuntimeFunc<ForcedProductReal16>(loc, builder); 728 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) 729 func = fir::runtime::getRuntimeFunc<mkRTKey(ProductInteger1)>(loc, builder); 730 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) 731 func = fir::runtime::getRuntimeFunc<mkRTKey(ProductInteger2)>(loc, builder); 732 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) 733 func = fir::runtime::getRuntimeFunc<mkRTKey(ProductInteger4)>(loc, builder); 734 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) 735 func = fir::runtime::getRuntimeFunc<mkRTKey(ProductInteger8)>(loc, builder); 736 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) 737 func = fir::runtime::getRuntimeFunc<ForcedProductInteger16>(loc, builder); 738 else if (eleTy == fir::ComplexType::get(builder.getContext(), 4)) 739 func = 740 fir::runtime::getRuntimeFunc<mkRTKey(CppProductComplex4)>(loc, builder); 741 else if (eleTy == fir::ComplexType::get(builder.getContext(), 8)) 742 func = 743 fir::runtime::getRuntimeFunc<mkRTKey(CppProductComplex8)>(loc, builder); 744 else if (eleTy == fir::ComplexType::get(builder.getContext(), 10)) 745 func = fir::runtime::getRuntimeFunc<ForcedProductComplex10>(loc, builder); 746 else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) 747 func = fir::runtime::getRuntimeFunc<ForcedProductComplex16>(loc, builder); 748 else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || 749 eleTy == fir::ComplexType::get(builder.getContext(), 3)) 750 TODO(loc, "half-precision PRODUCT"); 751 else 752 fir::emitFatalError(loc, "invalid type in PRODUCT"); 753 754 auto fTy = func.getFunctionType(); 755 auto sourceFile = fir::factory::locationToFilename(builder, loc); 756 if (fir::isa_complex(eleTy)) { 757 auto sourceLine = 758 fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); 759 auto args = 760 fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, 761 sourceFile, sourceLine, dim, maskBox); 762 builder.create<fir::CallOp>(loc, func, args); 763 return resultBox; 764 } 765 766 auto sourceLine = 767 fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); 768 auto args = fir::runtime::createArguments( 769 builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); 770 771 return builder.create<fir::CallOp>(loc, func, args).getResult(0); 772 } 773 774 /// Generate call to `DotProduct` intrinsic runtime routine. 775 mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder, 776 mlir::Location loc, 777 mlir::Value vectorABox, 778 mlir::Value vectorBBox, 779 mlir::Value resultBox) { 780 mlir::func::FuncOp func; 781 auto ty = vectorABox.getType(); 782 auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); 783 auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy(); 784 785 if (eleTy.isF16() || eleTy.isBF16()) 786 TODO(loc, "half-precision DOTPRODUCT"); 787 else if (eleTy.isF32()) 788 func = fir::runtime::getRuntimeFunc<mkRTKey(DotProductReal4)>(loc, builder); 789 else if (eleTy.isF64()) 790 func = fir::runtime::getRuntimeFunc<mkRTKey(DotProductReal8)>(loc, builder); 791 else if (eleTy.isF80()) 792 func = fir::runtime::getRuntimeFunc<ForcedDotProductReal10>(loc, builder); 793 else if (eleTy.isF128()) 794 func = fir::runtime::getRuntimeFunc<ForcedDotProductReal16>(loc, builder); 795 else if (eleTy == fir::ComplexType::get(builder.getContext(), 4)) 796 func = fir::runtime::getRuntimeFunc<mkRTKey(CppDotProductComplex4)>( 797 loc, builder); 798 else if (eleTy == fir::ComplexType::get(builder.getContext(), 8)) 799 func = fir::runtime::getRuntimeFunc<mkRTKey(CppDotProductComplex8)>( 800 loc, builder); 801 else if (eleTy == fir::ComplexType::get(builder.getContext(), 10)) 802 func = 803 fir::runtime::getRuntimeFunc<ForcedDotProductComplex10>(loc, builder); 804 else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) 805 func = 806 fir::runtime::getRuntimeFunc<ForcedDotProductComplex16>(loc, builder); 807 else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || 808 eleTy == fir::ComplexType::get(builder.getContext(), 3)) 809 TODO(loc, "half-precision DOTPRODUCT"); 810 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) 811 func = 812 fir::runtime::getRuntimeFunc<mkRTKey(DotProductInteger1)>(loc, builder); 813 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) 814 func = 815 fir::runtime::getRuntimeFunc<mkRTKey(DotProductInteger2)>(loc, builder); 816 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) 817 func = 818 fir::runtime::getRuntimeFunc<mkRTKey(DotProductInteger4)>(loc, builder); 819 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) 820 func = 821 fir::runtime::getRuntimeFunc<mkRTKey(DotProductInteger8)>(loc, builder); 822 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) 823 func = 824 fir::runtime::getRuntimeFunc<ForcedDotProductInteger16>(loc, builder); 825 else if (eleTy.isa<fir::LogicalType>()) 826 func = 827 fir::runtime::getRuntimeFunc<mkRTKey(DotProductLogical)>(loc, builder); 828 else 829 fir::emitFatalError(loc, "invalid type in DOTPRODUCT"); 830 831 auto fTy = func.getFunctionType(); 832 auto sourceFile = fir::factory::locationToFilename(builder, loc); 833 834 if (fir::isa_complex(eleTy)) { 835 auto sourceLine = 836 fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); 837 auto args = 838 fir::runtime::createArguments(builder, loc, fTy, resultBox, vectorABox, 839 vectorBBox, sourceFile, sourceLine); 840 builder.create<fir::CallOp>(loc, func, args); 841 return resultBox; 842 } 843 844 auto sourceLine = 845 fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); 846 auto args = fir::runtime::createArguments(builder, loc, fTy, vectorABox, 847 vectorBBox, sourceFile, sourceLine); 848 return builder.create<fir::CallOp>(loc, func, args).getResult(0); 849 } 850 /// Generate call to `SumDim` intrinsic runtime routine. This is the version 851 /// that handles any rank array with the dim argument specified. 852 void fir::runtime::genSumDim(fir::FirOpBuilder &builder, mlir::Location loc, 853 mlir::Value resultBox, mlir::Value arrayBox, 854 mlir::Value dim, mlir::Value maskBox) { 855 auto func = fir::runtime::getRuntimeFunc<mkRTKey(SumDim)>(loc, builder); 856 genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox); 857 } 858 859 /// Generate call to `Sum` intrinsic runtime routine. This is the version 860 /// that does not take a dim argument. 861 mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, 862 mlir::Value arrayBox, mlir::Value maskBox, 863 mlir::Value resultBox) { 864 mlir::func::FuncOp func; 865 auto ty = arrayBox.getType(); 866 auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); 867 auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy(); 868 auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); 869 870 if (eleTy.isF16() || eleTy.isBF16()) 871 TODO(loc, "half-precision SUM"); 872 else if (eleTy.isF32()) 873 func = fir::runtime::getRuntimeFunc<mkRTKey(SumReal4)>(loc, builder); 874 else if (eleTy.isF64()) 875 func = fir::runtime::getRuntimeFunc<mkRTKey(SumReal8)>(loc, builder); 876 else if (eleTy.isF80()) 877 func = fir::runtime::getRuntimeFunc<ForcedSumReal10>(loc, builder); 878 else if (eleTy.isF128()) 879 func = fir::runtime::getRuntimeFunc<ForcedSumReal16>(loc, builder); 880 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) 881 func = fir::runtime::getRuntimeFunc<mkRTKey(SumInteger1)>(loc, builder); 882 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(2))) 883 func = fir::runtime::getRuntimeFunc<mkRTKey(SumInteger2)>(loc, builder); 884 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(4))) 885 func = fir::runtime::getRuntimeFunc<mkRTKey(SumInteger4)>(loc, builder); 886 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(8))) 887 func = fir::runtime::getRuntimeFunc<mkRTKey(SumInteger8)>(loc, builder); 888 else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) 889 func = fir::runtime::getRuntimeFunc<ForcedSumInteger16>(loc, builder); 890 else if (eleTy == fir::ComplexType::get(builder.getContext(), 4)) 891 func = fir::runtime::getRuntimeFunc<mkRTKey(CppSumComplex4)>(loc, builder); 892 else if (eleTy == fir::ComplexType::get(builder.getContext(), 8)) 893 func = fir::runtime::getRuntimeFunc<mkRTKey(CppSumComplex8)>(loc, builder); 894 else if (eleTy == fir::ComplexType::get(builder.getContext(), 10)) 895 func = fir::runtime::getRuntimeFunc<ForcedSumComplex10>(loc, builder); 896 else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) 897 func = fir::runtime::getRuntimeFunc<ForcedSumComplex16>(loc, builder); 898 else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || 899 eleTy == fir::ComplexType::get(builder.getContext(), 3)) 900 TODO(loc, "half-precision SUM"); 901 else 902 fir::emitFatalError(loc, "invalid type in SUM"); 903 904 auto fTy = func.getFunctionType(); 905 auto sourceFile = fir::factory::locationToFilename(builder, loc); 906 if (fir::isa_complex(eleTy)) { 907 auto sourceLine = 908 fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); 909 auto args = 910 fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, 911 sourceFile, sourceLine, dim, maskBox); 912 builder.create<fir::CallOp>(loc, func, args); 913 return resultBox; 914 } 915 916 auto sourceLine = 917 fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); 918 auto args = fir::runtime::createArguments( 919 builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox); 920 921 return builder.create<fir::CallOp>(loc, func, args).getResult(0); 922 } 923