6

I'm just playing around with gcc (g++) and the compilerflags -msse and -msse2. I have a little test program which looks like that:

#include <iostream>

int main(int argc, char **argv) {
    float a = 12558.5688;
    float b = 6.5585;

    float result = 0.0;

    result = a * b;

    std::cout << "Result: " << result << std::endl;

    return 0;
}

When I compile it with the following statements:

/usr/local/bin/g++-4.9 -W -msse main.cpp -o testsse

and

/usr/local/bin/g++-4.9 -W -msse2 main.cpp -o testsse2

the output files are binary equal. But I've expected that they are not the same because of the SMID flags.

So my question is, do those complier flags do not have any influence on the binary file? I've tested it on OS X 10.10.3 and Fedora 21.

Thanks for your help.

Kind regards

Fabian

Fabian
  • 492
  • 6
  • 20
  • 1
    -msse and -msse2 are enabled by default on x86_64 processors. If you're building on such a processor, then it would make sense they have no effect. – IanPudney Apr 26 '15 at 07:52
  • 4
    There isn't any math to do here anyway, you're just printing a string and a constant – harold Apr 26 '15 at 07:54
  • 2
    You could look at the generated assembly to see if any of the instructions are used. – Retired Ninja Apr 26 '15 at 08:01
  • So this means I can't disable the -mmse2 flag with the makefile? – Fabian Apr 26 '15 at 08:07
  • Single floating point only needs SSE. Double floating point support came with SSE2. You can disable SSE altogether and use x87 instructions instead if you want. – Z boson Apr 27 '15 at 06:51

2 Answers2

4

In your code very basic floating point maths is involved. And I bet if you turn optimizations on (even -O1) it gets optimized out because those values are constant expressions and so calculable at compile-time.

SSE is used (movss, mulss) because it's the threshold of floating point calculus, if we want. SSE2 has no scope here.
In order to find room for SSE2 you need to include more complex calculus which may or may not exploit some instructions available in SSE2; you could look up what some do, do their equivalent and see if the compiler can take advantage of them.

edmz
  • 8,220
  • 2
  • 26
  • 45
  • 1
    So if I add some more "math" in there, there maybe will a effect? What is about the "deactivation" of sse2 while compiling? – Fabian Apr 26 '15 at 08:09
  • It could be so. Let me ask you: are perhaps you worried about adding that flag, maybe in slower compiling times? – edmz Apr 26 '15 at 08:15
  • No it's just for better understanding of the compiler behavoiour and the compiler flags. It has some experimental charachter and is based on my acually course work. – Fabian Apr 26 '15 at 08:32
  • Giving that flag instructs the compiler to use SSE2 instructions, if the compiler finds place for it; it isn't obligated. It's like as if you had to do a race and had to choose among some sets of cars: the first one is the most basic while the others are more specialized. If the race is more fitted for a specific type of car, you'll go for that one. – edmz Apr 26 '15 at 08:45
  • So if I interpret your answer right, the statment -msse does not avoid the use of -msse2, but it tells the compiler definitly to use the -msse flag. Right? – Fabian Apr 26 '15 at 08:54
  • Not completely. I think you're seeing SSE and SSE2 as one; they aren't. Let's take the example I gave you before: would you choose a Ferrari for grocery shopping? You don't need that: a family car would work. OTOH, would you choose a family car for a race? You could, but a Ferrari *if available* (someone tells you can use it, likewise for using SSE2) would be better. – edmz Apr 26 '15 at 09:03
  • The only thing more complex the OP needs is double floating point which requires SSE2. – Z boson Apr 27 '15 at 06:52
4

The first thing you need to know is that SSE2 and SSE are enabled and used by default for 64-bit code. For 32-bit code the default was x87 instructions.

The second thing you need to know is that double floating requires SSE2 so if you want to see a difference between SSE and SSE2 in your example you should compare double with float.

The third thing you need to know is how to convince your compiler to not optimize your calculations away. One way to do this is to wrap your code in functions like this:

//foo.cpp
float foof(float x, float y) {
    return x*y;
}

double food(double x, double y) {
    return x*y;
}

then g++ -O3 -S foo.cpp shows that foof uses mulss whereas food uses mulsd. If you want to make sure it's getting the right results you can link it in like this

//main.cpp
#include <iostream>   
extern float  foof(float, float);
extern double food(double, double);

int main(void) {
    float af = 12558.5688;
    float bf = 6.5585;
    float resultf = 0.0;

    double ad = af;
    double bd = bf;
    double resultd = 0.0;

    resultf = foof(af, bf);
    resultd = food(ad, bd);

    std::cout << "Resultf: " << resultf << " Resultd: " << resultd << std::endl;
}

Then do g++ -O3 -c foo.cpp and then g++ -O3 main.cpp foo.o.

If you want to disable SSE instructions then use -mfpmath=387 or compile in 32-bit mode with -m32.

Z boson
  • 32,619
  • 11
  • 123
  • 226