Skip to content

Commit

Permalink
Added CPUID check
Browse files Browse the repository at this point in the history
  • Loading branch information
sirzooro committed Nov 25, 2017
1 parent bbcb88e commit 390ac79
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 9 deletions.
2 changes: 0 additions & 2 deletions RakeDiagSearch/RakeDiagSearch/Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,6 @@ inline void Generator::StartImpl()
int cellValue; // New value for the cell
int oldCellValue; // Old value from the cell

int stop = 0; // Flag of finishing the computing

// Create constant copies of used fields to speedup calculations
const int cellsInPath = this->cellsInPath;
const int keyValue = this->keyValue;
Expand Down
102 changes: 95 additions & 7 deletions RakeDiagSearch/RakeDiagSearch/main.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# include <iostream>
# include <fstream>
# include <string>
# include <sys/stat.h>
# include "boinc_api.h"

# include "MovePairSearch.h"
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
#include "boinc_api.h"
#include "MovePairSearch.h"
#if defined(__i386__) || defined (__x86_64__)
#include <cpuid.h>
#include <stdio.h>
#endif

using namespace std;

Expand Down Expand Up @@ -126,3 +129,88 @@ int main(int argumentsCount, char* argumentsValues[])
// will be shown).
return 0;
}

// Do not check x86 CPU features if SSE2 is not required. Very old CPUs may not support CPUID.
// Code below uses C stdio because C++ iostreams are not initialized yet and app would crash.
// This function is called before main() starts.
#if (defined(__i386__) || defined (__x86_64__)) && defined(__SSE2__)
__attribute__((constructor(101), target("no-sse")))
void CheckCpuid()
{
unsigned int a, b, c, d;

if (!__get_cpuid(1, &a, &b, &c, &d))
{
fprintf(stderr, "CPUID instruction is not supported by your CPU!\n");
exit(1);
}

if (0 == (d & bit_SSE2))
{
fprintf(stderr, "SSE2 instructions are not supported by your CPU!\n");
exit(1);
}

#ifdef __AVX__
if (0 == (c & bit_AVX))
{
fprintf(stderr, "AVX instructions are not supported by your CPU!\n");
exit(1);
}

// AVX also needs OS support, check for it
if (0 == (c & bit_OSXSAVE))
{
fprintf(stderr, "OSXSAVE instructions are not supported by your CPU!\n");
exit(1);
}

unsigned int eax, edx;
unsigned int ecx = 0; // _XCR_XFEATURE_ENABLED_MASK
__asm__ ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (ecx));
if (0x6 != (eax & 0x6)) // XSTATE_SSE | XSTATE_YMM
{
fprintf(stderr, "AVX instructions are not supported by your OS!\n");
exit(1);
}
#endif

#ifdef __AVX2__
if (!__get_cpuid(7, &a, &b, &c, &d)) {
fprintf(stderr, "Extended CPUID 0x7 instruction is not supported by your CPU!\n");
exit(1);
}

if (0 == (b & bit_AVX2))
{
fprintf(stderr, "AVX2 instructions are not supported by your CPU!\n");
exit(1);
}
#endif

#ifdef __AVX512F__
// During comppilation following AVX512 instruction sets are enabled: F, CD, VL, BW, DQ
// Code directly uses F and VL. Compiler may emit instruction from other ones, so check them all

// We need data loaded during AVX and AVX2 checks, make sure we have it
#if !defined(__AVX__) || !defined(__AVX2__)
#error AVX or AVX2 is not enabled!
#endif

const unsigned int avx512bits = bit_AVX512F | bit_AVX512DQ | bit_AVX512CD | bit_AVX512BW | bit_AVX512VL;

if (avx512bits != (b & avx512bits))
{
fprintf(stderr, "AVX512 instructions are not supported by your CPU!\n");
exit(1);
}

// AVX512 also needs OS support, check for it
if (0xe6 != (eax & 0xe6)) // XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM
{
fprintf(stderr, "AVX512 instructions are not supported by your OS!\n");
exit(1);
}
#endif
}
#endif

0 comments on commit 390ac79

Please sign in to comment.