#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;
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
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);
"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
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#if __x86_64__
+#include <xmmintrin.h>
+#endif
using Fortran::common::RoundingMode;
using Fortran::evaluate::RealFlag;
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() {
stderr, "fesetenv() failed: %s\n", llvm::sys::StrError(errno).c_str());
std::abort();
}
+#if __x86_64__
+ _mm_setcsr(originalMxcsr);
+#endif
}
void ScopedHostFloatingPointEnvironment::ClearFlags() const {