Skip to content

cleanup of FPE on macOS #338

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 75 additions & 15 deletions src/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,48 @@ void resetSignalHandling()
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int getDefaultFloatingPointExceptions()
{
return ( FE_DIVBYZERO | FE_OVERFLOW | FE_INVALID );
return ( FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID );
}

unsigned long long int translateFloatingPointException( unsigned long long int const exception )
{
unsigned long long int result = 0;
#if defined(__APPLE__) && defined(__MACH__) // if apple
if( exception & FE_INEXACT )
{
result |= __fpcr_trap_inexact;
}
if( exception & FE_UNDERFLOW )
{
result |= __fpcr_trap_underflow;
}
if( exception & FE_OVERFLOW )
{
result |= __fpcr_trap_overflow;
}
if( exception & FE_DIVBYZERO )
{
result |= __fpcr_trap_divbyzero;
}
if( exception & FE_INVALID )
{
result |= __fpcr_trap_invalid;
}

#if defined(__arm__) || defined(__arm64__) // if apple arm
#elif defined(__x86_64__) // if apple x86_64
#else // if apple but not arm or x86_64
std::cerr<< "LvArray::system::translateFloatingPointException() not implemented for this architecture" << std::endl;
#endif


#else // if not apple
#if defined(__x86_64__)
result = exception;
#endif
#endif

return result;
}

#if defined(__APPLE__) && defined(__MACH__)&& !defined(__x86_64__)
Expand All @@ -542,10 +583,8 @@ fpe_signal_handler( int sig, siginfo_t *sip, void *scp )

int fe_code = sip->si_code;

printf( "In signal handler : " );

if( fe_code == ILL_ILLTRP )
printf( "Illegal trap detected\n" );
printf( "Illegal trap detected. If you see this you have a FPE, but Apple Silicon doesn't provide data on which FPE has occured.\n" );
else
printf( "Code detected : %d\n", fe_code );

Expand All @@ -559,19 +598,22 @@ int enableFloatingPointExceptions( int const exceptions )
#if defined(__APPLE__) && defined(__MACH__)
#if !defined(__x86_64__)

LVARRAY_UNUSED_VARIABLE( exceptions );
unsigned long long int const exceptionMasks = translateFloatingPointException( exceptions );

fenv_t env;
fegetenv( &env );

env.__fpcr = env.__fpcr | __fpcr_trap_invalid;
// std::cout<<std::hex<<"env.__fpcr = " << env.__fpcr << std::endl;
env.__fpcr = env.__fpcr | exceptionMasks ;
// std::cout<<std::hex<<"env.__fpcr = " << env.__fpcr << std::endl;

fesetenv( &env );

struct sigaction act;
act.sa_sigaction = fpe_signal_handler;
sigemptyset ( &act.sa_mask );
act.sa_flags = SA_SIGINFO;
sigaction( SIGILL, &act, NULL );
sigaction( SIGFPE, &act, NULL );
return 0;
#else
// Public domain polyfill for feenableexcept on OS X
Expand Down Expand Up @@ -632,23 +674,41 @@ int disableFloatingPointExceptions( int const exceptions )
#endif
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setFPE()

void setFlushToZero()
{
#if defined(__APPLE__) && defined(__MACH__)
#if !defined(__x86_64__)

#else
#if defined(__APPLE__) && defined(__MACH__) // if apple

#if defined(__arm__) || defined(__arm64__) // if apple arm
fenv_t env;
fegetenv( &env );
env.__fpcr = env.__fpcr | __fpcr_flush_to_zero ;
// std::cout<<std::hex<<"env.__fpcr = " << env.__fpcr << std::endl;
// std::cout<<std::hex<<"_FE_DFL_DISABLE_DENORMS_ENV.__fpcr = " << _FE_DFL_DISABLE_DENORMS_ENV.__fpcr << std::endl;
fesetenv( &env );
#elif defined(__x86_64__) // if apple x86_64
fesetenv( FE_DFL_DISABLE_SSE_DENORMS_ENV );
#else // if apple but not arm or x86_64
std::cerr<< "LvArray::system::setFlushToZero() not implemented for this architecture" << std::endl;
#endif
#elif defined(__x86_64__)

// if not apple
#else
#if defined(__x86_64__)
_MM_SET_FLUSH_ZERO_MODE( _MM_FLUSH_ZERO_ON );
_MM_SET_DENORMALS_ZERO_MODE( _MM_DENORMALS_ZERO_ON );
#endif
#if defined(__x86_64__)
enableFloatingPointExceptions( getDefaultFloatingPointExceptions() );

#endif
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setFPE()
{
enableFloatingPointExceptions( getDefaultFloatingPointExceptions() );
setFlushToZero();
}

} // namespace system
} // namespace LvArray
3 changes: 3 additions & 0 deletions src/system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ int disableFloatingPointExceptions( int const exceptions = getDefaultFloatingPoi
*/
void setFPE();


void setFlushToZero();

/**
* @class FloatingPointExceptionGuard
* @brief Changes the floating point environment and reverts it when destoyed.
Expand Down
4 changes: 0 additions & 4 deletions unitTests/testFloatingPointExceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
#include <cmath>
#include <float.h>


#if defined(__x86_64__)

using namespace testFloatingPointExceptionsHelpers;

const char IGNORE_OUTPUT[] = ".*";
Expand Down Expand Up @@ -74,7 +71,6 @@ TEST( TestFloatingPointEnvironment, FloatingPointExceptionGuard )
} // namespace testing
} // namespace LvArray

#endif

// This is the default gtest main method. It is included for ease of debugging.
int main( int argc, char * * argv )
Expand Down