mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 09:32:01 +00:00
169 lines
5.7 KiB
C++
169 lines
5.7 KiB
C++
#pragma once
|
|
|
|
/// This file contains macros and helpers for writing platform-dependent code.
|
|
///
|
|
/// Macroses DECLARE_<Arch>_SPECIFIC_CODE will wrap code inside them into the namespace TargetSpecific::<Arch> and enable
|
|
/// Arch-specific compile options.
|
|
/// Thus, it's allowed to call functions inside only after checking platform in runtime (see IsArchSupported() below)
|
|
/// For similarities there is a macros DECLARE_DEFAULT_CODE, which wraps code into the namespace TargetSpecific::Default
|
|
/// but dosn't specify any additional copile options.
|
|
///
|
|
/// Example:
|
|
///
|
|
/// DECLARE_DEFAULT_CODE (
|
|
/// int func() {
|
|
/// return 1;
|
|
/// }
|
|
/// ) // DECLARE_DEFAULT_CODE
|
|
///
|
|
/// DECLARE_AVX2_SPECIFIC_CODE (
|
|
/// int func() {
|
|
/// return 2;
|
|
/// }
|
|
/// ) // DECLARE_DEFAULT_CODE
|
|
///
|
|
/// int func() {
|
|
/// if (IsArchSupported(TargetArch::AVX2))
|
|
/// return TargetSpecifc::AVX2::func();
|
|
/// return TargetSpecifc::Default::func();
|
|
/// }
|
|
///
|
|
/// Sometimes code may benefit from compiling with different options.
|
|
/// For these purposes use DECLARE_MULTITARGET_CODE macros. It will create several copies of the code and
|
|
/// compile it with different options. These copies are available via TargetSpecifc namespaces described above.
|
|
///
|
|
/// Inside every TargetSpecific namespace there is a constexpr variable BuildArch, which TODO
|
|
///
|
|
/// Example:
|
|
///
|
|
/// DECLARE_MULTITARGET_CODE(
|
|
/// int func(int size, ...) {
|
|
/// int iteration_size = 1;
|
|
/// if constexpr (BuildArch == TargetArch::SSE4)
|
|
/// iteration_size = 2
|
|
/// else if constexpr (BuildArch == TargetArch::AVX || BuildArch == TargetArch::AVX2)
|
|
/// iteration_size = 4;
|
|
/// else if constexpr (BuildArch == TargetArch::AVX512)
|
|
/// iteration_size = 8;
|
|
/// for (int i = 0; i < size; i += iteration_size)
|
|
/// ...
|
|
/// }
|
|
/// ) // DECLARE_MULTITARGET_CODE
|
|
///
|
|
/// // All 5 versions of func are available here. Use runtime detection to choose one.
|
|
///
|
|
/// If you want to write IFunction or IExecutableFuncionImpl with runtime dispatching, see PerformanceAdaptors.h.
|
|
|
|
namespace DB
|
|
{
|
|
|
|
enum class TargetArch : int {
|
|
Default = 0, // Without any additional compiler options.
|
|
SSE4 = (1 << 0),
|
|
AVX = (1 << 1),
|
|
AVX2 = (1 << 2),
|
|
AVX512 = (1 << 3),
|
|
};
|
|
|
|
// Runtime detection.
|
|
bool IsArchSupported(TargetArch arch);
|
|
|
|
#if defined(__GNUC__)
|
|
// TODO: There are lots of different AVX512 :(
|
|
# define BEGIN_AVX512_SPECIFIC_CODE \
|
|
_Pragma("GCC push_options") \
|
|
_Pragma("GCC target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,avx512f,tune=native\")")
|
|
# define BEGIN_AVX2_SPECIFIC_CODE \
|
|
_Pragma("GCC push_options") \
|
|
_Pragma("GCC target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native\")")
|
|
# define BEGIN_AVX_SPECIFIC_CODE \
|
|
_Pragma("GCC push_options") \
|
|
_Pragma("GCC target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native\")")
|
|
# define BEGIN_SSE4_SPECIFIC_CODE \
|
|
_Pragma("GCC push_options") \
|
|
_Pragma("GCC target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,tune=native\")")
|
|
# define END_TARGET_SPECIFIC_CODE \
|
|
_Pragma("GCC pop_options")
|
|
#elif defined(__clang__)
|
|
// TODO: There are lots of different AVX512 :(
|
|
# define BEGIN_AVX512_SPECIFIC_CODE \
|
|
_Pragma("clang attribute push (__attribute__((target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2\"))))")
|
|
# define BEGIN_AVX2_SPECIFIC_CODE \
|
|
_Pragma("clang attribute push (__attribute__((target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2\"))))")
|
|
# define BEGIN_AVX_SPECIFIC_CODE \
|
|
_Pragma("clang attribute push (__attribute__((target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx\"))))")
|
|
# define BEGIN_SSE4_SPECIFIC_CODE \
|
|
_Pragma("clang attribute push (__attribute__((target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx\"))))")
|
|
# define END_TARGET_SPECIFIC_CODE \
|
|
_Pragma("clang attribute pop")
|
|
#else
|
|
# error "Only CLANG and GCC compilers are supported for vectorized code generation"
|
|
#endif
|
|
|
|
#define DECLARE_DEFAULT_CODE(...) \
|
|
namespace TargetSpecific::Default { \
|
|
using namespace DB::TargetSpecific::Default; \
|
|
__VA_ARGS__ \
|
|
}
|
|
|
|
#define DECLARE_SSE4_SPECIFIC_CODE(...) \
|
|
BEGIN_SSE4_SPECIFIC_CODE \
|
|
namespace TargetSpecific::SSE4 { \
|
|
using namespace DB::TargetSpecific::SSE4; \
|
|
__VA_ARGS__ \
|
|
} \
|
|
END_TARGET_SPECIFIC_CODE
|
|
|
|
#define DECLARE_AVX_SPECIFIC_CODE(...) \
|
|
BEGIN_AVX_SPECIFIC_CODE \
|
|
namespace TargetSpecific::AVX { \
|
|
using namespace DB::TargetSpecific::AVX; \
|
|
__VA_ARGS__ \
|
|
} \
|
|
END_TARGET_SPECIFIC_CODE
|
|
|
|
#define DECLARE_AVX2_SPECIFIC_CODE(...) \
|
|
BEGIN_AVX2_SPECIFIC_CODE \
|
|
namespace TargetSpecific::AVX2 { \
|
|
using namespace DB::TargetSpecific::AVX2; \
|
|
__VA_ARGS__ \
|
|
} \
|
|
END_TARGET_SPECIFIC_CODE
|
|
|
|
#define DECLARE_AVX512_SPECIFIC_CODE(...) \
|
|
BEGIN_AVX512_SPECIFIC_CODE \
|
|
namespace TargetSpecific::AVX512 { \
|
|
using namespace DB::TargetSpecific::AVX512; \
|
|
__VA_ARGS__ \
|
|
} \
|
|
END_TARGET_SPECIFIC_CODE
|
|
|
|
#define DECLARE_MULTITARGET_CODE(...) \
|
|
DECLARE_DEFAULT_CODE (__VA_ARGS__) \
|
|
DECLARE_SSE4_SPECIFIC_CODE (__VA_ARGS__) \
|
|
DECLARE_AVX_SPECIFIC_CODE (__VA_ARGS__) \
|
|
DECLARE_AVX2_SPECIFIC_CODE (__VA_ARGS__) \
|
|
DECLARE_AVX512_SPECIFIC_CODE(__VA_ARGS__)
|
|
|
|
DECLARE_DEFAULT_CODE(
|
|
constexpr auto BuildArch = TargetArch::Default;
|
|
) // DECLARE_DEFAULT_CODE
|
|
|
|
DECLARE_SSE4_SPECIFIC_CODE(
|
|
constexpr auto BuildArch = TargetArch::SSE4;
|
|
) // DECLARE_SSE4_SPECIFIC_CODE
|
|
|
|
DECLARE_AVX_SPECIFIC_CODE(
|
|
constexpr auto BuildArch = TargetArch::AVX;
|
|
) // DECLARE_AVX_SPECIFIC_CODE
|
|
|
|
DECLARE_AVX2_SPECIFIC_CODE(
|
|
constexpr auto BuildArch = TargetArch::AVX2;
|
|
) // DECLARE_AVX2_SPECIFIC_CODE
|
|
|
|
DECLARE_AVX512_SPECIFIC_CODE(
|
|
constexpr auto BuildArch = TargetArch::AVX512;
|
|
) // DECLARE_AVX512_SPECIFIC_CODE
|
|
|
|
} // namespace DB
|