1 #include "fp-testing.h"
2 #include "llvm/Support/Errno.h"
10 using Fortran::common::RoundingMode
;
11 using Fortran::evaluate::RealFlag
;
13 ScopedHostFloatingPointEnvironment::ScopedHostFloatingPointEnvironment(
15 bool treatSubnormalOperandsAsZero
, bool flushSubnormalResultsToZero
21 if (feholdexcept(&originalFenv_
) != 0) {
22 std::fprintf(stderr
, "feholdexcept() failed: %s\n",
23 llvm::sys::StrError(errno
).c_str());
27 if (fegetenv(¤tFenv
) != 0) {
29 stderr
, "fegetenv() failed: %s\n", llvm::sys::StrError(errno
).c_str());
34 originalMxcsr
= _mm_getcsr();
35 unsigned int currentMxcsr
{originalMxcsr
};
36 if (treatSubnormalOperandsAsZero
) {
37 currentMxcsr
|= 0x0040;
39 currentMxcsr
&= ~0x0040;
41 if (flushSubnormalResultsToZero
) {
42 currentMxcsr
|= 0x8000;
44 currentMxcsr
&= ~0x8000;
50 if (fesetenv(¤tFenv
) != 0) {
52 stderr
, "fesetenv() failed: %s\n", llvm::sys::StrError(errno
).c_str());
56 _mm_setcsr(currentMxcsr
);
60 ScopedHostFloatingPointEnvironment::~ScopedHostFloatingPointEnvironment() {
62 if (fesetenv(&originalFenv_
) != 0) {
64 stderr
, "fesetenv() failed: %s\n", llvm::sys::StrError(errno
).c_str());
68 _mm_setcsr(originalMxcsr
);
72 void ScopedHostFloatingPointEnvironment::ClearFlags() const {
73 feclearexcept(FE_ALL_EXCEPT
);
76 RealFlags
ScopedHostFloatingPointEnvironment::CurrentFlags() {
77 int exceptions
= fetestexcept(FE_ALL_EXCEPT
);
79 if (exceptions
& FE_INVALID
) {
80 flags
.set(RealFlag::InvalidArgument
);
82 if (exceptions
& FE_DIVBYZERO
) {
83 flags
.set(RealFlag::DivideByZero
);
85 if (exceptions
& FE_OVERFLOW
) {
86 flags
.set(RealFlag::Overflow
);
88 if (exceptions
& FE_UNDERFLOW
) {
89 flags
.set(RealFlag::Underflow
);
91 if (exceptions
& FE_INEXACT
) {
92 flags
.set(RealFlag::Inexact
);
97 void ScopedHostFloatingPointEnvironment::SetRounding(Rounding rounding
) {
98 switch (rounding
.mode
) {
99 case RoundingMode::TiesToEven
:
100 fesetround(FE_TONEAREST
);
102 case RoundingMode::ToZero
:
103 fesetround(FE_TOWARDZERO
);
105 case RoundingMode::Up
:
106 fesetround(FE_UPWARD
);
108 case RoundingMode::Down
:
109 fesetround(FE_DOWNWARD
);
111 case RoundingMode::TiesAwayFromZero
:
112 std::fprintf(stderr
, "SetRounding: TiesAwayFromZero not available");