From e3b74caa0dec420b441211ed1d3787ac5e61274a Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Fri, 22 Mar 2019 02:01:22 -0700 Subject: [PATCH] [flang] Move host floating point environment handling in host.h/host.cc Original-commit: flang-compiler/f18@0cba8b13089b12f4add5323e9c595e5367ece48e Tree-same-pre-rewrite: false --- flang/lib/evaluate/CMakeLists.txt | 3 +- flang/lib/evaluate/host.cc | 112 ++++++++++++++++++++++ flang/lib/evaluate/host.h | 12 +++ flang/lib/evaluate/intrinsics-library-templates.h | 15 +-- flang/lib/evaluate/intrinsics-library.cc | 104 ++------------------ 5 files changed, 133 insertions(+), 113 deletions(-) create mode 100644 flang/lib/evaluate/host.cc diff --git a/flang/lib/evaluate/CMakeLists.txt b/flang/lib/evaluate/CMakeLists.txt index e4b66d2..0322046 100644 --- a/flang/lib/evaluate/CMakeLists.txt +++ b/flang/lib/evaluate/CMakeLists.txt @@ -21,15 +21,16 @@ add_library(FortranEvaluate decimal.cc expression.cc fold.cc + host.cc integer.cc intrinsics.cc + intrinsics-library.cc logical.cc real.cc static-data.cc tools.cc type.cc variable.cc - intrinsics-library.cc ) target_link_libraries(FortranEvaluate diff --git a/flang/lib/evaluate/host.cc b/flang/lib/evaluate/host.cc new file mode 100644 index 0000000..680a6c7 --- /dev/null +++ b/flang/lib/evaluate/host.cc @@ -0,0 +1,112 @@ +// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "host.h" + +#include "../common/idioms.h" +#include +#include + +namespace Fortran::evaluate::host { +using namespace Fortran::parser::literals; + +void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment( + FoldingContext &context) { + errno = 0; + if (feholdexcept(&originalFenv_) != 0) { + common::die("Folding with host runtime: feholdexcept() failed: %s", + std::strerror(errno)); + return; + } + if (fegetenv(¤tFenv_) != 0) { + common::die("Folding with host runtime: fegetenv() failed: %s", + std::strerror(errno)); + return; + } +#if __x86_64__ + if (context.flushSubnormalsToZero()) { + currentFenv_.__mxcsr |= 0x8000; // result + currentFenv_.__mxcsr |= 0x0040; // operands + } else { + currentFenv_.__mxcsr &= ~0x8000; // result + currentFenv_.__mxcsr &= ~0x0040; // operands + } +#else + // TODO other architectures + context.messages().Say( + "TODO: flushing mode for subnormals is not set for this host architecture when folding with host runtime functions"_en_US); +#endif + errno = 0; + if (fesetenv(¤tFenv_) != 0) { + common::die("Folding with host runtime: fesetenv() failed: %s", + std::strerror(errno)); + return; + } + switch (context.rounding().mode) { + case RoundingMode::TiesToEven: fesetround(FE_TONEAREST); break; + case RoundingMode::ToZero: fesetround(FE_TOWARDZERO); break; + case RoundingMode::Up: fesetround(FE_UPWARD); break; + case RoundingMode::Down: fesetround(FE_DOWNWARD); break; + case RoundingMode::TiesAwayFromZero: + fesetround(FE_TONEAREST); + context.messages().Say( + "TiesAwayFromZero rounding mode is not available not available when folding constants with host runtime. Using TiesToEven instead."_en_US); + break; + } + errno = 0; +} +void HostFloatingPointEnvironment::CheckAndRestoreFloatingPointEnvironment( + FoldingContext &context) { + int errnoCapture{errno}; + int exceptions{fetestexcept(FE_ALL_EXCEPT)}; + RealFlags flags; + if (exceptions & FE_INVALID) { + flags.set(RealFlag::InvalidArgument); + } + if (exceptions & FE_DIVBYZERO) { + flags.set(RealFlag::DivideByZero); + } + if (exceptions & FE_OVERFLOW) { + flags.set(RealFlag::Overflow); + } + if (exceptions & FE_UNDERFLOW) { + flags.set(RealFlag::Underflow); + } + if (exceptions & FE_INEXACT) { + flags.set(RealFlag::Inexact); + } + + if (flags.empty()) { + if (errnoCapture == EDOM) { + flags.set(RealFlag::InvalidArgument); + } + if (errnoCapture == ERANGE) { + // can't distinguish over/underflow from errno + flags.set(RealFlag::Overflow); + } + } + + if (!flags.empty()) { + RealFlagWarnings(context, flags, "folding function with host runtime"); + } + errno = 0; + if (fesetenv(&originalFenv_) != 0) { + std::fprintf(stderr, "fesetenv() failed: %s\n", std::strerror(errno)); + common::die( + "Folding with host runtime: fesetenv() failed while restoring fenv: %s", + std::strerror(errno)); + } + errno = 0; +} +} diff --git a/flang/lib/evaluate/host.h b/flang/lib/evaluate/host.h index 5bd7e25..ab826b0 100644 --- a/flang/lib/evaluate/host.h +++ b/flang/lib/evaluate/host.h @@ -24,6 +24,7 @@ // to safely refer to this hardware type. #include "type.h" +#include #include #include #include @@ -33,6 +34,17 @@ namespace Fortran::evaluate { namespace host { +// Helper class to handle host runtime traps, status flag and errno +class HostFloatingPointEnvironment { +public: + void SetUpHostFloatingPointEnvironment(FoldingContext &); + void CheckAndRestoreFloatingPointEnvironment(FoldingContext &); + +private: + std::fenv_t originalFenv_; + std::fenv_t currentFenv_; +}; + // Type mapping from F18 types to host types struct UnsupportedType {}; // There is no host type for the F18 type diff --git a/flang/lib/evaluate/intrinsics-library-templates.h b/flang/lib/evaluate/intrinsics-library-templates.h index 3a14ecf..0f6364b0 100644 --- a/flang/lib/evaluate/intrinsics-library-templates.h +++ b/flang/lib/evaluate/intrinsics-library-templates.h @@ -27,14 +27,12 @@ #include "type.h" #include "../common/template.h" -#include #include #include namespace Fortran::evaluate { // Define meaningful types for the runtime -// TODO: add the support for void and descriptor using RuntimeTypes = evaluate::AllIntrinsicTypes; template struct IndexInTupleHelper {}; @@ -62,24 +60,13 @@ template using HostFuncPointer = FuncPointer, HostArgType...>; -// Helper class to handle host runtime traps, status flag and errno -class HostFloatingPointEnvironment { -public: - void SetUpHostFloatingPointEnvironment(FoldingContext &); - void CheckAndRestoreFloatingPointEnvironment(FoldingContext &); - -private: - std::fenv_t originalFenv_; - std::fenv_t currentFenv_; -}; - // Callable factory template struct CallableHostWrapper { static Scalar scalarCallable(FoldingContext &context, HostFuncPointer func, const Scalar &... x) { if constexpr (host::HostTypeExists()) { - HostFloatingPointEnvironment hostFPE; + host::HostFloatingPointEnvironment hostFPE; hostFPE.SetUpHostFloatingPointEnvironment(context); host::HostType res{ func(host::CastFortranToHost(x)...)}; diff --git a/flang/lib/evaluate/intrinsics-library.cc b/flang/lib/evaluate/intrinsics-library.cc index c24ac56..94b95f6 100644 --- a/flang/lib/evaluate/intrinsics-library.cc +++ b/flang/lib/evaluate/intrinsics-library.cc @@ -12,20 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -// This file defines host runtimes functions that can be used for folding +// This file defines host runtime functions that can be used for folding // intrinsic functions. // The default HostIntrinsicProceduresLibrary is built with and // functions that are guaranteed to exist from the C++ standard. #include "intrinsics-library-templates.h" -#include "../common/idioms.h" -#include -#include -#include +#include +#include namespace Fortran::evaluate { -using namespace Fortran::parser::literals; // Note: argument passing is ignored in equivalence bool HostIntrinsicProceduresLibrary::HasEquivalentProcedure( const IntrinsicProcedureRuntimeDescription &sym) const { @@ -53,8 +50,8 @@ bool HostIntrinsicProceduresLibrary::HasEquivalentProcedure( // Map numerical intrinsic to / functions -// TODO mapping to function to be tested. func takes -// real arg for n +// C++ Bessel functions take a floating point as first argument. +// Fortran Bessel functions take an integer. template static HostT Bessel_jn(std::int64_t n, HostT x) { return std::cyl_bessel_j(static_cast(n), x); } @@ -103,7 +100,7 @@ void AddLibmComplexHostProcedure( } } -// Defines which host runtime functions will be used for folding +// Define which host runtime functions will be used for folding void HostIntrinsicProceduresLibrary::DefaultInit() { @@ -115,93 +112,4 @@ void HostIntrinsicProceduresLibrary::DefaultInit() { AddLibmComplexHostProcedure(*this); AddLibmComplexHostProcedure(*this); } - -void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment( - FoldingContext &context) { - errno = 0; - if (feholdexcept(&originalFenv_) != 0) { - common::die("Folding with host runtime: feholdexcept() failed: %s", - std::strerror(errno)); - return; - } - if (fegetenv(¤tFenv_) != 0) { - common::die("Folding with host runtime: fegetenv() failed: %s", - std::strerror(errno)); - return; - } -#if __x86_64__ - if (context.flushSubnormalsToZero()) { - currentFenv_.__mxcsr |= 0x8000; // result - currentFenv_.__mxcsr |= 0x0040; // operands - } else { - currentFenv_.__mxcsr &= ~0x8000; // result - currentFenv_.__mxcsr &= ~0x0040; // operands - } -#else - // TODO other architectures - context.messages().Say( - "TODO: flushing mode for subnormals is not set for this host architecture when folding with host runtime functions"_en_US); -#endif - errno = 0; - if (fesetenv(¤tFenv_) != 0) { - common::die("Folding with host runtime: fesetenv() failed: %s", - std::strerror(errno)); - return; - } - switch (context.rounding().mode) { - case RoundingMode::TiesToEven: fesetround(FE_TONEAREST); break; - case RoundingMode::ToZero: fesetround(FE_TOWARDZERO); break; - case RoundingMode::Up: fesetround(FE_UPWARD); break; - case RoundingMode::Down: fesetround(FE_DOWNWARD); break; - case RoundingMode::TiesAwayFromZero: - fesetround(FE_TONEAREST); - context.messages().Say( - "TiesAwayFromZero rounding mode is not available not available when folding constants with host runtime. Using TiesToEven instead."_en_US); - break; - } - errno = 0; -} -void HostFloatingPointEnvironment::CheckAndRestoreFloatingPointEnvironment( - FoldingContext &context) { - int errnoCapture{errno}; - int exceptions{fetestexcept(FE_ALL_EXCEPT)}; - RealFlags flags; - if (exceptions & FE_INVALID) { - flags.set(RealFlag::InvalidArgument); - } - if (exceptions & FE_DIVBYZERO) { - flags.set(RealFlag::DivideByZero); - } - if (exceptions & FE_OVERFLOW) { - flags.set(RealFlag::Overflow); - } - if (exceptions & FE_UNDERFLOW) { - flags.set(RealFlag::Underflow); - } - if (exceptions & FE_INEXACT) { - flags.set(RealFlag::Inexact); - } - - if (flags.empty()) { - if (errnoCapture == EDOM) { - flags.set(RealFlag::InvalidArgument); - } - if (errnoCapture == ERANGE) { - // can't distinguish over/underflow from errno - flags.set(RealFlag::Overflow); - } - } - - if (!flags.empty()) { - RealFlagWarnings(context, flags, "folding function with host runtime"); - } - errno = 0; - if (fesetenv(&originalFenv_) != 0) { - std::fprintf(stderr, "fesetenv() failed: %s\n", std::strerror(errno)); - common::die( - "Folding with host runtime: fesetenv() failed while restoring fenv: %s", - std::strerror(errno)); - } - errno = 0; -} } -- 2.7.4