forked from OSchip/llvm-project
[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
This commit is contained in:
parent
9114900287
commit
2ebf4b6e4c
|
@ -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(¤tFenv_) != 0) {
|
||||
if (fegetenv(¤tFenv) != 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(¤tFenv_) != 0) {
|
||||
if (fesetenv(¤tFenv) != 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
|
||||
|
|
|
@ -41,7 +41,9 @@ public:
|
|||
|
||||
private:
|
||||
std::fenv_t originalFenv_;
|
||||
std::fenv_t currentFenv_;
|
||||
#if __x86_64__
|
||||
unsigned int originalMxcsr;
|
||||
#endif
|
||||
RealFlags flags_;
|
||||
bool hasSubnormalFlushingHardwareControl_{false};
|
||||
bool hardwareFlagsAreReliable_{true};
|
||||
|
|
|
@ -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(¤tFenv_) != 0) {
|
||||
fenv_t currentFenv;
|
||||
if (fegetenv(¤tFenv) != 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(¤tFenv_) != 0) {
|
||||
if (fesetenv(¤tFenv) != 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 {
|
||||
|
|
|
@ -19,7 +19,9 @@ public:
|
|||
|
||||
private:
|
||||
fenv_t originalFenv_;
|
||||
fenv_t currentFenv_;
|
||||
#if __x86_64__
|
||||
unsigned int originalMxcsr;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FORTRAN_TEST_EVALUATE_FP_TESTING_H_
|
||||
|
|
Loading…
Reference in New Issue