Skip to content

Commit cfe57c4

Browse files
committed
Add MSVC build support on windows
1 parent 6a7a01d commit cfe57c4

File tree

5 files changed

+74
-95
lines changed

5 files changed

+74
-95
lines changed

lib/meson.build

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ if cpp.has_argument('-march=haswell')
66
'x86simdsort-avx2.cpp',
77
),
88
include_directories : [src],
9-
cpp_args : ['-march=haswell'],
9+
cpp_args : meson.get_compiler('cpp').get_id() == 'msvc' ? ['/arch:AVX2'] : ['-march=haswell'],
1010
gnu_symbol_visibility : 'inlineshidden',
1111
dependencies: [omp_dep],
1212
)
@@ -18,7 +18,7 @@ if cpp.has_argument('-march=skylake-avx512')
1818
'x86simdsort-skx.cpp',
1919
),
2020
include_directories : [src],
21-
cpp_args : ['-march=skylake-avx512'],
21+
cpp_args : meson.get_compiler('cpp').get_id() == 'msvc' ? ['/arch:AVX512'] : ['-march=skylake-avx512'],
2222
gnu_symbol_visibility : 'inlineshidden',
2323
dependencies: [omp_dep],
2424
)
@@ -30,7 +30,7 @@ if cpp.has_argument('-march=icelake-client')
3030
'x86simdsort-icl.cpp',
3131
),
3232
include_directories : [src],
33-
cpp_args : ['-march=icelake-client'],
33+
cpp_args : meson.get_compiler('cpp').get_id() == 'msvc' ? ['/arch:AVX512'] : ['-march=icelake-client'],
3434
gnu_symbol_visibility : 'inlineshidden',
3535
dependencies: [omp_dep],
3636
)
@@ -42,7 +42,7 @@ if cancompilefp16
4242
'x86simdsort-spr.cpp',
4343
),
4444
include_directories : [src],
45-
cpp_args : ['-march=sapphirerapids'],
45+
cpp_args : meson.get_compiler('cpp').get_id() == 'msvc' ? ['/arch:AVX512'] : ['-march=sapphirerapids'],
4646
gnu_symbol_visibility : 'inlineshidden',
4747
dependencies: [omp_dep],
4848
)

lib/x86simdsort.cpp

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1+
#if defined(_MSC_VER)
2+
# define XSS_ATTRIBUTE_CONSTRUCTOR
3+
#else
4+
# define XSS_ATTRIBUTE_CONSTRUCTOR __attribute__((constructor))
5+
#endif
16
#include "x86simdsort.h"
27
#include "x86simdsort-internal.h"
38
#include "x86simdsort-scalar.h"
9+
#include "x86simdsortcpuid.h"
410
#include <algorithm>
511
#include <iostream>
612
#include <string>
@@ -12,23 +18,23 @@ static int check_cpu_feature_support(std::string_view cpufeature)
1218
if ((cpufeature == "avx512_spr") && (!disable_avx512))
1319
#if defined(__FLT16_MAX__) && !defined(__INTEL_LLVM_COMPILER) \
1420
&& (!defined(__clang_major__) || __clang_major__ >= 18)
15-
return __builtin_cpu_supports("avx512f")
16-
&& __builtin_cpu_supports("avx512fp16")
17-
&& __builtin_cpu_supports("avx512vbmi2");
21+
return xss_cpu_supports("avx512f")
22+
&& xss_cpu_supports("avx512fp16")
23+
&& xss_cpu_supports("avx512vbmi2");
1824
#else
1925
return 0;
2026
#endif
2127
else if ((cpufeature == "avx512_icl") && (!disable_avx512))
22-
return __builtin_cpu_supports("avx512f")
23-
&& __builtin_cpu_supports("avx512vbmi2")
24-
&& __builtin_cpu_supports("avx512bw")
25-
&& __builtin_cpu_supports("avx512vl");
28+
return xss_cpu_supports("avx512f")
29+
&& xss_cpu_supports("avx512vbmi2")
30+
&& xss_cpu_supports("avx512bw")
31+
&& xss_cpu_supports("avx512vl");
2632
else if ((cpufeature == "avx512_skx") && (!disable_avx512))
27-
return __builtin_cpu_supports("avx512f")
28-
&& __builtin_cpu_supports("avx512dq")
29-
&& __builtin_cpu_supports("avx512vl");
33+
return xss_cpu_supports("avx512f")
34+
&& xss_cpu_supports("avx512dq")
35+
&& xss_cpu_supports("avx512vl");
3036
else if (cpufeature == "avx2")
31-
return __builtin_cpu_supports("avx2");
37+
return xss_cpu_supports("avx2");
3238

3339
return 0;
3440
}
@@ -121,11 +127,11 @@ constexpr bool IS_TYPE_FLOAT16()
121127

122128
/* runtime dispatch mechanism */
123129
#define DISPATCH(func, TYPE, ISA) \
124-
DECLARE_INTERNAL_##func(TYPE) static __attribute__((constructor)) void \
130+
DECLARE_INTERNAL_##func(TYPE) static XSS_ATTRIBUTE_CONSTRUCTOR void \
125131
CAT(CAT(resolve_, func), TYPE)(void) \
126132
{ \
127133
CAT(CAT(internal_, func), TYPE) = &xss::scalar::func<TYPE>; \
128-
__builtin_cpu_init(); \
134+
xss_cpu_init(); \
129135
std::string_view preferred_cpu = find_preferred_cpu(ISA); \
130136
if constexpr (dispatch_requested("avx512", ISA)) { \
131137
if (preferred_cpu.find("avx512") != std::string_view::npos) { \
@@ -248,12 +254,12 @@ DISPATCH_ALL(argselect,
248254
}
249255

250256
#define DISPATCH_KV_FUNC(func, TYPE1, TYPE2, ISA) \
251-
static __attribute__((constructor)) void CAT( \
257+
static XSS_ATTRIBUTE_CONSTRUCTOR void CAT( \
252258
CAT(CAT(CAT(resolve_, func), _), TYPE1), TYPE2)(void) \
253259
{ \
254260
CAT(CAT(CAT(CAT(internal_, func), _), TYPE1), TYPE2) \
255261
= &xss::scalar::func<TYPE1, TYPE2>; \
256-
__builtin_cpu_init(); \
262+
xss_cpu_init(); \
257263
std::string_view preferred_cpu = find_preferred_cpu(ISA); \
258264
if constexpr (dispatch_requested("avx512", ISA)) { \
259265
if (preferred_cpu.find("avx512") != std::string_view::npos) { \

lib/x86simdsort.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@
66
#include <functional>
77
#include <numeric>
88

9-
#define XSS_EXPORT_SYMBOL __attribute__((visibility("default")))
10-
#define XSS_HIDE_SYMBOL __attribute__((visibility("hidden")))
9+
#if defined(_MSC_VER)
10+
# define XSS_EXPORT_SYMBOL __declspec(dllexport)
11+
# define XSS_HIDE_SYMBOL
12+
#else
13+
# define XSS_EXPORT_SYMBOL __attribute__((visibility("default")))
14+
# define XSS_HIDE_SYMBOL __attribute__((visibility("hidden")))
15+
#endif
1116
#define UNUSED(x) (void)(x)
1217

1318
namespace x86simdsort {

lib/x86simdsortcpuid.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef X86SIMDSORT_CPUID_H
2+
#define X86SIMDSORT_CPUID_H
3+
4+
#include <intrin.h>
5+
#include <string>
6+
#include <unordered_map>
7+
8+
static std::unordered_map<std::string, bool> xss_cpu_features;
9+
10+
inline void xss_cpu_init() {
11+
int cpuInfo[4] = {0};
12+
// Check AVX2
13+
__cpuid(cpuInfo, 0);
14+
int nIds = cpuInfo[0];
15+
__cpuid(cpuInfo, 1);
16+
bool osxsave = (cpuInfo[2] & (1 << 27)) != 0;
17+
bool avx = (cpuInfo[2] & (1 << 28)) != 0;
18+
__cpuid(cpuInfo, 7);
19+
bool avx2 = (cpuInfo[1] & (1 << 5)) != 0;
20+
bool avx512f = (cpuInfo[1] & (1 << 16)) != 0;
21+
bool avx512dq = (cpuInfo[1] & (1 << 17)) != 0;
22+
bool avx512bw = (cpuInfo[1] & (1 << 30)) != 0;
23+
bool avx512vl = (cpuInfo[1] & (1 << 31)) != 0;
24+
bool avx512vbmi2 = (cpuInfo[2] & (1 << 6)) != 0;
25+
bool avx512fp16 = (cpuInfo[3] & (1 << 23)) != 0;
26+
// Store results
27+
xss_cpu_features["avx2"] = avx2;
28+
xss_cpu_features["avx512f"] = avx512f;
29+
xss_cpu_features["avx512dq"] = avx512dq;
30+
xss_cpu_features["avx512bw"] = avx512bw;
31+
xss_cpu_features["avx512vl"] = avx512vl;
32+
xss_cpu_features["avx512vbmi2"] = avx512vbmi2;
33+
xss_cpu_features["avx512fp16"] = avx512fp16;
34+
}
35+
36+
inline bool xss_cpu_supports(const char* feature) {
37+
auto it = xss_cpu_features.find(feature);
38+
return it != xss_cpu_features.end() && it->second;
39+
}
40+
41+
#endif // X86SIMDSORT_CPUID_H

meson.build

Lines changed: 1 addition & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,6 @@ bench = include_directories('benchmarks')
1010
utils = include_directories('utils')
1111
tests = include_directories('tests')
1212

13-
# Add IPP sort to benchmarks:
14-
benchipp = false
15-
ipplink = []
16-
if get_option('build_ippbench')
17-
benchipp = true
18-
ipplink = ['-lipps', '-lippcore']
19-
endif
20-
21-
# Essentially '-Werror' for the sanitizers; all problems become fatal with this set
22-
if get_option('fatal_sanitizers')
23-
add_project_arguments([ '-fno-sanitize-recover=all' ], language: 'cpp')
24-
endif
25-
26-
# Add google vqsort to benchmarks:
27-
benchvq = false
28-
if get_option('build_vqsortbench')
29-
benchvq = true
30-
endif
31-
32-
# openMP:
33-
omp = []
34-
omp_dep = []
35-
if get_option('use_openmp')
36-
omp = dependency('openmp', required : true)
37-
omp_dep = declare_dependency(dependencies: omp, compile_args: ['-DXSS_USE_OPENMP'])
38-
endif
39-
4013
fp16code = '''#include<immintrin.h>
4114
int main() {
4215
__m512h temp = _mm512_set1_ph(1.0f);
@@ -47,27 +20,13 @@ int main() {
4720
cancompilefp16 = cpp.compiles(fp16code, args:'-march=sapphirerapids')
4821

4922
subdir('lib')
50-
if get_option('lib_type') == 'shared'
51-
libsimdsort = shared_library('x86simdsortcpp',
23+
libsimdsort = shared_library('x86simdsortcpp',
5224
'lib/x86simdsort.cpp',
5325
include_directories : [src, utils, lib],
5426
link_with : [libtargets],
55-
dependencies: [omp_dep],
56-
gnu_symbol_visibility : 'inlineshidden',
5727
install : true,
5828
soversion : 1,
5929
)
60-
else
61-
libsimdsort = static_library('x86simdsortcpp',
62-
'lib/x86simdsort.cpp',
63-
include_directories : [src, utils, lib],
64-
link_with : [libtargets],
65-
dependencies: [omp_dep],
66-
gnu_symbol_visibility : 'inlineshidden',
67-
install : true,
68-
pic: true,
69-
)
70-
endif
7130

7231
pkg_mod = import('pkgconfig')
7332
pkg_mod.generate(libraries : libsimdsort,
@@ -76,38 +35,6 @@ pkg_mod.generate(libraries : libsimdsort,
7635
filebase : 'x86simdsortcpp',
7736
description : 'C++ template library for high performance SIMD based sorting routines.')
7837

79-
# Create a new dependency variable making it easy to use this as a subproject:
80-
x86simdsortcpp_dep = declare_dependency(
81-
include_directories: include_directories('lib'),
82-
link_with: libsimdsort,
83-
)
84-
85-
# Build test suite if option build_tests set to true
86-
if get_option('build_tests')
87-
gtest_dep = dependency('gtest_main', required : true, static: false)
88-
subdir('tests')
89-
testexe = executable('testexe',
90-
include_directories : [lib, utils],
91-
dependencies : [gtest_dep, x86simdsortcpp_dep],
92-
link_whole : [libtests],
93-
)
94-
test('x86 simd sort tests', testexe)
95-
endif
96-
97-
# Build benchmarking suite if option build_benchmarks is set to true
98-
99-
if get_option('build_benchmarks')
100-
gbench_dep = dependency('benchmark', required : true, static: false)
101-
thread_dep = dependency('threads') # libbenchmark could need pthread_create
102-
subdir('benchmarks')
103-
benchexe = executable('benchexe',
104-
include_directories : [src, lib, utils, bench],
105-
dependencies : [gbench_dep, thread_dep, x86simdsortcpp_dep],
106-
link_args: ['-lbenchmark_main', ipplink],
107-
link_whole : [libbench],
108-
)
109-
endif
110-
11138
summary({
11239
'Can compile AVX-512 FP16 ISA': cancompilefp16,
11340
'Build test content': get_option('build_tests'),

0 commit comments

Comments
 (0)