[flang-commits] [flang] 2ebf4b6 - [flang] Fix setting mxcsr on MSVC

Isuru Fernando via flang-commits flang-commits at lists.llvm.org
Wed Jul 8 05:25:31 PDT 2020


Author: Isuru Fernando
Date: 2020-07-08T07:25:25-05:00
New Revision: 2ebf4b6e4c35c93c97da9ed14db7b38757c0d7f9

URL: https://github.com/llvm/llvm-project/commit/2ebf4b6e4c35c93c97da9ed14db7b38757c0d7f9
DIFF: https://github.com/llvm/llvm-project/commit/2ebf4b6e4c35c93c97da9ed14db7b38757c0d7f9.diff

LOG: [flang] Fix setting mxcsr on MSVC

Reviewers: sscalpone, jdoerfert, #flang, DavidTruby, jeanPerier

Reviewed By: jeanPerier

Subscribers: richard.barton.arm, jeanPerier, ro, llvm-commits

Tags: #llvm, #flang

Differential Revision: https://reviews.llvm.org/D77815

Added: 
    

Modified: 
    flang/lib/Evaluate/host.cpp
    flang/lib/Evaluate/host.h
    flang/unittests/Evaluate/fp-testing.cpp
    flang/unittests/Evaluate/fp-testing.h

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/host.cpp b/flang/lib/Evaluate/host.cpp
index ea831274b942..c9aa5c4bbce3 100644
--- 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 <cfenv>
+#if __x86_64__
+#include <xmmintrin.h>
+#endif
 
 namespace Fortran::evaluate::host {
 using namespace Fortran::parser::literals;
@@ -18,39 +21,42 @@ using namespace Fortran::parser::literals;
 void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment(
     FoldingContext &context) {
   errno = 0;
+  std::fenv_t currentFenv;
   if (feholdexcept(&originalFenv_) != 0) {
     common::die("Folding with host runtime: feholdexcept() failed: %s",
         llvm::sys::StrError(errno).c_str());
     return;
   }
-  if (fegetenv(&currentFenv_) != 0) {
+  if (fegetenv(&currentFenv) != 0) {
     common::die("Folding with host runtime: fegetenv() failed: %s",
         llvm::sys::StrError(errno).c_str());
     return;
   }
 #if __x86_64__
   hasSubnormalFlushingHardwareControl_ = true;
+  originalMxcsr = _mm_getcsr();
+  unsigned int currentMxcsr{originalMxcsr};
   if (context.flushSubnormalsToZero()) {
-    currentFenv_.__mxcsr |= 0x8000; // result
-    currentFenv_.__mxcsr |= 0x0040; // operands
+    currentMxcsr |= 0x8000;
+    currentMxcsr |= 0x0040;
   } else {
-    currentFenv_.__mxcsr &= ~0x8000; // result
-    currentFenv_.__mxcsr &= ~0x0040; // operands
+    currentMxcsr &= ~0x8000;
+    currentMxcsr &= ~0x0040;
   }
 #elif defined(__aarch64__)
 #if defined(__GNU_LIBRARY__)
   hasSubnormalFlushingHardwareControl_ = true;
   if (context.flushSubnormalsToZero()) {
-    currentFenv_.__fpcr |= (1U << 24); // control register
+    currentFenv.__fpcr |= (1U << 24); // control register
   } else {
-    currentFenv_.__fpcr &= ~(1U << 24); // control register
+    currentFenv.__fpcr &= ~(1U << 24); // control register
   }
 #elif defined(__BIONIC__)
   hasSubnormalFlushingHardwareControl_ = true;
   if (context.flushSubnormalsToZero()) {
-    currentFenv_.__control |= (1U << 24); // control register
+    currentFenv.__control |= (1U << 24); // control register
   } else {
-    currentFenv_.__control &= ~(1U << 24); // control register
+    currentFenv.__control &= ~(1U << 24); // control register
   }
 #else
   // If F18 is built with other C libraries on AArch64, software flushing will
@@ -70,11 +76,15 @@ void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment(
   hardwareFlagsAreReliable_ = false;
 #endif
   errno = 0;
-  if (fesetenv(&currentFenv_) != 0) {
+  if (fesetenv(&currentFenv) != 0) {
     common::die("Folding with host runtime: fesetenv() failed: %s",
         llvm::sys::StrError(errno).c_str());
     return;
   }
+#if __x86_64__
+  _mm_setcsr(currentMxcsr);
+#endif
+
   switch (context.rounding().mode) {
   case common::RoundingMode::TiesToEven:
     fesetround(FE_TONEAREST);
@@ -141,6 +151,10 @@ void HostFloatingPointEnvironment::CheckAndRestoreFloatingPointEnvironment(
         "Folding with host runtime: fesetenv() failed while restoring fenv: %s",
         llvm::sys::StrError(errno).c_str());
   }
+#if __x86_64__
+  _mm_setcsr(originalMxcsr);
+#endif
+
   errno = 0;
 }
 } // namespace Fortran::evaluate::host

diff  --git a/flang/lib/Evaluate/host.h b/flang/lib/Evaluate/host.h
index 20355ae3147a..2fac0424f17c 100644
--- a/flang/lib/Evaluate/host.h
+++ b/flang/lib/Evaluate/host.h
@@ -41,7 +41,9 @@ class HostFloatingPointEnvironment {
 
 private:
   std::fenv_t originalFenv_;
-  std::fenv_t currentFenv_;
+#if __x86_64__
+  unsigned int originalMxcsr;
+#endif
   RealFlags flags_;
   bool hasSubnormalFlushingHardwareControl_{false};
   bool hardwareFlagsAreReliable_{true};

diff  --git a/flang/unittests/Evaluate/fp-testing.cpp b/flang/unittests/Evaluate/fp-testing.cpp
index 66ab7b274a82..94d8d5086d00 100644
--- a/flang/unittests/Evaluate/fp-testing.cpp
+++ b/flang/unittests/Evaluate/fp-testing.cpp
@@ -3,6 +3,9 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
+#if __x86_64__
+#include <xmmintrin.h>
+#endif
 
 using Fortran::common::RoundingMode;
 using Fortran::evaluate::RealFlag;
@@ -20,31 +23,38 @@ ScopedHostFloatingPointEnvironment::ScopedHostFloatingPointEnvironment(
         llvm::sys::StrError(errno).c_str());
     std::abort();
   }
-  if (fegetenv(&currentFenv_) != 0) {
+  fenv_t currentFenv;
+  if (fegetenv(&currentFenv) != 0) {
     std::fprintf(
         stderr, "fegetenv() failed: %s\n", llvm::sys::StrError(errno).c_str());
     std::abort();
   }
+
 #if __x86_64__
+  originalMxcsr = _mm_getcsr();
+  unsigned int currentMxcsr{originalMxcsr};
   if (treatSubnormalOperandsAsZero) {
-    currentFenv_.__mxcsr |= 0x0040;
+    currentMxcsr |= 0x0040;
   } else {
-    currentFenv_.__mxcsr &= ~0x0040;
+    currentMxcsr &= ~0x0040;
   }
   if (flushSubnormalResultsToZero) {
-    currentFenv_.__mxcsr |= 0x8000;
+    currentMxcsr |= 0x8000;
   } else {
-    currentFenv_.__mxcsr &= ~0x8000;
+    currentMxcsr &= ~0x8000;
   }
 #else
   // TODO others
 #endif
   errno = 0;
-  if (fesetenv(&currentFenv_) != 0) {
+  if (fesetenv(&currentFenv) != 0) {
     std::fprintf(
         stderr, "fesetenv() failed: %s\n", llvm::sys::StrError(errno).c_str());
     std::abort();
   }
+#if __x86_64__
+  _mm_setcsr(currentMxcsr);
+#endif
 }
 
 ScopedHostFloatingPointEnvironment::~ScopedHostFloatingPointEnvironment() {
@@ -54,6 +64,9 @@ ScopedHostFloatingPointEnvironment::~ScopedHostFloatingPointEnvironment() {
         stderr, "fesetenv() failed: %s\n", llvm::sys::StrError(errno).c_str());
     std::abort();
   }
+#if __x86_64__
+  _mm_setcsr(originalMxcsr);
+#endif
 }
 
 void ScopedHostFloatingPointEnvironment::ClearFlags() const {

diff  --git a/flang/unittests/Evaluate/fp-testing.h b/flang/unittests/Evaluate/fp-testing.h
index 760e976c4c96..ee06765879b3 100644
--- a/flang/unittests/Evaluate/fp-testing.h
+++ b/flang/unittests/Evaluate/fp-testing.h
@@ -19,7 +19,9 @@ class ScopedHostFloatingPointEnvironment {
 
 private:
   fenv_t originalFenv_;
-  fenv_t currentFenv_;
+#if __x86_64__
+  unsigned int originalMxcsr;
+#endif
 };
 
 #endif // FORTRAN_TEST_EVALUATE_FP_TESTING_H_


        


More information about the flang-commits mailing list