diff --git a/flang/lib/Evaluate/host.cpp b/flang/lib/Evaluate/host.cpp --- a/flang/lib/Evaluate/host.cpp +++ b/flang/lib/Evaluate/host.cpp @@ -11,6 +11,9 @@ #include "flang/Common/idioms.h" #include "llvm/Support/Errno.h" #include +#if __x86_64__ +#include +#endif namespace Fortran::evaluate::host { using namespace Fortran::parser::literals; @@ -30,12 +33,13 @@ } #if __x86_64__ hasSubnormalFlushingHardwareControl_ = true; + unsigned int new_mxcsr{_mm_getcsr()}; if (context.flushSubnormalsToZero()) { - currentFenv_.__mxcsr |= 0x8000; // result - currentFenv_.__mxcsr |= 0x0040; // operands + new_mxcsr |= 0x8000; + new_mxcsr |= 0x0040; } else { - currentFenv_.__mxcsr &= ~0x8000; // result - currentFenv_.__mxcsr &= ~0x0040; // operands + new_mxcsr &= ~0x8000; + new_mxcsr &= ~0x0040; } #elif defined(__aarch64__) #if defined(__GNU_LIBRARY__) @@ -69,12 +73,17 @@ // registers. Therefore, fetestexcept should not be used. hardwareFlagsAreReliable_ = false; #endif +#if __x86_64__ + _mm_setcsr(new_mxcsr); +#else errno = 0; if (fesetenv(¤tFenv_) != 0) { common::die("Folding with host runtime: fesetenv() failed: %s", llvm::sys::StrError(errno).c_str()); return; } +#endif + switch (context.rounding().mode) { case common::RoundingMode::TiesToEven: fesetround(FE_TONEAREST); diff --git a/flang/unittests/Evaluate/fp-testing.cpp b/flang/unittests/Evaluate/fp-testing.cpp --- a/flang/unittests/Evaluate/fp-testing.cpp +++ b/flang/unittests/Evaluate/fp-testing.cpp @@ -3,6 +3,9 @@ #include #include #include +#if __x86_64__ && defined(_MSC_VER) +#include +#endif using Fortran::common::RoundingMode; using Fortran::evaluate::RealFlag; @@ -20,31 +23,34 @@ llvm::sys::StrError(errno).c_str()); std::abort(); } - if (fegetenv(¤tFenv_) != 0) { - std::fprintf( - stderr, "fegetenv() failed: %s\n", llvm::sys::StrError(errno).c_str()); - std::abort(); - } + #if __x86_64__ + unsigned int new_mxcsr{_mm_getcsr()}; if (treatSubnormalOperandsAsZero) { - currentFenv_.__mxcsr |= 0x0040; + new_mxcsr |= 0x0040; } else { - currentFenv_.__mxcsr &= ~0x0040; + new_mxcsr &= ~0x0040; } if (flushSubnormalResultsToZero) { - currentFenv_.__mxcsr |= 0x8000; + new_mxcsr |= 0x8000; } else { - currentFenv_.__mxcsr &= ~0x8000; + new_mxcsr &= ~0x8000; } + _mm_setcsr(new_mxcsr); #else + if (fegetenv(¤tFenv_) != 0) { + std::fprintf( + stderr, "fegetenv() failed: %s\n", llvm::sys::StrError(errno).c_str()); + std::abort(); + } // TODO others -#endif errno = 0; if (fesetenv(¤tFenv_) != 0) { std::fprintf( stderr, "fesetenv() failed: %s\n", llvm::sys::StrError(errno).c_str()); std::abort(); } +#endif } ScopedHostFloatingPointEnvironment::~ScopedHostFloatingPointEnvironment() {