brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · 56335f1 Raw
125 lines · cpp
1//===-- lib/Testing/fp-testing.cpp ------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang/Testing/fp-testing.h"10#include "llvm/Support/Errno.h"11#include <cstdio>12#include <cstdlib>13#include <cstring>14#if __x86_64__ || _M_X6415#include <xmmintrin.h>16#endif17 18using Fortran::common::RealFlag;19using Fortran::common::RoundingMode;20 21ScopedHostFloatingPointEnvironment::ScopedHostFloatingPointEnvironment(22#if __x86_64__ || _M_X6423    bool treatSubnormalOperandsAsZero, bool flushSubnormalResultsToZero24#else25    bool, bool26#endif27) {28  errno = 0;29  if (feholdexcept(&originalFenv_) != 0) {30    std::fprintf(stderr, "feholdexcept() failed: %s\n",31        llvm::sys::StrError(errno).c_str());32    std::abort();33  }34  fenv_t currentFenv;35  if (fegetenv(&currentFenv) != 0) {36    std::fprintf(37        stderr, "fegetenv() failed: %s\n", llvm::sys::StrError(errno).c_str());38    std::abort();39  }40 41#if __x86_64__ || _M_X6442  originalMxcsr = _mm_getcsr();43  unsigned int currentMxcsr{originalMxcsr};44  if (treatSubnormalOperandsAsZero) {45    currentMxcsr |= 0x0040;46  } else {47    currentMxcsr &= ~0x0040;48  }49  if (flushSubnormalResultsToZero) {50    currentMxcsr |= 0x8000;51  } else {52    currentMxcsr &= ~0x8000;53  }54#else55  // TODO others56#endif57  errno = 0;58  if (fesetenv(&currentFenv) != 0) {59    std::fprintf(60        stderr, "fesetenv() failed: %s\n", llvm::sys::StrError(errno).c_str());61    std::abort();62  }63#if __x86_64__64  _mm_setcsr(currentMxcsr);65#endif66}67 68ScopedHostFloatingPointEnvironment::~ScopedHostFloatingPointEnvironment() {69  errno = 0;70  if (fesetenv(&originalFenv_) != 0) {71    std::fprintf(72        stderr, "fesetenv() failed: %s\n", llvm::sys::StrError(errno).c_str());73    std::abort();74  }75#if __x86_64__ || _M_X6476  _mm_setcsr(originalMxcsr);77#endif78}79 80void ScopedHostFloatingPointEnvironment::ClearFlags() const {81  feclearexcept(FE_ALL_EXCEPT);82}83 84RealFlags ScopedHostFloatingPointEnvironment::CurrentFlags() {85  int exceptions = fetestexcept(FE_ALL_EXCEPT);86  RealFlags flags;87  if (exceptions & FE_INVALID) {88    flags.set(RealFlag::InvalidArgument);89  }90  if (exceptions & FE_DIVBYZERO) {91    flags.set(RealFlag::DivideByZero);92  }93  if (exceptions & FE_OVERFLOW) {94    flags.set(RealFlag::Overflow);95  }96  if (exceptions & FE_UNDERFLOW) {97    flags.set(RealFlag::Underflow);98  }99  if (exceptions & FE_INEXACT) {100    flags.set(RealFlag::Inexact);101  }102  return flags;103}104 105void ScopedHostFloatingPointEnvironment::SetRounding(Rounding rounding) {106  switch (rounding.mode) {107  case RoundingMode::TiesToEven:108    fesetround(FE_TONEAREST);109    break;110  case RoundingMode::ToZero:111    fesetround(FE_TOWARDZERO);112    break;113  case RoundingMode::Up:114    fesetround(FE_UPWARD);115    break;116  case RoundingMode::Down:117    fesetround(FE_DOWNWARD);118    break;119  case RoundingMode::TiesAwayFromZero:120    std::fprintf(stderr, "SetRounding: TiesAwayFromZero not available");121    std::abort();122    break;123  }124}125