From 6c7cfbe34e7bb98cf3cb71a92ba89b580b77958d Mon Sep 17 00:00:00 2001 From: David Truby Date: Mon, 17 Jun 2024 13:24:51 +0000 Subject: [PATCH] [flang] Allow derf as alternate spelling for erf This patch adds derf as an alternate spelling for the erf intrinsic. This spelling is supported by multiple other compilers and used by WRF. --- flang/lib/Evaluate/fold-real.cpp | 3 + flang/lib/Evaluate/intrinsics.cpp | 1 + flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 5 ++ flang/test/Evaluate/folding02.f90 | 3 + flang/test/Intrinsics/math-codegen.fir | 80 +++++++++++++++++++ 5 files changed, 92 insertions(+) diff --git a/flang/lib/Evaluate/fold-real.cpp b/flang/lib/Evaluate/fold-real.cpp index f71addcc4094a..d951197b8eb6c 100644 --- a/flang/lib/Evaluate/fold-real.cpp +++ b/flang/lib/Evaluate/fold-real.cpp @@ -153,6 +153,9 @@ Expr> FoldIntrinsicFunction( auto *intrinsic{std::get_if(&funcRef.proc().u)}; CHECK(intrinsic); std::string name{intrinsic->name}; + if (name == "derf") { + name = "erf"; + } if (name == "acos" || name == "acosh" || name == "asin" || name == "asinh" || (name == "atan" && args.size() == 1) || name == "atanh" || name == "bessel_j0" || name == "bessel_j1" || name == "bessel_y0" || diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index ace316174a892..212134b75c97d 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -403,6 +403,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"shift", AnyInt, Rank::dimRemovedOrScalar}, OptionalDIM}, SameType, Rank::conformable, IntrinsicClass::transformationalFunction}, {"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision}, + {"derf", {{"x", SameReal}}, SameReal}, {"digits", {{"x", AnyIntOrReal, Rank::anyOrAssumedRank, Optionality::required, common::Intent::In, {ArgFlag::canBeMoldNull}}}, diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index ab106f62aecfb..beb9011ee5fe6 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -1101,6 +1101,11 @@ static constexpr MathOperation mathOperations[] = { {"cosh", "ccosh", genFuncType, Ty::Complex<8>>, genLibCall}, {"cosh", RTNAME_STRING(CCoshF128), FuncTypeComplex16Complex16, genLibF128Call}, + {"derf", "derff", genFuncType, Ty::Real<4>>, + genMathOp}, + {"derf", "derf", genFuncType, Ty::Real<8>>, + genMathOp}, + {"derf", RTNAME_STRING(ErfF128), FuncTypeReal16Real16, genLibF128Call}, {"divc", {}, genFuncType, Ty::Complex<2>, Ty::Complex<2>>, diff --git a/flang/test/Evaluate/folding02.f90 b/flang/test/Evaluate/folding02.f90 index 89e2a09aa31b7..4581b3cf8ea5b 100644 --- a/flang/test/Evaluate/folding02.f90 +++ b/flang/test/Evaluate/folding02.f90 @@ -57,6 +57,7 @@ module m TEST_R4(atanh, atanh(0.8_4), 1.098612308502197265625_4) TEST_R4(cos, cos(0.5_4), 0.877582550048828125_4) TEST_R4(cosh, cosh(0.1_4), 1.0050041675567626953125_4) + TEST_R4(derf, derf(1._4), 0.842700779438018798828125_4) TEST_R4(erf, erf(1._4), 0.842700779438018798828125_4) TEST_R4(erfc, erfc(0.1_4), 0.887537062168121337890625_4) TEST_R4(exp, exp(0.1_4), 1.1051709651947021484375_4) @@ -97,6 +98,8 @@ module m 0.8775825618903727587394314468838274478912353515625_8) TEST_R8(cosh, cosh(0.1_8), & 1.0050041680558035039894093642942607402801513671875_8) + TEST_R8(derf, derf(1._8), & + 0.84270079294971489414223242420121096074581146240234375_8) TEST_R8(erf, erf(1._8), & 0.84270079294971489414223242420121096074581146240234375_8) TEST_R8(erfc, erfc(0.1_8), & diff --git a/flang/test/Intrinsics/math-codegen.fir b/flang/test/Intrinsics/math-codegen.fir index 62d841253075e..4555e33fead20 100644 --- a/flang/test/Intrinsics/math-codegen.fir +++ b/flang/test/Intrinsics/math-codegen.fir @@ -862,6 +862,86 @@ func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}) -> f64 { func.func private @erff(f32) -> f32 func.func private @erf(f64) -> f64 + +//--- derf_fast.fir +// RUN: fir-opt %t/derf_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/derf_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erff({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erf({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.erf %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.erf %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- derf_relaxed.fir +// RUN: fir-opt %t/derf_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/derf_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erff({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erf({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.erf %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.erf %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- derf_precise.fir +// RUN: fir-opt %t/derf_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/derf_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erff({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erf({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @erff(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @erf(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @erff(f32) -> f32 +func.func private @erf(f64) -> f64 + + + //--- exp_fast.fir // RUN: fir-opt %t/exp_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exp_fast.fir // CHECK: @_QPtest_real4