diff --git a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp --- a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp +++ b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp @@ -271,6 +271,35 @@ genReductionLoop(builder, funcOp, init, genBodyOp, rank); } +static void genRuntimeMinvalBody(fir::FirOpBuilder &builder, + mlir::func::FuncOp &funcOp, unsigned rank) { + auto init = [](fir::FirOpBuilder builder, mlir::Location loc, + mlir::Type elementType) { + if (auto ty = elementType.dyn_cast()) { + const llvm::fltSemantics &sem = ty.getFloatSemantics(); + return builder.createRealConstant(loc, elementType, + llvm::APFloat::getLargest(sem)); + } + unsigned bits = elementType.getIntOrFloatBitWidth(); + int64_t maxInt = llvm::APInt::getSignedMaxValue(bits).getSExtValue(); + return builder.createIntegerConstant(loc, elementType, maxInt); + }; + + auto genBodyOp = [](fir::FirOpBuilder builder, mlir::Location loc, + mlir::Type elementType, mlir::Value elem1, + mlir::Value elem2) { + mlir::Value res; + if (elementType.isa()) + res = builder.create(loc, elem1, elem2); + else if (elementType.isa()) + res = builder.create(loc, elem1, elem2); + else + llvm_unreachable("unsupported type"); + return res; + }; + genReductionLoop(builder, funcOp, init, genBodyOp, rank); +} + /// Generate function type for the simplified version of RTNAME(DotProduct) /// operating on the given \p elementType. static mlir::FunctionType genRuntimeDotType(fir::FirOpBuilder &builder, @@ -636,6 +665,10 @@ simplifyReduction(call, kindMap, genRuntimeMaxvalBody); return; } + if (funcName.startswith(RTNAME_STRING(Minval))) { + simplifyReduction(call, kindMap, genRuntimeMinvalBody); + return; + } } } }); diff --git a/flang/test/Transforms/simplifyintrinsics.fir b/flang/test/Transforms/simplifyintrinsics.fir --- a/flang/test/Transforms/simplifyintrinsics.fir +++ b/flang/test/Transforms/simplifyintrinsics.fir @@ -998,3 +998,59 @@ // CHECK-NOT: call{{.*}}_FortranASumInteger8( // CHECK: call @_FortranASumInteger8x2_simplified( // CHECK-NOT: call{{.*}}_FortranASumInteger8( + +// ----- + +// Call to MINVAL with 1D I32 array is replaced. +module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.target_triple = "native"} { + func.func @minval_1d_array_int(%arg0: !fir.ref> {fir.bindc_name = "a"}) -> i32 { + %c10 = arith.constant 10 : index + %0 = fir.alloca i32 {bindc_name = "test_min_2", uniq_name = "_QFtest_min_2Etest_min_2"} + %1 = fir.shape %c10 : (index) -> !fir.shape<1> + %2 = fir.embox %arg0(%1) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + %3 = fir.absent !fir.box + %c0 = arith.constant 0 : index + %4 = fir.address_of(@_QQcl.2E2F696D61785F322E66393000) : !fir.ref> + %c5_i32 = arith.constant 5 : i32 + %5 = fir.convert %2 : (!fir.box>) -> !fir.box + %6 = fir.convert %4 : (!fir.ref>) -> !fir.ref + %7 = fir.convert %c0 : (index) -> i32 + %8 = fir.convert %3 : (!fir.box) -> !fir.box + %9 = fir.call @_FortranAMinvalInteger4(%5, %6, %c5_i32, %7, %8) : (!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 + fir.store %9 to %0 : !fir.ref + %10 = fir.load %0 : !fir.ref + return %10 : i32 + } + func.func private @_FortranAMinvalInteger4(!fir.box, !fir.ref, i32, i32, !fir.box) -> i32 attributes {fir.runtime} + fir.global linkonce @_QQcl.2E2F696D61785F322E66393000 constant : !fir.char<1,13> { + %0 = fir.string_lit "./imin_2.f90\00"(13) : !fir.char<1,13> + fir.has_value %0 : !fir.char<1,13> + } +} + +// CHECK-LABEL: func.func @minval_1d_array_int( +// CHECK-SAME: %[[A:.*]]: !fir.ref> {fir.bindc_name = "a"}) -> i32 { +// CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +// CHECK: %[[A_BOX_I32:.*]] = fir.embox %[[A]](%[[SHAPE]]) : (!fir.ref>, !fir.shape<1>) -> !fir.box> +// CHECK: %[[A_BOX_NONE:.*]] = fir.convert %[[A_BOX_I32]] : (!fir.box>) -> !fir.box +// CHECK: %[[RES:.*]] = fir.call @_FortranAMinvalInteger4x1_simplified(%[[A_BOX_NONE]]) : (!fir.box) -> i32 +// CHECK: return %{{.*}} : i32 +// CHECK: } + +// CHECK-LABEL: func.func private @_FortranAMinvalInteger4x1_simplified( +// CHECK-SAME: %[[ARR:.*]]: !fir.box) -> i32 attributes {llvm.linkage = #llvm.linkage} { +// CHECK: %[[CINDEX_0:.*]] = arith.constant 0 : index +// CHECK: %[[ARR_BOX_I32:.*]] = fir.convert %[[ARR]] : (!fir.box) -> !fir.box> +// CHECK: %[[CI32_MININT:.*]] = arith.constant 2147483647 : i32 +// CHECK: %[[CINDEX_1:.*]] = arith.constant 1 : index +// CHECK: %[[DIMIDX_0:.*]] = arith.constant 0 : index +// CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[ARR_BOX_I32]], %[[DIMIDX_0]] : (!fir.box>, index) -> (index, index, index) +// CHECK: %[[EXTENT:.*]] = arith.subi %[[DIMS]]#1, %[[CINDEX_1]] : index +// CHECK: %[[RES:.*]] = fir.do_loop %[[ITER:.*]] = %[[CINDEX_0]] to %[[EXTENT]] step %[[CINDEX_1]] iter_args(%[[MIN:.*]] = %[[CI32_MININT]]) -> (i32) { +// CHECK: %[[ITEM:.*]] = fir.coordinate_of %[[ARR_BOX_I32]], %[[ITER]] : (!fir.box>, index) -> !fir.ref +// CHECK: %[[ITEM_VAL:.*]] = fir.load %[[ITEM]] : !fir.ref +// CHECK: %[[NEW_MIN:.*]] = arith.minsi %[[ITEM_VAL]], %[[MIN]] : i32 +// CHECK: fir.result %[[NEW_MIN]] : i32 +// CHECK: } +// CHECK: return %[[RES]] : i32 +// CHECK: }