This is an automated email from the ASF dual-hosted git repository.
kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new d048f71964 GH-50542: [C++] Fix ARROW_SIMD_LEVEL=NONE build, compile
SSE4.2 kernels (#50547)
d048f71964 is described below
commit d048f71964fe2df5540be2256048eb15f830962b
Author: Dominique Belhachemi <[email protected]>
AuthorDate: Sun Aug 16 16:19:12 2026 -0400
GH-50542: [C++] Fix ARROW_SIMD_LEVEL=NONE build, compile SSE4.2 kernels
(#50547)
### Rationale for this change
Building with ARROW_SIMD_LEVEL=NONE and ARROW_RUNTIME_SIMD_LEVEL=MAX failed
with:
bpacking.cc:39:49: error: 'unpack_sse4_2' is not a member of
'arrow::internal::bpacking'
The SSE4.2 dispatch table entries are emitted when either the compile-time
or the runtime macro is set, but the kernels themselves were only compiled when
the compile-time macro was set.
### What changes are included in this PR?
I moved the byte_stream_split SSE4.2 instantiations into a dedicated
translation unit, keeping the dispatcher's own unit at the baseline ISA.
### Are these changes tested?
Yes
### Are there any user-facing changes?
No
* GitHub Issue: #50542
Authored-by: Dominique Belhachemi <[email protected]>
Signed-off-by: Sutou Kouhei <[email protected]>
---
.github/workflows/cpp_extra.yml | 6 +++
cpp/src/arrow/CMakeLists.txt | 15 ++++++++
cpp/src/arrow/util/bpacking_simd_128.cc | 2 +-
cpp/src/arrow/util/bpacking_simd_internal.h | 2 +-
cpp/src/arrow/util/bpacking_test.cc | 8 +++-
cpp/src/arrow/util/byte_stream_split_internal.h | 24 +++++++++++-
.../util/byte_stream_split_internal_sse4_2.cc | 43 ++++++++++++++++++++++
7 files changed, 94 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/cpp_extra.yml b/.github/workflows/cpp_extra.yml
index c384f5f0f7..60332f08f6 100644
--- a/.github/workflows/cpp_extra.yml
+++ b/.github/workflows/cpp_extra.yml
@@ -122,6 +122,12 @@ jobs:
-e CMAKE_CXX_STANDARD=23
runs-on: ubuntu-latest
title: AMD64 Debian C++23
+ - image: debian-cpp
+ run-options: >-
+ -e ARROW_SIMD_LEVEL=NONE
+ -e ARROW_CXXFLAGS=-march=x86-64
+ runs-on: ubuntu-latest
+ title: AMD64 Debian SIMD Level NONE
env:
ARCHERY_DEBUG: 1
ARROW_ENABLE_TIMING_TESTS: OFF
diff --git a/cpp/src/arrow/CMakeLists.txt b/cpp/src/arrow/CMakeLists.txt
index 2569b9bcd4..c5bc01c8ef 100644
--- a/cpp/src/arrow/CMakeLists.txt
+++ b/cpp/src/arrow/CMakeLists.txt
@@ -325,6 +325,13 @@ function(ADD_ARROW_BENCHMARK REL_TEST_NAME)
${ARG_UNPARSED_ARGUMENTS})
endfunction()
+macro(append_runtime_sse4_2_src SRCS SRC)
+ if(ARROW_HAVE_RUNTIME_SSE4_2 AND ARROW_SIMD_LEVEL STREQUAL "NONE")
+ list(APPEND ${SRCS} ${SRC})
+ set_source_files_properties(${SRC} PROPERTIES COMPILE_OPTIONS
"${ARROW_SSE4_2_FLAG}")
+ endif()
+endmacro()
+
macro(append_runtime_avx2_src SRCS SRC)
if(ARROW_HAVE_RUNTIME_AVX2)
list(APPEND ${SRCS} ${SRC})
@@ -612,9 +619,17 @@ set(ARROW_UTIL_SRCS
append_runtime_avx2_src(ARROW_UTIL_SRCS
util/byte_stream_split_internal_avx2.cc)
+append_runtime_sse4_2_src(ARROW_UTIL_SRCS
util/byte_stream_split_internal_sse4_2.cc)
+
append_runtime_avx2_src(ARROW_UTIL_SRCS util/bpacking_simd_256.cc)
append_runtime_avx512_src(ARROW_UTIL_SRCS util/bpacking_simd_avx512.cc)
+# also provides the NEON kernels on aarch64, so it stays in ARROW_UTIL_SRCS
+if(ARROW_CPU_FLAG STREQUAL "x86" AND ARROW_HAVE_RUNTIME_SSE4_2)
+ set_source_files_properties(util/bpacking_simd_128.cc PROPERTIES
COMPILE_OPTIONS
+
"${ARROW_SSE4_2_FLAG}")
+endif()
+
append_runtime_sve256_src(ARROW_UTIL_SRCS util/bpacking_simd_256.cc)
if(ARROW_WITH_BROTLI)
diff --git a/cpp/src/arrow/util/bpacking_simd_128.cc
b/cpp/src/arrow/util/bpacking_simd_128.cc
index 1bc756b2aa..9f35667d2a 100644
--- a/cpp/src/arrow/util/bpacking_simd_128.cc
+++ b/cpp/src/arrow/util/bpacking_simd_128.cc
@@ -18,7 +18,7 @@
#if defined(ARROW_HAVE_NEON)
# define UNPACK_PLATFORM unpack_neon
# define KERNEL_PLATFORM KernelNeon
-#elif defined(ARROW_HAVE_SSE4_2)
+#elif defined(ARROW_HAVE_SSE4_2) || defined(ARROW_HAVE_RUNTIME_SSE4_2)
# define UNPACK_PLATFORM unpack_sse4_2
# define KERNEL_PLATFORM KernelSse42
#endif
diff --git a/cpp/src/arrow/util/bpacking_simd_internal.h
b/cpp/src/arrow/util/bpacking_simd_internal.h
index 78aaa4a8f9..88df5f6bb0 100644
--- a/cpp/src/arrow/util/bpacking_simd_internal.h
+++ b/cpp/src/arrow/util/bpacking_simd_internal.h
@@ -26,7 +26,7 @@ namespace arrow::internal::bpacking {
#if defined(ARROW_HAVE_NEON)
# define UNPACK_ARCH128 unpack_neon
-#elif defined(ARROW_HAVE_SSE4_2)
+#elif defined(ARROW_HAVE_SSE4_2) || defined(ARROW_HAVE_RUNTIME_SSE4_2)
# define UNPACK_ARCH128 unpack_sse4_2
#endif
diff --git a/cpp/src/arrow/util/bpacking_test.cc
b/cpp/src/arrow/util/bpacking_test.cc
index 0503a15110..52c67dbd79 100644
--- a/cpp/src/arrow/util/bpacking_test.cc
+++ b/cpp/src/arrow/util/bpacking_test.cc
@@ -27,7 +27,8 @@
#include "arrow/util/bpacking_scalar_internal.h"
#include "arrow/util/bpacking_simd_internal.h"
-#if defined(ARROW_HAVE_RUNTIME_AVX2) || defined(ARROW_HAVE_RUNTIME_AVX512) || \
+#if defined(ARROW_HAVE_SSE4_2) || defined(ARROW_HAVE_RUNTIME_SSE4_2) || \
+ defined(ARROW_HAVE_RUNTIME_AVX2) || defined(ARROW_HAVE_RUNTIME_AVX512) || \
defined(ARROW_HAVE_RUNTIME_SVE128) || defined(ARROW_HAVE_RUNTIME_SVE256)
# include "arrow/util/cpu_info.h"
#endif
@@ -273,8 +274,11 @@ TYPED_TEST(TestUnpack, UnpackScalar) {
this->TestAll(&bpacking::unpack_scalar<TypeParam>);
}
-#if defined(ARROW_HAVE_SSE4_2)
+#if defined(ARROW_HAVE_SSE4_2) || defined(ARROW_HAVE_RUNTIME_SSE4_2)
TYPED_TEST(TestUnpack, UnpackSse4_2) {
+ if (!CpuInfo::GetInstance()->IsSupported(CpuInfo::SSE4_2)) {
+ GTEST_SKIP() << "Test requires SSE4.2";
+ }
this->TestAll(&bpacking::unpack_sse4_2<TypeParam>);
}
#endif
diff --git a/cpp/src/arrow/util/byte_stream_split_internal.h
b/cpp/src/arrow/util/byte_stream_split_internal.h
index 2e713dd42f..79543e1cf8 100644
--- a/cpp/src/arrow/util/byte_stream_split_internal.h
+++ b/cpp/src/arrow/util/byte_stream_split_internal.h
@@ -286,11 +286,31 @@ void ByteStreamSplitEncodeSimd(const uint8_t* raw_values,
int width,
}
}
-# if defined(ARROW_HAVE_RUNTIME_AVX2)
-
// The extern template declaration are used internally and need export
// to be used in tests and benchmarks.
+# if defined(ARROW_HAVE_RUNTIME_SSE4_2) && !defined(ARROW_HAVE_SSE4_2)
+
+// instantiated in byte_stream_split_internal_sse4_2.cc
+
+extern template ARROW_TEMPLATE_EXPORT void
ByteStreamSplitDecodeSimd<xsimd::sse4_2, 2>(
+ const uint8_t*, int, int64_t, int64_t, uint8_t*);
+extern template ARROW_TEMPLATE_EXPORT void
ByteStreamSplitDecodeSimd<xsimd::sse4_2, 4>(
+ const uint8_t*, int, int64_t, int64_t, uint8_t*);
+extern template ARROW_TEMPLATE_EXPORT void
ByteStreamSplitDecodeSimd<xsimd::sse4_2, 8>(
+ const uint8_t*, int, int64_t, int64_t, uint8_t*);
+
+extern template ARROW_TEMPLATE_EXPORT void
ByteStreamSplitEncodeSimd<xsimd::sse4_2, 2>(
+ const uint8_t*, int, const int64_t, uint8_t*);
+extern template ARROW_TEMPLATE_EXPORT void
ByteStreamSplitEncodeSimd<xsimd::sse4_2, 4>(
+ const uint8_t*, int, const int64_t, uint8_t*);
+extern template ARROW_TEMPLATE_EXPORT void
ByteStreamSplitEncodeSimd<xsimd::sse4_2, 8>(
+ const uint8_t*, int, const int64_t, uint8_t*);
+
+# endif
+
+# if defined(ARROW_HAVE_RUNTIME_AVX2)
+
extern template ARROW_TEMPLATE_EXPORT void
ByteStreamSplitDecodeSimd<xsimd::avx2, 2>(
const uint8_t*, int, int64_t, int64_t, uint8_t*);
extern template ARROW_TEMPLATE_EXPORT void
ByteStreamSplitDecodeSimd<xsimd::avx2, 4>(
diff --git a/cpp/src/arrow/util/byte_stream_split_internal_sse4_2.cc
b/cpp/src/arrow/util/byte_stream_split_internal_sse4_2.cc
new file mode 100644
index 0000000000..e96a24d67f
--- /dev/null
+++ b/cpp/src/arrow/util/byte_stream_split_internal_sse4_2.cc
@@ -0,0 +1,43 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "arrow/util/byte_stream_split_internal.h"
+#include "arrow/util/math_internal.h"
+#include "arrow/util/simd.h"
+
+#include <xsimd/types/xsimd_sse4_2_register.hpp>
+#include <xsimd/xsimd.hpp>
+
+#include <cstdint>
+
+namespace arrow::util::internal {
+
+template void ByteStreamSplitDecodeSimd<xsimd::sse4_2, 2>(const uint8_t*, int,
int64_t,
+ int64_t, uint8_t*);
+template void ByteStreamSplitDecodeSimd<xsimd::sse4_2, 4>(const uint8_t*, int,
int64_t,
+ int64_t, uint8_t*);
+template void ByteStreamSplitDecodeSimd<xsimd::sse4_2, 8>(const uint8_t*, int,
int64_t,
+ int64_t, uint8_t*);
+
+template void ByteStreamSplitEncodeSimd<xsimd::sse4_2, 2>(const uint8_t*, int,
+ const int64_t,
uint8_t*);
+template void ByteStreamSplitEncodeSimd<xsimd::sse4_2, 4>(const uint8_t*, int,
+ const int64_t,
uint8_t*);
+template void ByteStreamSplitEncodeSimd<xsimd::sse4_2, 8>(const uint8_t*, int,
+ const int64_t,
uint8_t*);
+
+} // namespace arrow::util::internal