How to disable fma3 instructions in gcc

967 views Asked by At

I need to disable FMA3 instructions (for backward compatibility issue) for the 64bit system. I'v used _set_FMA3_enable(0) in my windows environment. And what option (or macro) I need to use to disable FMA3 in gcc?

For example.

#include <iostream>
#include <iomanip>
#include <math.h>
#include <limits>

union value
{
    double real;
    long long unsigned integer;
};

int main()
{
#if defined (_WIN64)
    _set_FMA3_enable(0);
#endif

    value x;
    x.integer = 4602754097807755994;
    value y;
    y.real = sin(x.real);
    
    std::cout << std::setprecision(17) << y.real << std::endl;
    std::cout << y.integer << std::endl;
}

On Visual C++ it runs to 0.48674319998526994 4602440005894221058 with _set_FMA3_enable(0). And 0.48674319998526999 4602440005894221059 without it (or with `_set_FMA3_enable(1)).'

I run this code in gcc environment with g++ -g0 -march=x86-64 -O2 -mtune=generic -msse3 -mno-fma -DNDEBUG main.cpp and always get 0.48674319998526999 4602440005894221059.

How can I reproduce _set_FMA3_enable(0) results with gcc?

Visual Studio 16.7.4. gcc version 9.3.0 (with wsl)

1

There are 1 answers

0
eerorika On

How to disable fma3 instructions in gcc

Generation of FMA3 instructions can be disabled with -mno-fma option. -ffp-contract=off is another option which should also disable contraction of separate multiply and add operations into FMA.

How can I reproduce [visual studio] results with gcc?

Apparently, not by disabling FMA instructions. FMA are not the only thing that influence the accuracy of floating point operations.

You could try not relying on the standard library for sin and instead use the same implementation on both systems. You could also set rounding mode explicitly so that you don't rely on system defaults. If you do, then you should use -frounding-math as well.

It would be simpler if you can instead not rely on getting exactly same results.


P.S. The behaviour of the shown program is undefined in C++ because of read form inactive union member.