Add simd_config.h and HAVE_SIMD() selector

We need to select which SIMD variable to check based on the compilation
target: HAVE_KERNEL_xxx for the Linux kernel, HAVE_TOOLCHAIN_xxx for
other platforms.

This adds a HAVE_SIMD() macro returns the right result depending on the
definedness or value of the variable for this target.

The macro is in simd_config.h, which is forcibly included in every
compiler call (like zfs_config.h), to ensure that it can be used
directly without further includes.

Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <rob.norris@truenas.com>
Closes #18285
This commit is contained in:
Rob Norris 2026-03-05 10:23:30 +11:00 committed by Brian Behlendorf
parent 35f74f84e6
commit c329530e6b
5 changed files with 111 additions and 2 deletions

View File

@ -7,6 +7,7 @@
PHONY =
AM_CPPFLAGS = \
-include $(top_builddir)/zfs_config.h \
-include $(top_srcdir)/include/sys/simd_config.h \
-I$(top_builddir)/include \
-I$(top_srcdir)/include \
-I$(top_srcdir)/lib/libspl/include \

View File

@ -82,6 +82,7 @@ COMMON_H = \
sys/sa.h \
sys/sa_impl.h \
sys/sha2.h \
sys/simd_config.h \
sys/skein.h \
sys/spa.h \
sys/spa_checkpoint.h \

102
include/sys/simd_config.h Normal file
View File

@ -0,0 +1,102 @@
// SPDX-License-Identifier: CDDL-1.0
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2026, TrueNAS.
*/
#ifndef _SYS_SIMD_CONFIG_H
#define _SYS_SIMD_CONFIG_H
/*
* Goal: a HAVE_SIMD(x) macro that expands to either 1 or 0 depending on
* the availabilty of that extension on the wanted toolchain.
*
* We need to allow the following:
* - #define HAVE_TOOLCHAIN_AVX 1 (zfs_config.h, detected by configure)
* - #undef HAVE_TOOLCHAIN_AVX (zfs_config.h, probed but not detected)
* - -DHAVE_TOOLCHAIN_AVX (Makefile.bsd)
*
* For completeness, we also allow disabling by defined HAVE_TOOLCHAIN_AVX=0.
*
* The "obvious" implementation of this would be a macro that includes
* defined(...) in its expansion, but unfortunately that is not portable, and
* can produce compiler warnings (see -Wexpansion-to-defined). So we need to
* build our own version.
*/
/*
* 1. Expand incoming token to its defined value, if anything:
* eg HAVE_SIMD(AVX)
* -> _zfs_deftrue(HAVE_TOOLCHAIN_AVX)
* or -> __zfs_deftrue() (HAVE_TOOLCHAIN_AVX defined)
* or -> __zfs_deftrue(1) (HAVE_TOOLCHAIN_AVX = 1)
* -> __zfs_deftrue(0) (HAVE_TOOLCHAIN_AVX = 0)
* or -> __zfs_deftrue(HAVE_TOOLCHAIN_AVX) (HAVE_TOOLCHAIN_AVX undef)
*/
#define _zfs_deftrue(x) __zfs_deftrue(x)
/*
* 2. Replace know values with a token that we control:
* __zfs_deftrue()
* -> ___zfs_deftrue(___zfs_deftrue_arg_)
* __zfs_deftrue(1)
* -> ___zfs_deftrue(___zfs_deftrue_arg_1)
* __zfs_deftrue(0)
* -> ___zfs_deftrue(___zfs_deftrue_arg_0)
* __zfs_deftrue(HAVE_TOOLCHAIN_AVX)
* -> ___zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX)
*/
#define __zfs_deftrue(v) ___zfs_deftrue(___zfs_deftrue_arg_##v)
/*
* 3. Expand the incoming token into positional parameters for the next call:
* ___zfs_deftrue(___zfs_deftrue_arg_0)
* -> ____zfs_deftrue(0, 0, 0)
* ___zfs_deftrue(___zfs_deftrue_arg_1)
* -> ____zfs_deftrue(0, 1, 0)
* ___zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX)
* -> ____zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX, 0)
*/
#define ___zfs_deftrue_arg_ 0, 1
#define ___zfs_deftrue_arg_1 0, 1
#define ___zfs_deftrue_arg_0 0, 0
#define ___zfs_deftrue(t, ...) ____zfs_deftrue(t, 0)
/*
* 4. Emit the second argument, either the original value or the default 0.
* ____zfs_deftrue(0, 0, 0) -> 0
* ____zfs_deftrue(0, 1, 0) -> 1
* ____zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX, 0) -> 0
*/
#define ____zfs_deftrue(_n, v, ...) v
/*
* The Linux kernel requires a specific toolchain. Everything else uses the
* regular compiler toolchain.
*/
#if defined(_KERNEL) && defined(__linux__)
#define HAVE_SIMD(ext) _zfs_deftrue(HAVE_KERNEL_##ext)
#else
#define HAVE_SIMD(ext) _zfs_deftrue(HAVE_TOOLCHAIN_##ext)
#endif
#endif

View File

@ -11,6 +11,7 @@ zfs_include = @abs_top_srcdir@/include
icp_include = @abs_srcdir@/icp/include
zstd_include = @abs_srcdir@/zstd/include
ZFS_MODULE_CFLAGS += -include @abs_top_builddir@/zfs_config.h
ZFS_MODULE_CFLAGS += -include $(zfs_include)/sys/simd_config.h
ZFS_MODULE_CFLAGS += -I@abs_top_builddir@/include
src = @abs_srcdir@
obj = @abs_builddir@
@ -19,6 +20,7 @@ zfs_include = $(srctree)/include/zfs
icp_include = $(src)/icp/include
zstd_include = $(src)/zstd/include
ZFS_MODULE_CFLAGS += -include $(zfs_include)/zfs_config.h
ZFS_MODULE_CFLAGS += -include $(zfs_include)/sys/simd_config.h
endif
ZFS_MODULE_CFLAGS += -I$(zfs_include)/os/linux/kernel

View File

@ -38,6 +38,7 @@ CFLAGS+= -I${INCDIR}/os/freebsd
CFLAGS+= -I${INCDIR}/os/freebsd/spl
CFLAGS+= -I${INCDIR}/os/freebsd/zfs
CFLAGS+= -I${SRCDIR}/zstd/include
CFLAGS+= -include ${INCDIR}/sys/simd_config.h
CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h
CFLAGS+= -I${.CURDIR}
@ -46,8 +47,10 @@ CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \
-D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DCOMPAT_FREEBSD11
.if ${MACHINE_ARCH} == "amd64"
CFLAGS+= -D__x86_64 -DHAVE_SSE2 -DHAVE_SSSE3 -DHAVE_SSE4_1 \
-DHAVE_AVX -DHAVE_AVX2 -DHAVE_AVX512F -DHAVE_AVX512VL -DHAVE_AVX512BW
CFLAGS+= -D__x86_64 -DHAVE_TOOLCHAIN_SSE2 -DHAVE_TOOLCHAIN_SSSE3 \
-DHAVE_TOOLCHAIN_SSE4_1 -DHAVE_TOOLCHAIN_AVX -DHAVE_TOOLCHAIN_AVX2 \
-DHAVE_TOOLCHAIN_AVX512F -DHAVE_TOOLCHAIN_AVX512VL \
-DHAVE_TOOLCHAIN_AVX512BW
.endif
.if defined(WITH_DEBUG) && ${WITH_DEBUG} == "true"