diff --git a/CMakeLists.txt b/CMakeLists.txt index 37a553dd64..c04b71e0a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,6 +228,9 @@ ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND CMAKE_GENERATOR_PLATFORM STREQUA ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") MESSAGE(STATUS "Building for AArch64") SET(EMBREE_ARM ON) +ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64") + MESSAGE(STATUS "Building for PowerPC64") + SET(EMBREE_PPC64 ON) ENDIF() SET(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system") @@ -388,6 +391,13 @@ IF (EMBREE_MAX_ISA STREQUAL "NONE") TRY_COMPILE(COMPILER_SUPPORTS_AVX2 "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp" COMPILE_DEFINITIONS ${FLAGS_AVX2}) TRY_COMPILE(COMPILER_SUPPORTS_AVX512 "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp" COMPILE_DEFINITIONS ${FLAGS_AVX512}) TRY_COMPILE(COMPILER_SUPPORTS_APX "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/common/cmake/check_isa.cpp" COMPILE_DEFINITIONS ${FLAGS_APX}) + IF (EMBREE_PPC64) + # the probes pass trivially without any x86 flags + SET(COMPILER_SUPPORTS_AVX OFF) + SET(COMPILER_SUPPORTS_AVX2 OFF) + SET(COMPILER_SUPPORTS_AVX512 OFF) + SET(COMPILER_SUPPORTS_APX OFF) + ENDIF () OPTION(EMBREE_ISA_SSE2 "Enables SSE2 ISA." ON) OPTION(EMBREE_ISA_SSE42 "Enables SSE4.2 ISA." ON) @@ -563,6 +573,10 @@ IF (EMBREE_ARM) ENDIF() ENDIF() +IF (EMBREE_PPC64) + LIST(APPEND ISPC_TARGETS "vsx-i32x4") +ENDIF() + IF (EMBREE_ISA_NEON) SET(EMBREE_ISA_SSE2 ON) ENDIF() @@ -576,7 +590,7 @@ ENDIF() IF (EMBREE_ISA_SSE2) ADD_DEFINITIONS(-DEMBREE_TARGET_SSE2) - IF (NOT EMBREE_ARM) + IF (NOT EMBREE_ARM AND NOT EMBREE_PPC64) LIST(APPEND ISPC_TARGETS "sse2") ENDIF() IF(NOT FLAGS_LOWEST) @@ -587,7 +601,7 @@ ENDIF() IF (EMBREE_ISA_SSE42) ADD_DEFINITIONS(-DEMBREE_TARGET_SSE42) - IF (NOT EMBREE_ARM) + IF (NOT EMBREE_ARM AND NOT EMBREE_PPC64) LIST(APPEND ISPC_TARGETS "sse4") ENDIF() IF(NOT FLAGS_LOWEST) diff --git a/common/cmake/clang.cmake b/common/cmake/clang.cmake index ecb5f399db..1ba7ec1faf 100644 --- a/common/cmake/clang.cmake +++ b/common/cmake/clang.cmake @@ -21,6 +21,14 @@ IF (EMBREE_ARM) SET(FLAGS_AVX "-D__AVX__ -D__SSE4_2__ -D__SSE4_1__ -D__BMI__ -D__BMI2__ -D__LZCNT__") SET(FLAGS_AVX2 "-D__AVX2__ -D__AVX__ -D__SSE4_2__ -D__SSE4_1__ -D__BMI__ -D__BMI2__ -D__LZCNT__") ENDIF () +ELSEIF (EMBREE_PPC64) + # the x86 intrinsic wrappers need POWER8, honor a newer -mcpu from the user + STRING(REGEX MATCH "-mcpu=[^ ]+" FLAGS_PPC64_CPU "${CMAKE_CXX_FLAGS}") + IF (NOT FLAGS_PPC64_CPU) + SET(FLAGS_PPC64_CPU "-mcpu=power8") + ENDIF () + SET(FLAGS_SSE2 "-D__SSE__ -D__SSE2__ ${FLAGS_PPC64_CPU}") + SET(FLAGS_SSE42 "-D__SSE4_2__ -D__SSE4_1__ ${FLAGS_PPC64_CPU}") ELSE () # for `thread` keyword _SET_IF_EMPTY(FLAGS_SSE2 "-msse -msse2 -mno-sse4.2") diff --git a/common/cmake/ispc.cmake b/common/cmake/ispc.cmake index 7a4abaeb85..957dd66de9 100644 --- a/common/cmake/ispc.cmake +++ b/common/cmake/ispc.cmake @@ -75,6 +75,8 @@ MACRO (ISPC_COMPILE) IF (CMAKE_SIZEOF_VOID_P EQUAL 8) IF (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") SET(ISPC_ARCHITECTURE "aarch64") + ELSEIF (${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(powerpc|ppc)64le") + SET(ISPC_ARCHITECTURE "ppc64le") ELSE() SET(ISPC_ARCHITECTURE "x86-64") ENDIF() diff --git a/common/sys/intrinsics.h b/common/sys/intrinsics.h index fb6610605d..6b58e5ecc3 100644 --- a/common/sys/intrinsics.h +++ b/common/sys/intrinsics.h @@ -13,6 +13,39 @@ #include "../simd/arm/emulation.h" #else #include +#if defined(__powerpc64__) && defined(__clang__) +__forceinline unsigned int _mm_getcsr() { return 0; } +__forceinline void _mm_setcsr(unsigned int) {} +__forceinline int _mm_popcnt_u32(unsigned int v) { return __builtin_popcount(v); } +__forceinline long long _mm_popcnt_u64(unsigned long long v) { return __builtin_popcountll(v); } +__forceinline __m128i _mm_stream_load_si128(__m128i* p) { return _mm_load_si128(p); } +__forceinline __m128 _mm_dp_ps(__m128 a, __m128 b, const int imm) { + const __m128i hi = _mm_set_epi32((imm & 0x80) ? -1 : 0, (imm & 0x40) ? -1 : 0, (imm & 0x20) ? -1 : 0, (imm & 0x10) ? -1 : 0); + const __m128i lo = _mm_set_epi32((imm & 0x08) ? -1 : 0, (imm & 0x04) ? -1 : 0, (imm & 0x02) ? -1 : 0, (imm & 0x01) ? -1 : 0); + __m128 p = _mm_and_ps(_mm_mul_ps(a, b), _mm_castsi128_ps(hi)); + p = _mm_hadd_ps(p, p); + p = _mm_hadd_ps(p, p); + return _mm_and_ps(p, _mm_castsi128_ps(lo)); +} +__forceinline __m128 _mm_insert_ps(__m128 a, __m128 b, const int imm) { + float ta[4], tb[4]; + _mm_storeu_ps(ta, a); + _mm_storeu_ps(tb, b); + ta[(imm >> 4) & 3] = tb[(imm >> 6) & 3]; + for (int i = 0; i < 4; i++) if (imm & (1 << i)) ta[i] = 0.0f; + return _mm_loadu_ps(ta); +} +#define _MM_MASK_DENORM 0x0100 +#define _MM_MASK_DIV_ZERO 0x0200 +#define _MM_MASK_MASK 0x1f80 +#define _MM_FLUSH_ZERO_MASK 0x8000 +#define _MM_FLUSH_ZERO_ON 0x8000 +#define _MM_DENORMALS_ZERO_ON 0x0040 +#define _MM_DENORMALS_ZERO_OFF 0x0000 +#define _MM_DENORMALS_ZERO_MASK 0x0040 +#define _MM_SET_EXCEPTION_MASK(x) _mm_setcsr((_mm_getcsr() & ~_MM_MASK_MASK) | (x)) +#define _MM_SET_FLUSH_ZERO_MODE(x) _mm_setcsr((_mm_getcsr() & ~_MM_FLUSH_ZERO_MASK) | (x)) +#endif #if defined(__EMSCRIPTEN__) #include "../simd/wasm/emulation.h" #endif diff --git a/common/sys/platform.h b/common/sys/platform.h index 73bb412aa8..776a3b8277 100644 --- a/common/sys/platform.h +++ b/common/sys/platform.h @@ -57,12 +57,18 @@ #define __X86_ASM__ #endif +#if defined(__powerpc64__) +#define NO_WARN_X86_INTRINSICS +#define __SSE__ +#define __SSE2__ +#endif + /* detect 64 bit platform */ #if defined(__aarch64__) || defined(_M_ARM64) #define EMBREE_ARM64 #endif -#if defined(__X86_64__) || defined(EMBREE_ARM64) +#if defined(__X86_64__) || defined(EMBREE_ARM64) || defined(__powerpc64__) #define __64BIT__ #endif diff --git a/common/sys/sysinfo.cpp b/common/sys/sysinfo.cpp index 81e6cd23d8..843d9f1e1a 100644 --- a/common/sys/sysinfo.cpp +++ b/common/sys/sysinfo.cpp @@ -429,6 +429,13 @@ namespace embree #endif return cpu_features; +#elif defined(__powerpc64__) + + int cpu_features = CPU_FEATURE_SSE|CPU_FEATURE_SSE2|CPU_FEATURE_SSE3|CPU_FEATURE_SSSE3; + cpu_features |= CPU_FEATURE_SSE41|CPU_FEATURE_SSE42|CPU_FEATURE_POPCNT; + cpu_features |= CPU_FEATURE_XMM_ENABLED; + return cpu_features; + #elif defined(__ARM_NEON) || defined(EMBREE_ARM64) || defined(__EMSCRIPTEN__) int cpu_features = CPU_FEATURE_NEON|CPU_FEATURE_SSE|CPU_FEATURE_SSE2;