Detect the availability of SSE/SSE2 instruction set in Visual Studio
Asked Answered
R

4

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.

Reedreedbird answered 1/9, 2013 at 23:38 Comment(0)
S
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_.

Sturges answered 1/9, 2013 at 23:40 Comment(0)
T
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
Thyself answered 2/9, 2013 at 10:2 Comment(0)
S
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_.

Sturges answered 1/9, 2013 at 23:40 Comment(0)
P
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...

President answered 2/9, 2013 at 5:33 Comment(2)
According to their documentation (msdn.microsoft.com/en-us/library/b0084kay.aspx), Visual Studio doesn’t set the __SSEn__ macros (but they do set __AVX__ and __AVX2__).Farber
Typical, I suppose - everybody else defines the __SSEn__ macros, but not Microsoft.President
T
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];
}
Thirion answered 21/8, 2019 at 16:10 Comment(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.)Nodical
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.Nodical

© 2022 - 2024 — McMap. All rights reserved.