tijagi
tijagi

Reputation: 1244

Why `gcc -Q -march=corei7-avx --help=target` lies?

If we query what -march=native expands to, the result seems as it should be

$ gcc -Q -march=native --help=target | grep -E '^\s+-.*(sse|march)'
  -march=                           corei7-avx
  -mno-sse4                         [disabled]
  -msse                             [enabled]
  -msse2                            [enabled]
  -msse2avx                         [disabled]
  -msse3                            [enabled]
  -msse4                            [enabled]
  -msse4.1                          [enabled]
  -msse4.2                          [enabled]
  -msse4a                           [disabled]
  -msse5                            
  -msseregparm                      [disabled]
  -mssse3                           [enabled]

But if the architecture is specified directly, gcc drops the SSE flags it would enable for native, why?

 $ gcc -Q -march=corei7-avx --help=target | grep -E '^\s+-.*sse'
  -mno-sse4                         [enabled]
  -msse                             [disabled]
  -msse2                            [disabled]
  -msse2avx                         [disabled]
  -msse3                            [disabled]
  -msse4                            [disabled]
  -msse4.1                          [disabled]
  -msse4.2                          [disabled]
  -msse4a                           [disabled]
  -msse5                            
  -msseregparm                      [disabled]
  -mssse3                           [disabled]

Compilation with -march=corei7-avx, however, shows, that they’ll be enabled.

$ echo | gcc -march=corei7-avx -dM -E - | grep -i sse
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE2_MATH__ 1
#define __SSE_MATH__ 1
#define __SSE2__ 1
#define __SSSE3__ 1
#define __SSE__ 1
#define __SSE3__ 1

Upvotes: 6

Views: 1521

Answers (2)

Avraham
Avraham

Reputation: 1719

This is a known bug in GCC (39851); it has been open since GCC 4.5 in 2009.

Upvotes: 3

rodrigo
rodrigo

Reputation: 98446

I'm guessing a bit but anyway, this is too long for a commentary...

Take a look at the output of this command:

$ echo | gcc -march=native -v -x c -c -

And this other:

$ echo | gcc -march=corei7-avx -v -x c -c -

The interesting part is the call to the cc1 binary. In the -march=native case it is replaced by all the target options, not just the equivalent -march one. I have a sandybridge, so in my machine it gives:

.../cc1 -march=sandybridge -mmmx -mno-3dnow -msse -msse2 -msse3 -mssse3 \
        -mno-sse4a -mcx16 -msahf -mno-movbe -mno-aes -mno-sha -mpclmul \
        -mpopcnt -mno-abm -mno-lwp -mno-fma -mno-fma4 -mno-xop ...

Whereas when you add the -march=corei7-avx or (-march=sandybridge in my case) there is none of those specific architecture options.

Now my conclusion:

The output of -Q --help=target tell whether the given compiler options are set, not if feature is actually enabled or not. As is happens, some of these features can be enabled or disabled in different ways.

For example, SSE can be enabled with -msse, and also with -march=corei7-avx or -march=sandybridge. But although specifying -march=corei7-avx enables SSE, it does not set the -msse options per se.

On the other hand -march=native sets a lot of options, not only the actual -march but also any other relevant option that can be fetched from the runtime system, such as cache sizes.

The proper way to check if a specific feature is on or off is, as you already noticed, checking the predefined defines.

Upvotes: 3

Related Questions