tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[PATCH] __builtin_ffs/clz in sys/bitops.h
The attached patch adapts sys/bitops.h to take advantage of
__builtin_ffs/clz if available.
For recent gcc and clang on x86 and Arm, this makes the difference
between a string of branches and arithmetic versus a single x86 BSR or
Arm CLZ instruction or similar.
(No change to popcount, which lives in strings.h, not sys/bitops.h,
and still uses the usual logarithmic-SWAR algorithm that beats
microcoded loops often found in CPUs.)
The patch arranges to keep both versions exercised in the automatic
tests.
Would anyone like to see if there's a performance benefit on a range
of CPUs? It might be worthwhile, but performance measurements for
this sort of thing constitute a rabbit hole that I probably won't find
the time to fall into for in the foreseeable future.
From 494ce7f4bddb181a7de6e97aa461899926c8e761 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Thu, 13 Jul 2023 20:33:06 +0000
Subject: [PATCH] sys/bitops.h: Use __builtin_ffs/ffsll/clz/clzll if available.
Make sure to test both versions of the code.
---
sys/sys/bitops.h | 25 +++++++++++++++++++
tests/include/sys/Makefile | 1 +
tests/include/sys/t_bitops_nobuiltin.c | 34 ++++++++++++++++++++++++++
3 files changed, 60 insertions(+)
create mode 100644 tests/include/sys/t_bitops_nobuiltin.c
diff --git a/sys/sys/bitops.h b/sys/sys/bitops.h
index b80fdc247214..29017fc3e631 100644
--- a/sys/sys/bitops.h
+++ b/sys/sys/bitops.h
@@ -31,6 +31,7 @@
#ifndef _SYS_BITOPS_H_
#define _SYS_BITOPS_H_
+#include <sys/cdefs.h>
#include <sys/stdint.h>
/*
@@ -40,6 +41,11 @@
static __inline int __unused
ffs32(uint32_t _n)
{
+#if defined(__has_builtin) && __has_builtin(__builtin_ffs) && \
+ !defined(_SYS_BITOPS_NOBUILTIN)
+ __CTASSERT(sizeof(_n) <= sizeof(int));
+ return __builtin_ffs(_n);
+#else
int _v;
if (!_n)
@@ -67,6 +73,7 @@ ffs32(uint32_t _n)
_v += 1;
}
return _v;
+#endif
}
#endif
@@ -74,6 +81,11 @@ ffs32(uint32_t _n)
static __inline int __unused
ffs64(uint64_t _n)
{
+#if defined(__has_builtin) && __has_builtin(__builtin_ffsl) && \
+ !defined(_SYS_BITOPS_NOBUILTIN)
+ __CTASSERT(sizeof(_n) <= sizeof(long long));
+ return __builtin_ffsll(_n);
+#else
int _v;
if (!_n)
@@ -105,6 +117,7 @@ ffs64(uint64_t _n)
_v += 1;
}
return _v;
+#endif
}
#endif
@@ -115,6 +128,11 @@ ffs64(uint64_t _n)
static __inline int __unused
fls32(uint32_t _n)
{
+#if defined(__has_builtin) && __has_builtin(__builtin_clz) && \
+ !defined(_SYS_BITOPS_NOBUILTIN)
+ __CTASSERT(sizeof(_n) == sizeof(int));
+ return _n == 0 ? 0 : 32 - __builtin_clz(_n);
+#else
int _v;
if (!_n)
@@ -142,6 +160,7 @@ fls32(uint32_t _n)
_v -= 1;
}
return _v;
+#endif
}
#endif
@@ -149,6 +168,11 @@ fls32(uint32_t _n)
static __inline int __unused
fls64(uint64_t _n)
{
+#if defined(__has_builtin) && __has_builtin(__builtin_clzll) && \
+ !defined(_SYS_BITOPS_NOBUILTIN)
+ __CTASSERT(sizeof(_n) == sizeof(long long));
+ return _n == 0 ? 0 : 64 - __builtin_clzll(_n);
+#else
int _v;
if (!_n)
@@ -180,6 +204,7 @@ fls64(uint64_t _n)
_v -= 1;
}
return _v;
+#endif
}
#endif
diff --git a/tests/include/sys/Makefile b/tests/include/sys/Makefile
index 25755bebfe3d..59c57b174e28 100644
--- a/tests/include/sys/Makefile
+++ b/tests/include/sys/Makefile
@@ -7,6 +7,7 @@ NOMAN= # defined
TESTSDIR= ${TESTSBASE}/include/sys
TESTS_C+= t_bitops
+TESTS_C+= t_bitops_nobuiltin
TESTS_C+= t_bootblock
TESTS_C+= t_cdefs
TESTS_C+= t_list
diff --git a/tests/include/sys/t_bitops_nobuiltin.c b/tests/include/sys/t_bitops_nobuiltin.c
new file mode 100644
index 000000000000..dd5d67a8fc1d
--- /dev/null
+++ b/tests/include/sys/t_bitops_nobuiltin.c
@@ -0,0 +1,34 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define _SYS_BITOPS_NOBUILTIN
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include "t_bitops.c"
Home |
Main Index |
Thread Index |
Old Index