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__ && defined(_MSC_VER) +#include +#endif namespace Fortran::evaluate::host { using namespace Fortran::parser::literals; @@ -30,6 +33,16 @@ } #if __x86_64__ hasSubnormalFlushingHardwareControl_ = true; +#ifdef _MSC_VER + unsigned int new_mxcsr{_mm_getcsr()}; + if (context.flushSubnormalsToZero()) { + new_mxcsr |= 0x8000; + new_mxcsr |= 0x0040; + } else { + new_mxcsr &= ~0x8000; + new_mxcsr &= ~0x0040; + } +#else if (context.flushSubnormalsToZero()) { currentFenv_.__mxcsr |= 0x8000; // result currentFenv_.__mxcsr |= 0x0040; // operands @@ -37,6 +50,7 @@ currentFenv_.__mxcsr &= ~0x8000; // result currentFenv_.__mxcsr &= ~0x0040; // operands } +#endif #elif defined(__aarch64__) #if defined(__GNU_LIBRARY__) hasSubnormalFlushingHardwareControl_ = true; @@ -75,6 +89,10 @@ llvm::sys::StrError(errno).c_str()); return; } +#if __x86_64__ && defined(_MSC_VER) + _mm_setcsr(new_mxcsr); +#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; @@ -26,6 +29,19 @@ std::abort(); } #if __x86_64__ +#ifdef _MSC_VER + unsigned int new_mxcsr{_mm_getcsr()}; + if (treatSubnormalOperandsAsZero) { + new_mxcsr |= 0x0040; + } else { + new_mxcsr &= ~0x0040; + } + if (flushSubnormalResultsToZero) { + new_mxcsr |= 0x8000; + } else { + new_mxcsr &= ~0x8000; + } +#else if (treatSubnormalOperandsAsZero) { currentFenv_.__mxcsr |= 0x0040; } else { @@ -36,6 +52,7 @@ } else { currentFenv_.__mxcsr &= ~0x8000; } +#endif #else // TODO others #endif @@ -45,6 +62,9 @@ stderr, "fesetenv() failed: %s\n", llvm::sys::StrError(errno).c_str()); std::abort(); } +#if __x86_64__ && defined(_MSC_VER) + _mm_setcsr(new_mxcsr); +#endif } ScopedHostFloatingPointEnvironment::~ScopedHostFloatingPointEnvironment() {