Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmake/cpu_features.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ elseif (ARCH_PPC64LE)
# Note that gcc and clang have support for x86 SSE2 intrinsics when building for PowerPC
option (POWER9 "Build for Power 9 CPU and above" 0)
if(POWER9)
set (COMPILER_FLAGS "${COMPILER_FLAGS} -maltivec -mcpu=power9 -D__SSE2__=1 -DNO_WARN_X86_INTRINSICS")
set (COMPILER_FLAGS "${COMPILER_FLAGS} -maltivec -mcpu=power9 -D__SSE2__=1 -DNO_WARN_X86_INTRINSICS -DHAVE_POWER8=1 -DHAS_ALTIVEC=1")
else ()
set (COMPILER_FLAGS "${COMPILER_FLAGS} -maltivec -mcpu=power8 -D__SSE2__=1 -DNO_WARN_X86_INTRINSICS")
set (COMPILER_FLAGS "${COMPILER_FLAGS} -maltivec -mcpu=power8 -D__SSE2__=1 -DNO_WARN_X86_INTRINSICS -DHAVE_POWER8=1 -DHAS_ALTIVEC=1")
endif ()

elseif (ARCH_AMD64)
Expand Down
12 changes: 11 additions & 1 deletion src/Common/HashTable/Hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,16 @@ inline DB::UInt64 intHash64(DB::UInt64 x)
#include <nmmintrin.h>
#endif

#if (defined(__PPC64__) || defined(__powerpc64__)) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#include "Common/HashTable/crc32_constants.h"
# include "Common/HashTable/vec_crc32.h"
#endif



#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
#include <arm_acle.h>
#endif

/// NOTE: Intel intrinsic can be confusing.
/// - https://code.google.com/archive/p/sse-intrinsics/wikis/PmovIntrinsicBug.wiki
/// - https://stackoverflow.com/questions/15752770/mm-crc32-u64-poorly-defined
Expand All @@ -57,6 +63,8 @@ inline DB::UInt64 intHashCRC32(DB::UInt64 x)
return _mm_crc32_u64(-1ULL, x);
#elif defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
return __crc32cd(-1U, x);
#elif (defined(__PPC64__) || defined(__powerpc64__)) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return crc32_ppc(-1U, reinterpret_cast<const unsigned char *>(&x), sizeof(x));
#else
/// On other platforms we do not have CRC32. NOTE This can be confusing.
/// NOTE: consider using intHash32()
Expand All @@ -69,6 +77,8 @@ inline DB::UInt64 intHashCRC32(DB::UInt64 x, DB::UInt64 updated_value)
return _mm_crc32_u64(updated_value, x);
#elif defined(__aarch64__) && defined(__ARM_FEATURE_CRC32)
return __crc32cd(static_cast<UInt32>(updated_value), x);
#elif (defined(__PPC64__) || defined(__powerpc64__)) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return crc32_ppc(updated_value, reinterpret_cast<const unsigned char *>(&x), sizeof(x));
#else
/// On other platforms we do not have CRC32. NOTE This can be confusing.
return intHash64(x) ^ updated_value;
Expand Down
87 changes: 87 additions & 0 deletions src/Common/HashTable/clang_workaround.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#ifndef CLANG_WORKAROUND_H
#define CLANG_WORKAROUND_H

/*
* These stubs fix clang incompatibilities with GCC builtins.
*/

#ifndef __builtin_crypto_vpmsumw
#define __builtin_crypto_vpmsumw __builtin_crypto_vpmsumb
#endif
#ifndef __builtin_crypto_vpmsumd
#define __builtin_crypto_vpmsumd __builtin_crypto_vpmsumb
#endif

static inline
__vector unsigned long long __attribute__((overloadable))
vec_ld(int __a, const __vector unsigned long long* __b)
{
return (__vector unsigned long long)__builtin_altivec_lvx(__a, __b);
}

/*
* GCC __builtin_pack_vector_int128 returns a vector __int128_t but Clang
* does not recognize this type. On GCC this builtin is translated to a
* xxpermdi instruction that only moves the registers __a, __b instead generates
* a load.
*
* Clang has vec_xxpermdi intrinsics. It was implemented in 4.0.0.
*/
static inline
__vector unsigned long long __builtin_pack_vector (unsigned long __a,
unsigned long __b)
{
#if defined(__BIG_ENDIAN__)
__vector unsigned long long __v = {__a, __b};
#else
__vector unsigned long long __v = {__b, __a};
#endif
return __v;
}

/*
* Clang 7 changed the behavior of vec_xxpermdi in order to provide the same
* behavior of GCC. That means code adapted to Clang >= 7 does not work on
* Clang <= 6. So, fallback to __builtin_unpack_vector() on Clang <= 6.
*/
#if !defined vec_xxpermdi || __clang_major__ <= 6

static inline
unsigned long __builtin_unpack_vector (__vector unsigned long long __v,
int __o)
{
return __v[__o];
}

#if defined(__BIG_ENDIAN__)
#define __builtin_unpack_vector_0(a) __builtin_unpack_vector ((a), 0)
#define __builtin_unpack_vector_1(a) __builtin_unpack_vector ((a), 1)
#else
#define __builtin_unpack_vector_0(a) __builtin_unpack_vector ((a), 1)
#define __builtin_unpack_vector_1(a) __builtin_unpack_vector ((a), 0)
#endif

#else

static inline
unsigned long __builtin_unpack_vector_0 (__vector unsigned long long __v)
{
#if defined(__BIG_ENDIAN__)
return vec_xxpermdi(__v, __v, 0x0)[0];
#else
return vec_xxpermdi(__v, __v, 0x3)[0];
#endif
}

static inline
unsigned long __builtin_unpack_vector_1 (__vector unsigned long long __v)
{
#if defined(__BIG_ENDIAN__)
return vec_xxpermdi(__v, __v, 0x3)[0];
#else
return vec_xxpermdi(__v, __v, 0x0)[0];
#endif
}
#endif /* vec_xxpermdi */

#endif
Loading