Index: flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp =================================================================== --- flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp +++ flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp @@ -578,6 +578,22 @@ mlir::Location loc = call.getLoc(); fir::FirOpBuilder builder(op, kindMap); + // Inherit FastMathFlags from the call operation by configuring + // the builder accordingly. + std::string fmfString{}; + auto fmi = mlir::dyn_cast(*op); + if (fmi) { + mlir::arith::FastMathFlags flags = + fmi.getFastMathFlagsAttr().getValue(); + if (flags != mlir::arith::FastMathFlags::none) { + builder.setFastMathFlags(flags); + // Stringize FastMathFlags flags for mangling the generated + // function name. + fmfString = mlir::arith::stringifyFastMathFlags(flags); + std::replace(fmfString.begin(), fmfString.end(), ',', '_'); + } + } + mlir::Type type = call.getResult(0).getType(); if (!type.isa() && !type.isa()) return; @@ -611,9 +627,13 @@ // of the arguments. std::string typedFuncName(funcName); llvm::raw_string_ostream nameOS(typedFuncName); - nameOS << "_"; + // We must mangle the generated function name with FastMathFlags + // value. + if (!fmfString.empty()) + nameOS << '_' << fmfString; + nameOS << '_'; arg1Type->print(nameOS); - nameOS << "_"; + nameOS << '_'; arg2Type->print(nameOS); mlir::func::FuncOp newFunc = getOrCreateFunction( Index: flang/test/Transforms/simplifyintrinsics.fir =================================================================== --- flang/test/Transforms/simplifyintrinsics.fir +++ flang/test/Transforms/simplifyintrinsics.fir @@ -998,3 +998,42 @@ // CHECK-NOT: call{{.*}}_FortranASumInteger8( // CHECK: call @_FortranASumInteger8x2_simplified( // CHECK-NOT: call{{.*}}_FortranASumInteger8( + +// ----- + +func.func @dot_f32_contract_reassoc(%arg0: !fir.box> {fir.bindc_name = "a"}, %arg1: !fir.box> {fir.bindc_name = "b"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "dot", uniq_name = "_QFdotEdot"} + %1 = fir.address_of(@_QQcl.2E2F646F742E66393000) : !fir.ref> + %c3_i32 = arith.constant 3 : i32 + %2 = fir.convert %arg0 : (!fir.box>) -> !fir.box + %3 = fir.convert %arg1 : (!fir.box>) -> !fir.box + %4 = fir.convert %1 : (!fir.ref>) -> !fir.ref + %5 = fir.call @_FortranADotProductReal4(%2, %3, %4, %c3_i32) fastmath : (!fir.box, !fir.box, !fir.ref, i32) -> f32 + fir.store %5 to %0 : !fir.ref + %6 = fir.load %0 : !fir.ref + return %6 : f32 +} + +func.func @dot_f32_fast(%arg0: !fir.box> {fir.bindc_name = "a"}, %arg1: !fir.box> {fir.bindc_name = "b"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "dot", uniq_name = "_QFdotEdot"} + %1 = fir.address_of(@_QQcl.2E2F646F742E66393000) : !fir.ref> + %c3_i32 = arith.constant 3 : i32 + %2 = fir.convert %arg0 : (!fir.box>) -> !fir.box + %3 = fir.convert %arg1 : (!fir.box>) -> !fir.box + %4 = fir.convert %1 : (!fir.ref>) -> !fir.ref + %5 = fir.call @_FortranADotProductReal4(%2, %3, %4, %c3_i32) fastmath : (!fir.box, !fir.box, !fir.ref, i32) -> f32 + fir.store %5 to %0 : !fir.ref + %6 = fir.load %0 : !fir.ref + return %6 : f32 +} + +// CHECK-LABEL: @dot_f32_contract_reassoc +// CHECK: fir.call @_FortranADotProductReal4_reassoc_contract_f32_f32_simplified(%2, %3) fastmath +// CHECK-LABEL: @dot_f32_fast +// CHECK: fir.call @_FortranADotProductReal4_fast_f32_f32_simplified(%2, %3) fastmath +// CHECK-LABEL: func.func private @_FortranADotProductReal4_reassoc_contract_f32_f32_simplified +// CHECK: arith.mulf %{{.*}}, %{{.*}} fastmath : f32 +// CHECK: arith.addf %{{.*}}, %{{.*}} fastmath : f32 +// CHECK-LABEL: func.func private @_FortranADotProductReal4_fast_f32_f32_simplified +// CHECK: arith.mulf %{{.*}}, %{{.*}} fastmath : f32 +// CHECK: arith.addf %{{.*}}, %{{.*}} fastmath : f32