From: Jean Perier Date: Thu, 6 Jun 2019 10:24:35 +0000 (-0700) Subject: [flang] Fix 482: do not check floating point environment flags with clang X-Git-Tag: llvmorg-12-init~9537^2~1160 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=057b6875f7858aaeef8c1944e07076fb31fe642c;p=platform%2Fupstream%2Fllvm.git [flang] Fix 482: do not check floating point environment flags with clang Original-commit: flang-compiler/f18@fc423c151654055e50c3fad563be4e0a6afd7348 Reviewed-on: https://github.com/flang-compiler/f18/pull/483 Tree-same-pre-rewrite: false --- diff --git a/flang/lib/evaluate/host.cc b/flang/lib/evaluate/host.cc index f2cc383..e41e01d 100644 --- a/flang/lib/evaluate/host.cc +++ b/flang/lib/evaluate/host.cc @@ -66,6 +66,15 @@ void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment( // If F18 is not built on one of the above host architecture, software // flushing will be performed around host library calls if needed. #endif + +#ifdef __clang__ + // clang does not ensure that floating point environment flags are meaningful. + // It may perform optimizations that will impact the floating point + // environment. For instance, libc++ complex float tan and tanh compilation + // with clang -O2 introduces a division by zero on X86 in unused slots of xmm + // registers. Therefore, fetestexcept should not be used. + hardwareFlagsAreReliable_ = false; +#endif errno = 0; if (fesetenv(¤tFenv_) != 0) { common::die("Folding with host runtime: fesetenv() failed: %s", @@ -83,41 +92,43 @@ void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment( "TiesAwayFromZero rounding mode is not available not available when folding constants with host runtime. Using TiesToEven instead."_en_US); break; } + flags_.clear(); 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 (hardwareFlagsAreReliable()) { + int exceptions{fetestexcept(FE_ALL_EXCEPT)}; + 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 (flags_.empty()) { if (errnoCapture == EDOM) { - flags.set(RealFlag::InvalidArgument); + flags_.set(RealFlag::InvalidArgument); } if (errnoCapture == ERANGE) { // can't distinguish over/underflow from errno - flags.set(RealFlag::Overflow); + flags_.set(RealFlag::Overflow); } } - if (!flags.empty()) { - RealFlagWarnings(context, flags, "folding function with host runtime"); + if (!flags_.empty()) { + RealFlagWarnings(context, flags_, "intrinsic function"); } errno = 0; if (fesetenv(&originalFenv_) != 0) { diff --git a/flang/lib/evaluate/host.h b/flang/lib/evaluate/host.h index 7dca52f..fe7dcf5 100644 --- a/flang/lib/evaluate/host.h +++ b/flang/lib/evaluate/host.h @@ -39,14 +39,18 @@ class HostFloatingPointEnvironment { public: void SetUpHostFloatingPointEnvironment(FoldingContext &); void CheckAndRestoreFloatingPointEnvironment(FoldingContext &); - bool hasSubnormalFlushingHardwareControl() { + bool hasSubnormalFlushingHardwareControl() const { return hasSubnormalFlushingHardwareControl_; } + void SetFlag(RealFlag flag) { flags_.set(flag); } + bool hardwareFlagsAreReliable() const { return hardwareFlagsAreReliable_; } private: std::fenv_t originalFenv_; std::fenv_t currentFenv_; + RealFlags flags_; bool hasSubnormalFlushingHardwareControl_{false}; + bool hardwareFlagsAreReliable_{true}; }; // Type mapping from F18 types to host types diff --git a/flang/lib/evaluate/intrinsics-library-templates.h b/flang/lib/evaluate/intrinsics-library-templates.h index 1a10fec..7bc1e67 100644 --- a/flang/lib/evaluate/intrinsics-library-templates.h +++ b/flang/lib/evaluate/intrinsics-library-templates.h @@ -88,24 +88,42 @@ template struct CallableHostWrapper { if constexpr (host::HostTypeExists()) { host::HostFloatingPointEnvironment hostFPE; hostFPE.SetUpHostFloatingPointEnvironment(context); - host::HostType res{}; + host::HostType hostResult{}; + Scalar result{}; if (context.flushSubnormalsToZero() && !hostFPE.hasSubnormalFlushingHardwareControl()) { - res = func(host::CastFortranToHost( + hostResult = func(host::CastFortranToHost( Flusher::FlushSubnormals(x))...); - hostFPE.CheckAndRestoreFloatingPointEnvironment(context); - return Flusher::FlushSubnormals(host::CastHostToFortran(res)); + result = Flusher::FlushSubnormals( + host::CastHostToFortran(hostResult)); } else { - res = func(host::CastFortranToHost(x)...); - hostFPE.CheckAndRestoreFloatingPointEnvironment(context); - return host::CastHostToFortran(res); + hostResult = + func(host::CastFortranToHost(x)...); + result = host::CastHostToFortran(hostResult); } + if (!hostFPE.hardwareFlagsAreReliable()) { + CheckFloatingPointIssues(hostFPE, result); + } + hostFPE.CheckAndRestoreFloatingPointEnvironment(context); + return result; } else { common::die("Internal error: Host does not supports this function type." "This should not have been called for folding"); } } static constexpr inline auto MakeScalarCallable() { return &scalarCallable; } + + static void CheckFloatingPointIssues( + host::HostFloatingPointEnvironment &hostFPE, const Scalar &x) { + if constexpr (TR::category == TypeCategory::Complex || + TR::category == TypeCategory::Real) { + if (x.IsNotANumber()) { + hostFPE.SetFlag(RealFlag::InvalidArgument); + } else if (x.IsInfinite()) { + hostFPE.SetFlag(RealFlag::Overflow); + } + } + } }; template diff --git a/flang/test/evaluate/folding04.f90 b/flang/test/evaluate/folding04.f90 index 9ca5503..4bd2961 100644 --- a/flang/test/evaluate/folding04.f90 +++ b/flang/test/evaluate/folding04.f90 @@ -30,26 +30,23 @@ module real_tests !WARN: division by zero on division real(4), parameter :: r4_ninf = -1._4/0._4 - !WARN: invalid argument on folding function with host runtime + !WARN: invalid argument on intrinsic function real(4), parameter :: nan_r4_acos1 = acos(1.1) TEST_ISNAN(nan_r4_acos1) - !WARN: invalid argument on folding function with host runtime + !WARN: invalid argument on intrinsic function real(4), parameter :: nan_r4_acos2 = acos(r4_pmax) TEST_ISNAN(nan_r4_acos2) - !WARN: invalid argument on folding function with host runtime + !WARN: invalid argument on intrinsic function real(4), parameter :: nan_r4_acos3 = acos(r4_nmax) TEST_ISNAN(nan_r4_acos3) - !WARN: invalid argument on folding function with host runtime + !WARN: invalid argument on intrinsic function real(4), parameter :: nan_r4_acos4 = acos(r4_ninf) TEST_ISNAN(nan_r4_acos4) - !WARN: invalid argument on folding function with host runtime + !WARN: invalid argument on intrinsic function real(4), parameter :: nan_r4_acos5 = acos(r4_pinf) TEST_ISNAN(nan_r4_acos5) - ! No warnings expected for NaN propagation (quiet) - real(4), parameter :: nan_r4_acos6 = acos(r4_nan) - TEST_ISNAN(nan_r4_acos6) - !WARN: overflow on folding function with host runtime + !WARN: overflow on intrinsic function logical, parameter :: test_exp_overflow = exp(256._4).EQ.r4_pinf end module