7

How can I check in code whether SSE/SSE2 is enabled or not by the Visual Studio compiler?

I have tried #ifdef __SSE__ but it didn't work.

plasmacel
  • 8,183
  • 7
  • 53
  • 101
user2202420
  • 159
  • 1
  • 2
  • 9

4 Answers4

9

Some additional information on _M_IX86_FP.

_M_IX86_FP is only defined for 32-bit code. 64-bit x86 code has at least SSE2. You can use _M_AMD64 or _M_X64 to determine if the code is 64-bit.

#ifdef __AVX2__
//AVX2
#elif defined ( __AVX__ )
//AVX
#elif (defined(_M_AMD64) || defined(_M_X64))
//SSE2 x64
#elif _M_IX86_FP == 2
//SSE2 x32
#elif _M_IX86_FP == 1
//SSE x32
#else
//nothing
#endif
Z boson
  • 32,619
  • 11
  • 123
  • 226
5

From the documentation:

_M_IX86_FP

Expands to a value indicating which /arch compiler option was used:

  • 0 if /arch:IA32 was used.
  • 1 if /arch:SSE was used.
  • 2 if /arch:SSE2 was used. This value is the default if /arch was not specified.

I don't see any mention of _SSE_.

Community
  • 1
  • 1
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
5

The relevant preprocessor macros have two underscores at each end:

#ifdef __SSE__

#ifdef __SSE2__

#ifdef __SSE3__

#ifdef __SSE4_1__

#ifdef __AVX__

...etc...

UPDATE: apparently the above macros are not automatically pre-defined for you when using Visual Studio (even though they are in every other x86 compiler that I have ever used), so you may need to define them yourself if you want portability with gcc, clang, ICC, et al...

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 3
    According to their documentation (http://msdn.microsoft.com/en-us/library/b0084kay.aspx), Visual Studio doesn’t set the `__SSEn__` macros (but they do set `__AVX__` and `__AVX2__`). – Stephen Canon May 22 '14 at 15:27
  • 3
    Typical, I suppose - everybody else defines the `__SSEn__` macros, but not Microsoft. – Paul R May 22 '14 at 15:39
2

This is a late answer, but on MSDN you can find an article about __cpuid and __cpuidex. I redid the class into a function and it checks the support of MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1. https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=vs-2019

[[nodiscard]] bool CheckSimdSupport() noexcept
{
    std::array<int, 4> cpui;
    int nIds_{};
    std::bitset<32> f_1_ECX_{};
    std::bitset<32> f_1_EDX_{};
    std::vector<std::array<int, 4>> data_;

    __cpuid(cpui.data(), 0);
    nIds_ = cpui[0];

    for (int i = 0; i <= 1; ++i)
    {
        __cpuid(cpui.data(), i);
        data_.push_back(cpui);
    }

    if (nIds_ >= 1)
    {
        f_1_ECX_ = data_[1][2];
        f_1_EDX_ = data_[1][3];
    }
    // f_1_ECX_[0] - SSE3
    // f_1_ECX_[9] - SSSE3
    // f_1_ECX_[19] - SSE4.1
    // f_1_EDX_[23] - MMX
    // f_1_EDX_[25] - SSE
    // f_1_EDX_[26] - SSE2
    return f_1_ECX_[0] && f_1_ECX_[9] && f_1_ECX_[19] && f_1_EDX_[23] && f_1_EDX_[25] && f_1_EDX_[26];
}
qymb
  • 21
  • 1
  • 2
  • That checks at runtime to find out what the target CPU supports. It doesn't tell you what baseline level was enabled with compiler options for the compiler to emit on its own. (Both things are potentially useful for different purposes / use-cases.) – Peter Cordes Aug 21 '19 at 17:30
  • This kind of thing *might* be what the OP actually had in mind; "enabled on the target" is a plausible interpretation of the wording, different from how the other answers interpret it. MSVC lets you use intrinsics for instruction sets you haven't told the compiler it can use, and it doesn't have a `gcc -O3 -march=native` equivalent AFAIK that actually detects the build hosts CPU at compile time. – Peter Cordes Aug 21 '19 at 18:40