DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/2] eal: provide leading and trailing zero bit count
@ 2022-11-23 22:14 Tyler Retzlaff
  2022-11-23 22:14 ` [PATCH 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
                   ` (7 more replies)
  0 siblings, 8 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2022-11-23 22:14 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff

Provide leading and trailing zero bit count functions to abstract away
compiler specific implementations.

Include basic unit test for new leading/trailing zero bit count functions.

Tyler Retzlaff (2):
  eal: provide leading and trailing zero bit count abstraction
  test/bitcount: add bitcount tests

 app/test/meson.build           |   2 +
 app/test/test_bitcount.c       |  92 +++++++++++++++
 lib/eal/include/meson.build    |   1 +
 lib/eal/include/rte_bitcount.h | 257 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 352 insertions(+)
 create mode 100644 app/test/test_bitcount.c
 create mode 100644 lib/eal/include/rte_bitcount.h

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
@ 2022-11-23 22:14 ` Tyler Retzlaff
  2023-04-03 21:46   ` Mattias Rönnblom
  2022-11-23 22:14 ` [PATCH 2/2] test/bitcount: add bitcount tests Tyler Retzlaff
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2022-11-23 22:14 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff

Provide an abstraction for leading and trailing zero bit counting
functions to hide compiler specific intrinsics and builtins.

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 lib/eal/include/meson.build    |   1 +
 lib/eal/include/rte_bitcount.h | 257 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 258 insertions(+)
 create mode 100644 lib/eal/include/rte_bitcount.h

diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
index cfcd40a..8ff1d65 100644
--- a/lib/eal/include/meson.build
+++ b/lib/eal/include/meson.build
@@ -5,6 +5,7 @@ includes += include_directories('.')
 
 headers += files(
         'rte_alarm.h',
+        'rte_bitcount.h',
         'rte_bitmap.h',
         'rte_bitops.h',
         'rte_branch_prediction.h',
diff --git a/lib/eal/include/rte_bitcount.h b/lib/eal/include/rte_bitcount.h
new file mode 100644
index 0000000..2f4dd38
--- /dev/null
+++ b/lib/eal/include/rte_bitcount.h
@@ -0,0 +1,257 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#ifndef EAL_BITCOUNT_H
+#define EAL_BITCOUNT_H
+
+#include <rte_compat.h>
+
+#ifdef RTE_TOOLCHAIN_MSVC
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_clz(unsigned int v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_clzl(unsigned long v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_clzll(unsigned long long v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse64(&rv, v);
+
+	return (unsigned)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_ctz(unsigned int v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_ctzl(unsigned long v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_ctzll(unsigned long long v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward64(&rv, v);
+
+	return (unsigned)rv;
+}
+
+#else
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_clz(unsigned int v)
+{
+	return (unsigned)__builtin_clz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_clzl(unsigned long v)
+{
+	return (unsigned)__builtin_clzl(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_clzll(unsigned long v)
+{
+	return (unsigned)__builtin_clzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_ctz(unsigned int v)
+{
+	return (unsigned)__builtin_ctz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_ctzl(unsigned long v)
+{
+	return (unsigned)__builtin_ctzl(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned
+rte_ctzll(unsigned long v)
+{
+	return (unsigned)__builtin_ctzll(v);
+}
+
+#endif
+
+#endif /* EAL_BITCOUNT_H */
+
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH 2/2] test/bitcount: add bitcount tests
  2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
  2022-11-23 22:14 ` [PATCH 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2022-11-23 22:14 ` Tyler Retzlaff
  2022-11-23 23:43 ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2022-11-23 22:14 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff

basic unit test of following functions

    rte_clz
    rte_clzl
    rte_clzll
    rte_ctz
    rte_ctzl
    rte_ctzll

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 app/test/meson.build     |  2 ++
 app/test/test_bitcount.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)
 create mode 100644 app/test/test_bitcount.c

diff --git a/app/test/meson.build b/app/test/meson.build
index f34d19e..d1277bc 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -13,6 +13,7 @@ test_sources = files(
         'test_alarm.c',
         'test_atomic.c',
         'test_barrier.c',
+        'test_bitcount.c',
         'test_bitops.c',
         'test_bitmap.c',
         'test_bpf.c',
@@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
 fast_tests = [
         ['acl_autotest', true, true],
         ['atomic_autotest', false, true],
+        ['bitcount_autotest', true, true],
         ['bitmap_autotest', true, true],
         ['bpf_autotest', true, true],
         ['bpf_convert_autotest', true, true],
diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
new file mode 100644
index 0000000..7b71fdf
--- /dev/null
+++ b/app/test/test_bitcount.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#include <string.h>
+
+#include <rte_bitcount.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
+
+static int
+test_clz(void)
+{
+	unsigned int v = 1;
+	RTE_TEST_ASSERT(rte_clz(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_clzl(void)
+{
+	unsigned long v = 1;
+	RTE_TEST_ASSERT(rte_clzl(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_clzll(void)
+{
+	unsigned long long v = 1;
+	RTE_TEST_ASSERT(rte_clzll(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctz(void)
+{
+	unsigned int v = 2;
+	RTE_TEST_ASSERT(rte_ctz(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctzl(void)
+{
+	unsigned long v = 2;
+	RTE_TEST_ASSERT(rte_ctzl(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctzll(void)
+{
+	unsigned long long v = 2;
+	RTE_TEST_ASSERT(rte_ctzll(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static struct unit_test_suite bitcount_test_suite = {
+	.suite_name = "bitcount autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+		TEST_CASE(test_clz),
+		TEST_CASE(test_clzl),
+		TEST_CASE(test_clzll),
+		TEST_CASE(test_ctz),
+		TEST_CASE(test_ctzl),
+		TEST_CASE(test_ctzll),
+		TEST_CASES_END()
+	}
+};
+
+static int
+test_bitcount(void)
+{
+	return unit_test_suite_runner(&bitcount_test_suite);
+}
+
+REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v2 0/2] eal: provide leading and trailing zero bit count
  2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
  2022-11-23 22:14 ` [PATCH 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2022-11-23 22:14 ` [PATCH 2/2] test/bitcount: add bitcount tests Tyler Retzlaff
@ 2022-11-23 23:43 ` Tyler Retzlaff
  2022-11-23 23:43   ` [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
                     ` (3 more replies)
  2023-01-06 22:01 ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Tyler Retzlaff
                   ` (4 subsequent siblings)
  7 siblings, 4 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2022-11-23 23:43 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff

Provide leading and trailing zero bit count functions to abstract away
compiler specific implementations.

Include basic unit test for new leading/trailing zero bit count functions.

v2:
  * use unsigned int instead of unsigned (checkpatches)
  * match multiple include guard naming convention to rte_common.h
  * add explicit extern "C" linkage to rte_bitcount.h
    note: not really needed but checkpatches required
  * add missing space around '-'

Tyler Retzlaff (2):
  eal: provide leading and trailing zero bit count abstraction
  test/bitcount: add bitcount tests

 app/test/meson.build           |   2 +
 app/test/test_bitcount.c       |  92 ++++++++++++++
 lib/eal/include/meson.build    |   1 +
 lib/eal/include/rte_bitcount.h | 265 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 360 insertions(+)
 create mode 100644 app/test/test_bitcount.c
 create mode 100644 lib/eal/include/rte_bitcount.h

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-23 23:43 ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
@ 2022-11-23 23:43   ` Tyler Retzlaff
  2022-11-24 10:17     ` Morten Brørup
  2023-01-05  7:09     ` Morten Brørup
  2022-11-23 23:43   ` [PATCH v2 2/2] test/bitcount: add bitcount tests Tyler Retzlaff
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2022-11-23 23:43 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff

Provide an abstraction for leading and trailing zero bit counting
functions to hide compiler specific intrinsics and builtins.

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 lib/eal/include/meson.build    |   1 +
 lib/eal/include/rte_bitcount.h | 265 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 266 insertions(+)
 create mode 100644 lib/eal/include/rte_bitcount.h

diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
index cfcd40a..8ff1d65 100644
--- a/lib/eal/include/meson.build
+++ b/lib/eal/include/meson.build
@@ -5,6 +5,7 @@ includes += include_directories('.')
 
 headers += files(
         'rte_alarm.h',
+        'rte_bitcount.h',
         'rte_bitmap.h',
         'rte_bitops.h',
         'rte_branch_prediction.h',
diff --git a/lib/eal/include/rte_bitcount.h b/lib/eal/include/rte_bitcount.h
new file mode 100644
index 0000000..587de52
--- /dev/null
+++ b/lib/eal/include/rte_bitcount.h
@@ -0,0 +1,265 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#ifndef _RTE_BITCOUNT_H_
+#define _RTE_BITCOUNT_H_
+
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef RTE_TOOLCHAIN_MSVC
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz(unsigned int v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clzl(unsigned long v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clzll(unsigned long long v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz(unsigned int v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctzl(unsigned long v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctzll(unsigned long long v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+#else
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz(unsigned int v)
+{
+	return (unsigned int)__builtin_clz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clzl(unsigned long v)
+{
+	return (unsigned int)__builtin_clzl(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clzll(unsigned long v)
+{
+	return (unsigned int)__builtin_clzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz(unsigned int v)
+{
+	return (unsigned int)__builtin_ctz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctzl(unsigned long v)
+{
+	return (unsigned int)__builtin_ctzl(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctzll(unsigned long v)
+{
+	return (unsigned int)__builtin_ctzll(v);
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BITCOUNT_H_ */
+
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v2 2/2] test/bitcount: add bitcount tests
  2022-11-23 23:43 ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
  2022-11-23 23:43   ` [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2022-11-23 23:43   ` Tyler Retzlaff
  2023-01-04 23:46   ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
  2023-01-09 17:36   ` [PATCH v4 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  3 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2022-11-23 23:43 UTC (permalink / raw)
  To: dev; +Cc: Tyler Retzlaff

basic unit test of following functions

    rte_clz
    rte_clzl
    rte_clzll
    rte_ctz
    rte_ctzl
    rte_ctzll

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 app/test/meson.build     |  2 ++
 app/test/test_bitcount.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)
 create mode 100644 app/test/test_bitcount.c

diff --git a/app/test/meson.build b/app/test/meson.build
index f34d19e..d1277bc 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -13,6 +13,7 @@ test_sources = files(
         'test_alarm.c',
         'test_atomic.c',
         'test_barrier.c',
+        'test_bitcount.c',
         'test_bitops.c',
         'test_bitmap.c',
         'test_bpf.c',
@@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
 fast_tests = [
         ['acl_autotest', true, true],
         ['atomic_autotest', false, true],
+        ['bitcount_autotest', true, true],
         ['bitmap_autotest', true, true],
         ['bpf_autotest', true, true],
         ['bpf_convert_autotest', true, true],
diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
new file mode 100644
index 0000000..7b71fdf
--- /dev/null
+++ b/app/test/test_bitcount.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#include <string.h>
+
+#include <rte_bitcount.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
+
+static int
+test_clz(void)
+{
+	unsigned int v = 1;
+	RTE_TEST_ASSERT(rte_clz(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_clzl(void)
+{
+	unsigned long v = 1;
+	RTE_TEST_ASSERT(rte_clzl(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_clzll(void)
+{
+	unsigned long long v = 1;
+	RTE_TEST_ASSERT(rte_clzll(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctz(void)
+{
+	unsigned int v = 2;
+	RTE_TEST_ASSERT(rte_ctz(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctzl(void)
+{
+	unsigned long v = 2;
+	RTE_TEST_ASSERT(rte_ctzl(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctzll(void)
+{
+	unsigned long long v = 2;
+	RTE_TEST_ASSERT(rte_ctzll(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static struct unit_test_suite bitcount_test_suite = {
+	.suite_name = "bitcount autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+		TEST_CASE(test_clz),
+		TEST_CASE(test_clzl),
+		TEST_CASE(test_clzll),
+		TEST_CASE(test_ctz),
+		TEST_CASE(test_ctzl),
+		TEST_CASE(test_ctzll),
+		TEST_CASES_END()
+	}
+};
+
+static int
+test_bitcount(void)
+{
+	return unit_test_suite_runner(&bitcount_test_suite);
+}
+
+REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* RE: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-23 23:43   ` [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2022-11-24 10:17     ` Morten Brørup
  2022-11-28 17:13       ` Tyler Retzlaff
  2023-01-05  7:09     ` Morten Brørup
  1 sibling, 1 reply; 81+ messages in thread
From: Morten Brørup @ 2022-11-24 10:17 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: dev

> From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> Sent: Thursday, 24 November 2022 00.43
> 
> Provide an abstraction for leading and trailing zero bit counting
> functions to hide compiler specific intrinsics and builtins.
> 
> Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> ---

Related functions already exist in lib/eal/include/rte_common.h.

If some functions are missing, it would be good to add them.

Also, it makes sense moving them out of rte_common.h.


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-24 10:17     ` Morten Brørup
@ 2022-11-28 17:13       ` Tyler Retzlaff
  2022-11-28 17:22         ` Morten Brørup
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2022-11-28 17:13 UTC (permalink / raw)
  To: Morten Brørup; +Cc: dev

On Thu, Nov 24, 2022 at 11:17:23AM +0100, Morten Brørup wrote:
> > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > Sent: Thursday, 24 November 2022 00.43
> > 
> > Provide an abstraction for leading and trailing zero bit counting
> > functions to hide compiler specific intrinsics and builtins.
> > 
> > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > ---
> 

let me unpack what is being asked for here.

> Related functions already exist in lib/eal/include/rte_common.h.

i don't understand. are you saying these inline functions duplicate
existing bit counting functionality? if so i'll relocate any you
identify.

> 
> If some functions are missing, it would be good to add them.

the change here is to address a specific family of functions that are
impeding portability of the rte_common.h header and nothing more.

i'm open to having a separate mail thread discussing what other
functions we might want and whether to relocate code out of rte_common.h
since that is likely to be a drawn out discussion it shouldn't be a
blocking dependency of this series.

> 
> Also, it makes sense moving them out of rte_common.h.

thanks!

^ permalink raw reply	[flat|nested] 81+ messages in thread

* RE: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-28 17:13       ` Tyler Retzlaff
@ 2022-11-28 17:22         ` Morten Brørup
  2022-11-28 17:27           ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Morten Brørup @ 2022-11-28 17:22 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: dev

> From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> Sent: Monday, 28 November 2022 18.14
> 
> On Thu, Nov 24, 2022 at 11:17:23AM +0100, Morten Brørup wrote:
> > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > Sent: Thursday, 24 November 2022 00.43
> > >
> > > Provide an abstraction for leading and trailing zero bit counting
> > > functions to hide compiler specific intrinsics and builtins.
> > >
> > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > ---
> >
> 
> let me unpack what is being asked for here.
> 
> > Related functions already exist in lib/eal/include/rte_common.h.
> 
> i don't understand. are you saying these inline functions duplicate
> existing bit counting functionality? if so i'll relocate any you
> identify.

Sorry about not being clear about my intentions with the feedback.

I'm not asking for anything; I only wanted to point at the similar family of functions in rte_common.h, to make sure that you were aware of them.

> 
> >
> > If some functions are missing, it would be good to add them.
> 
> the change here is to address a specific family of functions that are
> impeding portability of the rte_common.h header and nothing more.
> 
> i'm open to having a separate mail thread discussing what other
> functions we might want and whether to relocate code out of
> rte_common.h
> since that is likely to be a drawn out discussion it shouldn't be a
> blocking dependency of this series.

I do not request any new functions; I'll leave it up to you to decide if anything would be good to add.

> 
> >
> > Also, it makes sense moving them out of rte_common.h.
> 
> thanks!

Thank you! Cleaning up is always appreciated.


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-28 17:22         ` Morten Brørup
@ 2022-11-28 17:27           ` Tyler Retzlaff
  2023-01-05  9:04             ` Thomas Monjalon
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2022-11-28 17:27 UTC (permalink / raw)
  To: Morten Brørup; +Cc: dev

On Mon, Nov 28, 2022 at 06:22:10PM +0100, Morten Brørup wrote:
> > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > Sent: Monday, 28 November 2022 18.14
> > 
> > On Thu, Nov 24, 2022 at 11:17:23AM +0100, Morten Brørup wrote:
> > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > Sent: Thursday, 24 November 2022 00.43
> > > >
> > > > Provide an abstraction for leading and trailing zero bit counting
> > > > functions to hide compiler specific intrinsics and builtins.
> > > >
> > > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > > ---
> > >
> > 
> > let me unpack what is being asked for here.
> > 
> > > Related functions already exist in lib/eal/include/rte_common.h.
> > 
> > i don't understand. are you saying these inline functions duplicate
> > existing bit counting functionality? if so i'll relocate any you
> > identify.
> 
> Sorry about not being clear about my intentions with the feedback.
> 
> I'm not asking for anything; I only wanted to point at the similar family of functions in rte_common.h, to make sure that you were aware of them.

oh! not a problem. i'm very keen to catch any mistakes, thought i had
missed something.

> 
> > 
> > >
> > > If some functions are missing, it would be good to add them.
> > 
> > the change here is to address a specific family of functions that are
> > impeding portability of the rte_common.h header and nothing more.
> > 
> > i'm open to having a separate mail thread discussing what other
> > functions we might want and whether to relocate code out of
> > rte_common.h
> > since that is likely to be a drawn out discussion it shouldn't be a
> > blocking dependency of this series.
> 
> I do not request any new functions; I'll leave it up to you to decide if anything would be good to add.
> 
> > 
> > >
> > > Also, it makes sense moving them out of rte_common.h.
> > 
> > thanks!
> 
> Thank you! Cleaning up is always appreciated.

yes, if i can get more rapid approvals there is a lot more in the
pipeline. i'd like gain some momentum if possible.

ty

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 0/2] eal: provide leading and trailing zero bit count
  2022-11-23 23:43 ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
  2022-11-23 23:43   ` [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2022-11-23 23:43   ` [PATCH v2 2/2] test/bitcount: add bitcount tests Tyler Retzlaff
@ 2023-01-04 23:46   ` Tyler Retzlaff
  2023-01-09 17:36   ` [PATCH v4 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  3 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-04 23:46 UTC (permalink / raw)
  To: dev, david.marchand, thomas

hi just adding a few extra folks to the to line to try and get some
reviewer attention since this patch has been sitting here for a while.

the change is fairly straight forward, would just like to get it
cleared.

feedback is appreciated!

thanks

On Wed, Nov 23, 2022 at 03:43:15PM -0800, Tyler Retzlaff wrote:
> Provide leading and trailing zero bit count functions to abstract away
> compiler specific implementations.
> 
> Include basic unit test for new leading/trailing zero bit count functions.
> 
> v2:
>   * use unsigned int instead of unsigned (checkpatches)
>   * match multiple include guard naming convention to rte_common.h
>   * add explicit extern "C" linkage to rte_bitcount.h
>     note: not really needed but checkpatches required
>   * add missing space around '-'
> 
> Tyler Retzlaff (2):
>   eal: provide leading and trailing zero bit count abstraction
>   test/bitcount: add bitcount tests
> 
>  app/test/meson.build           |   2 +
>  app/test/test_bitcount.c       |  92 ++++++++++++++
>  lib/eal/include/meson.build    |   1 +
>  lib/eal/include/rte_bitcount.h | 265 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 360 insertions(+)
>  create mode 100644 app/test/test_bitcount.c
>  create mode 100644 lib/eal/include/rte_bitcount.h
> 
> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 81+ messages in thread

* RE: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-23 23:43   ` [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2022-11-24 10:17     ` Morten Brørup
@ 2023-01-05  7:09     ` Morten Brørup
  2023-01-05  9:01       ` Thomas Monjalon
  2023-04-04 21:23       ` Tyler Retzlaff
  1 sibling, 2 replies; 81+ messages in thread
From: Morten Brørup @ 2023-01-05  7:09 UTC (permalink / raw)
  To: Tyler Retzlaff, dev; +Cc: david.marchand, thomas

> From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> Sent: Thursday, 24 November 2022 00.43
> 
> Provide an abstraction for leading and trailing zero bit counting
> functions to hide compiler specific intrinsics and builtins.
> 
> Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> ---
>  lib/eal/include/meson.build    |   1 +
>  lib/eal/include/rte_bitcount.h | 265
> +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 266 insertions(+)
>  create mode 100644 lib/eal/include/rte_bitcount.h
> 
> diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
> index cfcd40a..8ff1d65 100644
> --- a/lib/eal/include/meson.build
> +++ b/lib/eal/include/meson.build
> @@ -5,6 +5,7 @@ includes += include_directories('.')
> 
>  headers += files(
>          'rte_alarm.h',
> +        'rte_bitcount.h',
>          'rte_bitmap.h',
>          'rte_bitops.h',
>          'rte_branch_prediction.h',
> diff --git a/lib/eal/include/rte_bitcount.h
> b/lib/eal/include/rte_bitcount.h
> new file mode 100644
> index 0000000..587de52
> --- /dev/null
> +++ b/lib/eal/include/rte_bitcount.h
> @@ -0,0 +1,265 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (C) 2022 Microsoft Corporation
> + */
> +
> +#ifndef _RTE_BITCOUNT_H_
> +#define _RTE_BITCOUNT_H_
> +
> +#include <rte_compat.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#ifdef RTE_TOOLCHAIN_MSVC
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_clz(unsigned int v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanReverse(&rv, v);
> +
> +	return (unsigned int)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_clzl(unsigned long v)

Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.

E.g.: rte_clz32(uint32_t v)

> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanReverse(&rv, v);
> +
> +	return (unsigned int)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_clzll(unsigned long long v)

Same comment as above: e.g. rte_clz64(uint64_t v)


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05  7:09     ` Morten Brørup
@ 2023-01-05  9:01       ` Thomas Monjalon
  2023-01-05 17:21         ` Tyler Retzlaff
  2023-04-04 21:23       ` Tyler Retzlaff
  1 sibling, 1 reply; 81+ messages in thread
From: Thomas Monjalon @ 2023-01-05  9:01 UTC (permalink / raw)
  To: Tyler Retzlaff, Morten Brørup; +Cc: dev, david.marchand

05/01/2023 08:09, Morten Brørup:
> > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > notice
> > + *
> > + * Get the count of leading 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of leading zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_clzl(unsigned long v)
> 
> Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> 
> E.g.: rte_clz32(uint32_t v)

I agree on using numbers.




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-28 17:27           ` Tyler Retzlaff
@ 2023-01-05  9:04             ` Thomas Monjalon
  2023-01-05 17:23               ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Thomas Monjalon @ 2023-01-05  9:04 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: Morten Brørup, dev, david.marchand

28/11/2022 18:27, Tyler Retzlaff:
> On Mon, Nov 28, 2022 at 06:22:10PM +0100, Morten Brørup wrote:
> > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > Sent: Monday, 28 November 2022 18.14
> > > 
> > > On Thu, Nov 24, 2022 at 11:17:23AM +0100, Morten Brørup wrote:
> > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > Sent: Thursday, 24 November 2022 00.43
> > > > >
> > > > > Provide an abstraction for leading and trailing zero bit counting
> > > > > functions to hide compiler specific intrinsics and builtins.
> > > > >
> > > > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > 
> > > let me unpack what is being asked for here.
> > > 
> > > > Related functions already exist in lib/eal/include/rte_common.h.
> > > 
> > > i don't understand. are you saying these inline functions duplicate
> > > existing bit counting functionality? if so i'll relocate any you
> > > identify.
> > 
> > Sorry about not being clear about my intentions with the feedback.
> > 
> > I'm not asking for anything; I only wanted to point at the similar family of functions in rte_common.h, to make sure that you were aware of them.
> 
> oh! not a problem. i'm very keen to catch any mistakes, thought i had
> missed something.

I think we should move all bit-related functions together.
Please could you add another patch to your series
moving "ms1b"/"bsf"/"fls" functions in this file?




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05  9:01       ` Thomas Monjalon
@ 2023-01-05 17:21         ` Tyler Retzlaff
  2023-01-06  0:32           ` Stephen Hemminger
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-05 17:21 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Morten Brørup, dev, david.marchand

On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> 05/01/2023 08:09, Morten Brørup:
> > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > +/**
> > > + * @warning
> > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > notice
> > > + *
> > > + * Get the count of leading 0-bits in v.
> > > + *
> > > + * @param v
> > > + *   The value.
> > > + * @return
> > > + *   The count of leading zero bits.
> > > + */
> > > +__rte_experimental
> > > +static inline unsigned int
> > > +rte_clzl(unsigned long v)
> > 
> > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > 
> > E.g.: rte_clz32(uint32_t v)
> 
> I agree on using numbers.
> 

love the idea, fewer functions too.

though it is a shame we cannot adopt C11 standard because we could just
do away with the bit suffixes entirely.

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05  9:04             ` Thomas Monjalon
@ 2023-01-05 17:23               ` Tyler Retzlaff
  2023-01-05 17:27                 ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-05 17:23 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Morten Brørup, dev, david.marchand

On Thu, Jan 05, 2023 at 10:04:46AM +0100, Thomas Monjalon wrote:
> 28/11/2022 18:27, Tyler Retzlaff:
> > On Mon, Nov 28, 2022 at 06:22:10PM +0100, Morten Brørup wrote:
> > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > Sent: Monday, 28 November 2022 18.14
> > > > 
> > > > On Thu, Nov 24, 2022 at 11:17:23AM +0100, Morten Brørup wrote:
> > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > Sent: Thursday, 24 November 2022 00.43
> > > > > >
> > > > > > Provide an abstraction for leading and trailing zero bit counting
> > > > > > functions to hide compiler specific intrinsics and builtins.
> > > > > >
> > > > > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > > 
> > > > let me unpack what is being asked for here.
> > > > 
> > > > > Related functions already exist in lib/eal/include/rte_common.h.
> > > > 
> > > > i don't understand. are you saying these inline functions duplicate
> > > > existing bit counting functionality? if so i'll relocate any you
> > > > identify.
> > > 
> > > Sorry about not being clear about my intentions with the feedback.
> > > 
> > > I'm not asking for anything; I only wanted to point at the similar family of functions in rte_common.h, to make sure that you were aware of them.
> > 
> > oh! not a problem. i'm very keen to catch any mistakes, thought i had
> > missed something.
> 
> I think we should move all bit-related functions together.
> Please could you add another patch to your series
> moving "ms1b"/"bsf"/"fls" functions in this file?
> 
> 

okay, so there is already a rte_bitops.h. i guess everything should go
there including the leading/trailing count functions instead of adding a
new header.

i'll introduce a new patch to the series that gathers the existing
functions into rte_bitops.h and place the new functions there too.

thanks

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05 17:23               ` Tyler Retzlaff
@ 2023-01-05 17:27                 ` Tyler Retzlaff
  2023-01-05 20:57                   ` Tyler Retzlaff
  2023-01-06 10:00                   ` Thomas Monjalon
  0 siblings, 2 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-05 17:27 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Morten Brørup, dev, david.marchand

On Thu, Jan 05, 2023 at 09:23:49AM -0800, Tyler Retzlaff wrote:
> On Thu, Jan 05, 2023 at 10:04:46AM +0100, Thomas Monjalon wrote:
> > 28/11/2022 18:27, Tyler Retzlaff:
> > > On Mon, Nov 28, 2022 at 06:22:10PM +0100, Morten Brørup wrote:
> > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > Sent: Monday, 28 November 2022 18.14
> > > > > 
> > > > > On Thu, Nov 24, 2022 at 11:17:23AM +0100, Morten Brørup wrote:
> > > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > > Sent: Thursday, 24 November 2022 00.43
> > > > > > >
> > > > > > > Provide an abstraction for leading and trailing zero bit counting
> > > > > > > functions to hide compiler specific intrinsics and builtins.
> > > > > > >
> > > > > > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > > > 
> > > > > let me unpack what is being asked for here.
> > > > > 
> > > > > > Related functions already exist in lib/eal/include/rte_common.h.
> > > > > 
> > > > > i don't understand. are you saying these inline functions duplicate
> > > > > existing bit counting functionality? if so i'll relocate any you
> > > > > identify.
> > > > 
> > > > Sorry about not being clear about my intentions with the feedback.
> > > > 
> > > > I'm not asking for anything; I only wanted to point at the similar family of functions in rte_common.h, to make sure that you were aware of them.
> > > 
> > > oh! not a problem. i'm very keen to catch any mistakes, thought i had
> > > missed something.
> > 
> > I think we should move all bit-related functions together.
> > Please could you add another patch to your series
> > moving "ms1b"/"bsf"/"fls" functions in this file?
> > 
> > 
> 
> okay, so there is already a rte_bitops.h. i guess everything should go
> there including the leading/trailing count functions instead of adding a
> new header.
> 
> i'll introduce a new patch to the series that gathers the existing
> functions into rte_bitops.h and place the new functions there too.
> 
> thanks

just as a further follow up, you do understand that this is technically
an api break?

moving functions from rte_common.h to rte_bitops.h will make translation
units that included only rte_common.h but used these functions will
fail to compile without being updated to include rte_bitops.h.

anyway, i'll submit v3 with this change anyway.

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05 17:27                 ` Tyler Retzlaff
@ 2023-01-05 20:57                   ` Tyler Retzlaff
  2023-01-05 21:34                     ` Morten Brørup
  2023-01-06 10:00                   ` Thomas Monjalon
  1 sibling, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-05 20:57 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Morten Brørup, dev, david.marchand

On Thu, Jan 05, 2023 at 09:27:12AM -0800, Tyler Retzlaff wrote:
> On Thu, Jan 05, 2023 at 09:23:49AM -0800, Tyler Retzlaff wrote:
> > > > oh! not a problem. i'm very keen to catch any mistakes, thought i had
> > > > missed something.
> > > 
> > > I think we should move all bit-related functions together.
> > > Please could you add another patch to your series
> > > moving "ms1b"/"bsf"/"fls" functions in this file?
> > > 
> > > 
> > 
> > okay, so there is already a rte_bitops.h. i guess everything should go
> > there including the leading/trailing count functions instead of adding a
> > new header.
> > 
> > i'll introduce a new patch to the series that gathers the existing
> > functions into rte_bitops.h and place the new functions there too.
> > 
> > thanks
> 
> just as a further follow up, you do understand that this is technically
> an api break?
> 
> moving functions from rte_common.h to rte_bitops.h will make translation
> units that included only rte_common.h but used these functions will
> fail to compile without being updated to include rte_bitops.h.
> 
> anyway, i'll submit v3 with this change anyway.

so when attempting to do this it became immediately obvious that moving
just the bit op functions out is going to create a circular dependency
between rte_common.h, rte_bitops.h

once the bit ops are moved out of common there are still other inline
functions that remain in comman that require bringing bitops back in,
but bitops depends on common.

my compromise will be to break log2 and pow2 inline functions into their
own files to break the cycle (common no longer depends on bitops). i'll
submit patches for this but it ends up touching a lot more of the
tree to add back includes for log/pow inline use.

alternatively i can just not move the remaining bit manipulation
functions, let me know which is preferred.

thanks

^ permalink raw reply	[flat|nested] 81+ messages in thread

* RE: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05 20:57                   ` Tyler Retzlaff
@ 2023-01-05 21:34                     ` Morten Brørup
  2023-01-05 22:06                       ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Morten Brørup @ 2023-01-05 21:34 UTC (permalink / raw)
  To: Tyler Retzlaff, Thomas Monjalon; +Cc: dev, david.marchand

> From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> Sent: Thursday, 5 January 2023 21.58
> 
> On Thu, Jan 05, 2023 at 09:27:12AM -0800, Tyler Retzlaff wrote:
> > On Thu, Jan 05, 2023 at 09:23:49AM -0800, Tyler Retzlaff wrote:
> > > > > oh! not a problem. i'm very keen to catch any mistakes, thought
> i had
> > > > > missed something.
> > > >
> > > > I think we should move all bit-related functions together.
> > > > Please could you add another patch to your series
> > > > moving "ms1b"/"bsf"/"fls" functions in this file?
> > > >
> > > >
> > >
> > > okay, so there is already a rte_bitops.h. i guess everything should
> go
> > > there including the leading/trailing count functions instead of
> adding a
> > > new header.
> > >
> > > i'll introduce a new patch to the series that gathers the existing
> > > functions into rte_bitops.h and place the new functions there too.
> > >
> > > thanks
> >
> > just as a further follow up, you do understand that this is
> technically
> > an api break?
> >
> > moving functions from rte_common.h to rte_bitops.h will make
> translation
> > units that included only rte_common.h but used these functions will
> > fail to compile without being updated to include rte_bitops.h.
> >
> > anyway, i'll submit v3 with this change anyway.
> 
> so when attempting to do this it became immediately obvious that moving
> just the bit op functions out is going to create a circular dependency
> between rte_common.h, rte_bitops.h
> 
> once the bit ops are moved out of common there are still other inline
> functions that remain in comman that require bringing bitops back in,
> but bitops depends on common.
> 
> my compromise will be to break log2 and pow2 inline functions into
> their
> own files to break the cycle (common no longer depends on bitops). i'll
> submit patches for this but it ends up touching a lot more of the
> tree to add back includes for log/pow inline use.
> 
> alternatively i can just not move the remaining bit manipulation
> functions, let me know which is preferred.

It seems that no perfect solution exists, so we will have to live with a compromise. Here is another proposal for a compromise, for yours and Thomas's consideration:

I noticed that rte_bitops.h is mainly for setting/getting bits, used for accessing hardware.

Your functions are mathematical functions, and so are the similar functions in rte_common.h (which is why it makes sense to keep them together with yours). If we cannot clean up rte_common.h by moving them out, perhaps we should accept the current situation (until we find a way to move them out) and just add your mathematical functions where the existing mathematical functions reside, i.e. in rte_common.h.

This proposal only makes the existing mess slightly larger; it doesn't create a new kind of mess.

-Morten


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05 21:34                     ` Morten Brørup
@ 2023-01-05 22:06                       ` Tyler Retzlaff
  2023-01-05 23:10                         ` Morten Brørup
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-05 22:06 UTC (permalink / raw)
  To: Morten Brørup; +Cc: Thomas Monjalon, dev, david.marchand

On Thu, Jan 05, 2023 at 10:34:55PM +0100, Morten Brørup wrote:
> > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > Sent: Thursday, 5 January 2023 21.58
> > 
> > On Thu, Jan 05, 2023 at 09:27:12AM -0800, Tyler Retzlaff wrote:
> > > On Thu, Jan 05, 2023 at 09:23:49AM -0800, Tyler Retzlaff wrote:
> > > > > > oh! not a problem. i'm very keen to catch any mistakes, thought
> > i had
> > > > > > missed something.
> > > > >
> > > > > I think we should move all bit-related functions together.
> > > > > Please could you add another patch to your series
> > > > > moving "ms1b"/"bsf"/"fls" functions in this file?
> > > > >
> > > > >
> > > >
> > > > okay, so there is already a rte_bitops.h. i guess everything should
> > go
> > > > there including the leading/trailing count functions instead of
> > adding a
> > > > new header.
> > > >
> > > > i'll introduce a new patch to the series that gathers the existing
> > > > functions into rte_bitops.h and place the new functions there too.
> > > >
> > > > thanks
> > >
> > > just as a further follow up, you do understand that this is
> > technically
> > > an api break?
> > >
> > > moving functions from rte_common.h to rte_bitops.h will make
> > translation
> > > units that included only rte_common.h but used these functions will
> > > fail to compile without being updated to include rte_bitops.h.
> > >
> > > anyway, i'll submit v3 with this change anyway.
> > 
> > so when attempting to do this it became immediately obvious that moving
> > just the bit op functions out is going to create a circular dependency
> > between rte_common.h, rte_bitops.h
> > 
> > once the bit ops are moved out of common there are still other inline
> > functions that remain in comman that require bringing bitops back in,
> > but bitops depends on common.
> > 
> > my compromise will be to break log2 and pow2 inline functions into
> > their
> > own files to break the cycle (common no longer depends on bitops). i'll
> > submit patches for this but it ends up touching a lot more of the
> > tree to add back includes for log/pow inline use.
> > 
> > alternatively i can just not move the remaining bit manipulation
> > functions, let me know which is preferred.
> 
> It seems that no perfect solution exists, so we will have to live with a compromise. Here is another proposal for a compromise, for yours and Thomas's consideration:
> 
> I noticed that rte_bitops.h is mainly for setting/getting bits, used for accessing hardware.
> 
> Your functions are mathematical functions, and so are the similar functions in rte_common.h (which is why it makes sense to keep them together with yours). If we cannot clean up rte_common.h by moving them out, perhaps we should accept the current situation (until we find a way to move them out) and just add your mathematical functions where the existing mathematical functions reside, i.e. in rte_common.h.
> 
> This proposal only makes the existing mess slightly larger; it doesn't create a new kind of mess.

so i fudged around a bit to see if i could get a happy medium. i ended
up with this.

remove include of rte_debug.h from rte_bitops.h

  * had to remove the RTE_ASSERT from existing rte_bitops.h functions
  * this breaks a good piece of the cycle debug -> log -> common -> bitops -> debug
  * deal breaker? i don't think it was right that we were getting all
    of log, common just for using bitops anyway.

move pow2 functions from rte_common.h -> rte_pow2ops.h
  * new header includes rte_bitops.h

move log2 functions from rte_common.h -> rte_log2ops.h
  * new header includes rte_bitops.h, rte_pow2ops.h

include rte_bitops.h, rte_pow2ops.h and rte_log2ops.h back into
rte_common.h

  * this is done to reduce the impact of compatibility break by
    continuing to expose the pow2/log2/bitops via rte_common.h

so we end up with 3 standalone headers, where the whole tree builds
without having to add a pile of includes for the new headers. we can
later deprecate the exposure of the inline functions when including
rte_common.h

  * one caveat is that there was some contamination coming in via the
    removed rte_debug.h where rte_bitops.h was used. so technically
    a break of api too.

objections?

if this is no good i'll just fold my new functions into rte_common.h and
leave the mess for the next person, though i am trying not to do that.

thanks for the discussion.

^ permalink raw reply	[flat|nested] 81+ messages in thread

* RE: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05 22:06                       ` Tyler Retzlaff
@ 2023-01-05 23:10                         ` Morten Brørup
  2023-01-06  1:04                           ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Morten Brørup @ 2023-01-05 23:10 UTC (permalink / raw)
  To: Tyler Retzlaff, Thomas Monjalon; +Cc: dev, david.marchand

> From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> Sent: Thursday, 5 January 2023 23.06
> 
> On Thu, Jan 05, 2023 at 10:34:55PM +0100, Morten Brørup wrote:
> > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > Sent: Thursday, 5 January 2023 21.58
> > >
> > > On Thu, Jan 05, 2023 at 09:27:12AM -0800, Tyler Retzlaff wrote:
> > > > On Thu, Jan 05, 2023 at 09:23:49AM -0800, Tyler Retzlaff wrote:
> > > > > > > oh! not a problem. i'm very keen to catch any mistakes,
> thought
> > > i had
> > > > > > > missed something.
> > > > > >
> > > > > > I think we should move all bit-related functions together.
> > > > > > Please could you add another patch to your series
> > > > > > moving "ms1b"/"bsf"/"fls" functions in this file?
> > > > > >
> > > > > >
> > > > >
> > > > > okay, so there is already a rte_bitops.h. i guess everything
> should
> > > go
> > > > > there including the leading/trailing count functions instead of
> > > adding a
> > > > > new header.
> > > > >
> > > > > i'll introduce a new patch to the series that gathers the
> existing
> > > > > functions into rte_bitops.h and place the new functions there
> too.
> > > > >
> > > > > thanks
> > > >
> > > > just as a further follow up, you do understand that this is
> > > technically
> > > > an api break?
> > > >
> > > > moving functions from rte_common.h to rte_bitops.h will make
> > > translation
> > > > units that included only rte_common.h but used these functions
> will
> > > > fail to compile without being updated to include rte_bitops.h.
> > > >
> > > > anyway, i'll submit v3 with this change anyway.
> > >
> > > so when attempting to do this it became immediately obvious that
> moving
> > > just the bit op functions out is going to create a circular
> dependency
> > > between rte_common.h, rte_bitops.h
> > >
> > > once the bit ops are moved out of common there are still other
> inline
> > > functions that remain in comman that require bringing bitops back
> in,
> > > but bitops depends on common.
> > >
> > > my compromise will be to break log2 and pow2 inline functions into
> > > their
> > > own files to break the cycle (common no longer depends on bitops).
> i'll
> > > submit patches for this but it ends up touching a lot more of the
> > > tree to add back includes for log/pow inline use.
> > >
> > > alternatively i can just not move the remaining bit manipulation
> > > functions, let me know which is preferred.
> >
> > It seems that no perfect solution exists, so we will have to live
> with a compromise. Here is another proposal for a compromise, for yours
> and Thomas's consideration:
> >
> > I noticed that rte_bitops.h is mainly for setting/getting bits, used
> for accessing hardware.
> >
> > Your functions are mathematical functions, and so are the similar
> functions in rte_common.h (which is why it makes sense to keep them
> together with yours). If we cannot clean up rte_common.h by moving them
> out, perhaps we should accept the current situation (until we find a
> way to move them out) and just add your mathematical functions where
> the existing mathematical functions reside, i.e. in rte_common.h.
> >
> > This proposal only makes the existing mess slightly larger; it
> doesn't create a new kind of mess.
> 
> so i fudged around a bit to see if i could get a happy medium. i ended
> up with this.
> 
> remove include of rte_debug.h from rte_bitops.h
> 
>   * had to remove the RTE_ASSERT from existing rte_bitops.h functions
>   * this breaks a good piece of the cycle debug -> log -> common ->
> bitops -> debug
>   * deal breaker? i don't think it was right that we were getting all
>     of log, common just for using bitops anyway.
> 
> move pow2 functions from rte_common.h -> rte_pow2ops.h
>   * new header includes rte_bitops.h
> 
> move log2 functions from rte_common.h -> rte_log2ops.h
>   * new header includes rte_bitops.h, rte_pow2ops.h
> 
> include rte_bitops.h, rte_pow2ops.h and rte_log2ops.h back into
> rte_common.h
> 
>   * this is done to reduce the impact of compatibility break by
>     continuing to expose the pow2/log2/bitops via rte_common.h
> 
> so we end up with 3 standalone headers, where the whole tree builds
> without having to add a pile of includes for the new headers. we can
> later deprecate the exposure of the inline functions when including
> rte_common.h
> 
>   * one caveat is that there was some contamination coming in via the
>     removed rte_debug.h where rte_bitops.h was used. so technically
>     a break of api too.
> 
> objections?
> 
> if this is no good i'll just fold my new functions into rte_common.h
> and
> leave the mess for the next person, though i am trying not to do that.
> 
> thanks for the discussion.

Here's some long term thinking: EAL has grown into a trashcan where too much is thrown in. It should only be a thin shim to abstract the underlying hardware and O/S environment. A step in that direction could be splitting the current EAL into a true EAL and a Utils library. Not now, but perhaps some day in a rosy future.

Your proposal effectively makes rte_common.h even bigger by including rte_bitops.h (which was intended for accessing hardware). I am not sure it is a step in the right direction. On the other hand, introducing yet another header file for bit-mathematical functions is probably worse than adding them to rte_bitops.h.

I can't come up with something good myself, but I lean towards simply adding your functions to rte_common.h and live with the existing mess. If you think your proposal is better, I will not object. I'm only voicing my thoughts.

@Thomas may have another perspective on the matter.

Thanks for all the work you put into this.

-Morten


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05 17:21         ` Tyler Retzlaff
@ 2023-01-06  0:32           ` Stephen Hemminger
  2023-01-06 11:48             ` Bruce Richardson
  0 siblings, 1 reply; 81+ messages in thread
From: Stephen Hemminger @ 2023-01-06  0:32 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: Thomas Monjalon, Morten Brørup, dev, david.marchand

On Thu, 5 Jan 2023 09:21:18 -0800
Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:

> On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> > 05/01/2023 08:09, Morten Brørup:  
> > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > +/**
> > > > + * @warning
> > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > notice
> > > > + *
> > > > + * Get the count of leading 0-bits in v.
> > > > + *
> > > > + * @param v
> > > > + *   The value.
> > > > + * @return
> > > > + *   The count of leading zero bits.
> > > > + */
> > > > +__rte_experimental
> > > > +static inline unsigned int
> > > > +rte_clzl(unsigned long v)  
> > > 
> > > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > > 
> > > E.g.: rte_clz32(uint32_t v)  
> > 
> > I agree on using numbers.
> >   
> 
> love the idea, fewer functions too.
> 
> though it is a shame we cannot adopt C11 standard because we could just
> do away with the bit suffixes entirely.

We could but the project needs to support older RHEL releases
which have older tool sets. Though probably this is moot point given
how much meson seems to change.

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05 23:10                         ` Morten Brørup
@ 2023-01-06  1:04                           ` Tyler Retzlaff
  2023-01-06 10:09                             ` Thomas Monjalon
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-06  1:04 UTC (permalink / raw)
  To: Morten Brørup; +Cc: Thomas Monjalon, dev, david.marchand

On Fri, Jan 06, 2023 at 12:10:45AM +0100, Morten Brørup wrote:
> > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > Sent: Thursday, 5 January 2023 23.06
> > 
> > doesn't create a new kind of mess.
> > 
> > so i fudged around a bit to see if i could get a happy medium. i ended
> > up with this.
> > 
> > remove include of rte_debug.h from rte_bitops.h
> > 
> >   * had to remove the RTE_ASSERT from existing rte_bitops.h functions
> >   * this breaks a good piece of the cycle debug -> log -> common ->
> > bitops -> debug
> >   * deal breaker? i don't think it was right that we were getting all
> >     of log, common just for using bitops anyway.
> > 
> > move pow2 functions from rte_common.h -> rte_pow2ops.h
> >   * new header includes rte_bitops.h
> > 
> > move log2 functions from rte_common.h -> rte_log2ops.h
> >   * new header includes rte_bitops.h, rte_pow2ops.h
> > 
> > include rte_bitops.h, rte_pow2ops.h and rte_log2ops.h back into
> > rte_common.h
> > 
> >   * this is done to reduce the impact of compatibility break by
> >     continuing to expose the pow2/log2/bitops via rte_common.h
> > 
> > so we end up with 3 standalone headers, where the whole tree builds
> > without having to add a pile of includes for the new headers. we can
> > later deprecate the exposure of the inline functions when including
> > rte_common.h
> > 
> >   * one caveat is that there was some contamination coming in via the
> >     removed rte_debug.h where rte_bitops.h was used. so technically
> >     a break of api too.
> > 
> > objections?
> > 
> > if this is no good i'll just fold my new functions into rte_common.h
> > and
> > leave the mess for the next person, though i am trying not to do that.
> > 
> > thanks for the discussion.
> 
> Here's some long term thinking: EAL has grown into a trashcan where too much is thrown in. It should only be a thin shim to abstract the underlying hardware and O/S environment. A step in that direction could be splitting the current EAL into a true EAL and a Utils library. Not now, but perhaps some day in a rosy future.
> 
> Your proposal effectively makes rte_common.h even bigger by including rte_bitops.h (which was intended for accessing hardware). I am not sure it is a step in the right direction. On the other hand, introducing yet another header file for bit-mathematical functions is probably worse than adding them to rte_bitops.h.
> 
> I can't come up with something good myself, but I lean towards simply adding your functions to rte_common.h and live with the existing mess. If you think your proposal is better, I will not object. I'm only voicing my thoughts.

it's hard when we are starting with something monolithic and trying to
split it. you always end up with these iterative transitions toward what
you want because you have to keep some kind of compat.

> 
> @Thomas may have another perspective on the matter.

Thomas any last word after this back and forth?  This change isn't
necessarily blocking me but is a distraction i'd like to finish/offload.
> 
> Thanks for all the work you put into this.

np, it is somewhat out of necessity since i need this stuff to be
portable.  but having it move in the right direction at the same time is
a benefit for anyone who comes later.

ty

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05 17:27                 ` Tyler Retzlaff
  2023-01-05 20:57                   ` Tyler Retzlaff
@ 2023-01-06 10:00                   ` Thomas Monjalon
  1 sibling, 0 replies; 81+ messages in thread
From: Thomas Monjalon @ 2023-01-06 10:00 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: Morten Brørup, dev, david.marchand

05/01/2023 18:27, Tyler Retzlaff:
> On Thu, Jan 05, 2023 at 09:23:49AM -0800, Tyler Retzlaff wrote:
> > On Thu, Jan 05, 2023 at 10:04:46AM +0100, Thomas Monjalon wrote:
> > > 28/11/2022 18:27, Tyler Retzlaff:
> > > > On Mon, Nov 28, 2022 at 06:22:10PM +0100, Morten Brørup wrote:
> > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > Sent: Monday, 28 November 2022 18.14
> > > > > > 
> > > > > > On Thu, Nov 24, 2022 at 11:17:23AM +0100, Morten Brørup wrote:
> > > > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > > > Sent: Thursday, 24 November 2022 00.43
> > > > > > > >
> > > > > > > > Provide an abstraction for leading and trailing zero bit counting
> > > > > > > > functions to hide compiler specific intrinsics and builtins.
> > > > > > > >
> > > > > > > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > > > > 
> > > > > > let me unpack what is being asked for here.
> > > > > > 
> > > > > > > Related functions already exist in lib/eal/include/rte_common.h.
> > > > > > 
> > > > > > i don't understand. are you saying these inline functions duplicate
> > > > > > existing bit counting functionality? if so i'll relocate any you
> > > > > > identify.
> > > > > 
> > > > > Sorry about not being clear about my intentions with the feedback.
> > > > > 
> > > > > I'm not asking for anything; I only wanted to point at the similar family of functions in rte_common.h, to make sure that you were aware of them.
> > > > 
> > > > oh! not a problem. i'm very keen to catch any mistakes, thought i had
> > > > missed something.
> > > 
> > > I think we should move all bit-related functions together.
> > > Please could you add another patch to your series
> > > moving "ms1b"/"bsf"/"fls" functions in this file?
> > > 
> > > 
> > 
> > okay, so there is already a rte_bitops.h. i guess everything should go
> > there including the leading/trailing count functions instead of adding a
> > new header.

Yes good idea to gather all in rte_bitops.h.

> > i'll introduce a new patch to the series that gathers the existing
> > functions into rte_bitops.h and place the new functions there too.
> > 
> > thanks
> 
> just as a further follow up, you do understand that this is technically
> an api break?

Yes

> moving functions from rte_common.h to rte_bitops.h will make translation
> units that included only rte_common.h but used these functions will
> fail to compile without being updated to include rte_bitops.h.

These functions are not used a lot, it is a "small" API break.



^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06  1:04                           ` Tyler Retzlaff
@ 2023-01-06 10:09                             ` Thomas Monjalon
  0 siblings, 0 replies; 81+ messages in thread
From: Thomas Monjalon @ 2023-01-06 10:09 UTC (permalink / raw)
  To: Morten Brørup, Tyler Retzlaff; +Cc: dev, david.marchand

06/01/2023 02:04, Tyler Retzlaff:
> On Fri, Jan 06, 2023 at 12:10:45AM +0100, Morten Brørup wrote:
> > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > Sent: Thursday, 5 January 2023 23.06
> > > 
> > > doesn't create a new kind of mess.
> > > 
> > > so i fudged around a bit to see if i could get a happy medium. i ended
> > > up with this.
> > > 
> > > remove include of rte_debug.h from rte_bitops.h
> > > 
> > >   * had to remove the RTE_ASSERT from existing rte_bitops.h functions
> > >   * this breaks a good piece of the cycle debug -> log -> common ->
> > > bitops -> debug
> > >   * deal breaker? i don't think it was right that we were getting all
> > >     of log, common just for using bitops anyway.
> > > 
> > > move pow2 functions from rte_common.h -> rte_pow2ops.h
> > >   * new header includes rte_bitops.h
> > > 
> > > move log2 functions from rte_common.h -> rte_log2ops.h
> > >   * new header includes rte_bitops.h, rte_pow2ops.h
> > > 
> > > include rte_bitops.h, rte_pow2ops.h and rte_log2ops.h back into
> > > rte_common.h
> > > 
> > >   * this is done to reduce the impact of compatibility break by
> > >     continuing to expose the pow2/log2/bitops via rte_common.h
> > > 
> > > so we end up with 3 standalone headers, where the whole tree builds
> > > without having to add a pile of includes for the new headers. we can
> > > later deprecate the exposure of the inline functions when including
> > > rte_common.h
> > > 
> > >   * one caveat is that there was some contamination coming in via the
> > >     removed rte_debug.h where rte_bitops.h was used. so technically
> > >     a break of api too.
> > > 
> > > objections?
> > > 
> > > if this is no good i'll just fold my new functions into rte_common.h
> > > and
> > > leave the mess for the next person, though i am trying not to do that.
> > > 
> > > thanks for the discussion.
> > 
> > Here's some long term thinking: EAL has grown into a trashcan where too much is thrown in. It should only be a thin shim to abstract the underlying hardware and O/S environment. A step in that direction could be splitting the current EAL into a true EAL and a Utils library. Not now, but perhaps some day in a rosy future.
> > 
> > Your proposal effectively makes rte_common.h even bigger by including rte_bitops.h (which was intended for accessing hardware). I am not sure it is a step in the right direction. On the other hand, introducing yet another header file for bit-mathematical functions is probably worse than adding them to rte_bitops.h.
> > 
> > I can't come up with something good myself, but I lean towards simply adding your functions to rte_common.h and live with the existing mess. If you think your proposal is better, I will not object. I'm only voicing my thoughts.
> 
> it's hard when we are starting with something monolithic and trying to
> split it. you always end up with these iterative transitions toward what
> you want because you have to keep some kind of compat.
> 
> > 
> > @Thomas may have another perspective on the matter.
> 
> Thomas any last word after this back and forth?  This change isn't
> necessarily blocking me but is a distraction i'd like to finish/offload.

I think it is better to move all in rte_bitops.h
rte_common must have almost zero dependency.
If log2 and pow2 are based on bitops operations, it is not a bad fit for rte_bitops.h.




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06  0:32           ` Stephen Hemminger
@ 2023-01-06 11:48             ` Bruce Richardson
  2023-01-06 12:41               ` Morten Brørup
  2023-01-06 18:47               ` Tyler Retzlaff
  0 siblings, 2 replies; 81+ messages in thread
From: Bruce Richardson @ 2023-01-06 11:48 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Tyler Retzlaff, Thomas Monjalon, Morten Brørup, dev, david.marchand

On Thu, Jan 05, 2023 at 04:32:40PM -0800, Stephen Hemminger wrote:
> On Thu, 5 Jan 2023 09:21:18 -0800
> Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:
> 
> > On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> > > 05/01/2023 08:09, Morten Brørup:  
> > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > +/**
> > > > > + * @warning
> > > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > > notice
> > > > > + *
> > > > > + * Get the count of leading 0-bits in v.
> > > > > + *
> > > > > + * @param v
> > > > > + *   The value.
> > > > > + * @return
> > > > > + *   The count of leading zero bits.
> > > > > + */
> > > > > +__rte_experimental
> > > > > +static inline unsigned int
> > > > > +rte_clzl(unsigned long v)  
> > > > 
> > > > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > > > 
> > > > E.g.: rte_clz32(uint32_t v)  
> > > 
> > > I agree on using numbers.
> > >   
> > 
> > love the idea, fewer functions too.
> > 
> > though it is a shame we cannot adopt C11 standard because we could just
> > do away with the bit suffixes entirely.
> 
> We could but the project needs to support older RHEL releases
> which have older tool sets. Though probably this is moot point given
> how much meson seems to change.

True, though meson tends to be a bit easier to update than GCC on a system
- no "pip3 install --upgrade gcc", sadly :-)

If we can't go all the way to C11 support, how about at least going to C99
support? As far as I know DPDK has never updated its minimum C-standard
version, and it might be a good idea to start the process of doing so, even
if it is a baby step.

/Bruce

^ permalink raw reply	[flat|nested] 81+ messages in thread

* RE: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06 11:48             ` Bruce Richardson
@ 2023-01-06 12:41               ` Morten Brørup
  2023-01-06 13:40                 ` Thomas Monjalon
  2023-01-06 18:47               ` Tyler Retzlaff
  1 sibling, 1 reply; 81+ messages in thread
From: Morten Brørup @ 2023-01-06 12:41 UTC (permalink / raw)
  To: Bruce Richardson, Stephen Hemminger, david.marchand
  Cc: Tyler Retzlaff, Thomas Monjalon, dev

> From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> Sent: Friday, 6 January 2023 12.48
> 
> On Thu, Jan 05, 2023 at 04:32:40PM -0800, Stephen Hemminger wrote:
> > On Thu, 5 Jan 2023 09:21:18 -0800
> > Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:
> >
> > > On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> > > > 05/01/2023 08:09, Morten Brørup:
> > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > +/**
> > > > > > + * @warning
> > > > > > + * @b EXPERIMENTAL: this API may change, or be removed,
> without prior
> > > > > > notice
> > > > > > + *
> > > > > > + * Get the count of leading 0-bits in v.
> > > > > > + *
> > > > > > + * @param v
> > > > > > + *   The value.
> > > > > > + * @return
> > > > > > + *   The count of leading zero bits.
> > > > > > + */
> > > > > > +__rte_experimental
> > > > > > +static inline unsigned int
> > > > > > +rte_clzl(unsigned long v)
> > > > >
> > > > > Don't use l (long) and ll (long long) for names (and types),
> use explicit bit lengths, 32 and 64.
> > > > >
> > > > > E.g.: rte_clz32(uint32_t v)
> > > >
> > > > I agree on using numbers.
> > > >
> > >
> > > love the idea, fewer functions too.
> > >
> > > though it is a shame we cannot adopt C11 standard because we could
> just
> > > do away with the bit suffixes entirely.
> >
> > We could but the project needs to support older RHEL releases
> > which have older tool sets. Though probably this is moot point given
> > how much meson seems to change.
> 
> True, though meson tends to be a bit easier to update than GCC on a
> system
> - no "pip3 install --upgrade gcc", sadly :-)
> 
> If we can't go all the way to C11 support, how about at least going to
> C99
> support? As far as I know DPDK has never updated its minimum C-standard
> version, and it might be a good idea to start the process of doing so,
> even
> if it is a baby step.
> 
> /Bruce

The DPDK Getting Started Guide [1] says:

"Required Tools and Libraries:
[...]
a supported C compiler such as gcc (version 4.9+)"

GCC version 4.9 supports C11 [2]:
"GCC 4.9 Changes: "ISO C11 support is now at a similar level of completeness to ISO C99 support [...]"

So why are we not going to support C11?

Probably because of RHEL 7, which only provides GCC 4.8 [3].

RHEL 7 was released for GA on June 10, 2014 [4]. If someone has a server with a nine year old distro still used in production, it is probably because it is running some legacy application, which is difficult to get up and running on a newer distro. Partial conclusion: RHEL 7 is probably still widely used in production.

However, I have a hard time understanding why anyone would build and/or deploy a brand new DPDK application (based on DPDK 23.03) on such a server. Can someone please justify this?

Are we really going to postpone C11 support in DPDK until June 30, 2026, when RHEL 7 ends its Extended Life Cycle Support [4]?

If so, then the GCC version mentioned in the DPDK Getting Started Guide should be corrected accordingly.

[1]: https://doc.dpdk.org/guides/linux_gsg/sys_reqs.html#compilation-of-the-dpdk
[2]: https://gcc.gnu.org/wiki/C11Status
[3]: https://access.redhat.com/solutions/19458
[4]: https://access.redhat.com/support/policy/updates/errata#Life_Cycle_Dates


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06 12:41               ` Morten Brørup
@ 2023-01-06 13:40                 ` Thomas Monjalon
  2023-01-06 18:58                   ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Thomas Monjalon @ 2023-01-06 13:40 UTC (permalink / raw)
  To: Bruce Richardson, Stephen Hemminger, david.marchand
  Cc: dev, Tyler Retzlaff, dev, Morten Brørup,
	honnappa.nagarahalli, jerinj, ktraynor, maxime.coquelin

06/01/2023 13:41, Morten Brørup:
> > From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> > Sent: Friday, 6 January 2023 12.48
> > 
> > On Thu, Jan 05, 2023 at 04:32:40PM -0800, Stephen Hemminger wrote:
> > > On Thu, 5 Jan 2023 09:21:18 -0800
> > > Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:
> > >
> > > > On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> > > > > 05/01/2023 08:09, Morten Brørup:
> > > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > > +/**
> > > > > > > + * @warning
> > > > > > > + * @b EXPERIMENTAL: this API may change, or be removed,
> > without prior
> > > > > > > notice
> > > > > > > + *
> > > > > > > + * Get the count of leading 0-bits in v.
> > > > > > > + *
> > > > > > > + * @param v
> > > > > > > + *   The value.
> > > > > > > + * @return
> > > > > > > + *   The count of leading zero bits.
> > > > > > > + */
> > > > > > > +__rte_experimental
> > > > > > > +static inline unsigned int
> > > > > > > +rte_clzl(unsigned long v)
> > > > > >
> > > > > > Don't use l (long) and ll (long long) for names (and types),
> > use explicit bit lengths, 32 and 64.
> > > > > >
> > > > > > E.g.: rte_clz32(uint32_t v)
> > > > >
> > > > > I agree on using numbers.
> > > > >
> > > >
> > > > love the idea, fewer functions too.
> > > >
> > > > though it is a shame we cannot adopt C11 standard because we could
> > just
> > > > do away with the bit suffixes entirely.
> > >
> > > We could but the project needs to support older RHEL releases
> > > which have older tool sets. Though probably this is moot point given
> > > how much meson seems to change.
> > 
> > True, though meson tends to be a bit easier to update than GCC on a
> > system
> > - no "pip3 install --upgrade gcc", sadly :-)
> > 
> > If we can't go all the way to C11 support, how about at least going to
> > C99
> > support? As far as I know DPDK has never updated its minimum C-standard
> > version, and it might be a good idea to start the process of doing so,
> > even
> > if it is a baby step.

I am in favor of this baby step: define -std=c99 porject-wise
and see what are the effects during the year.


> The DPDK Getting Started Guide [1] says:
> 
> "Required Tools and Libraries:
> [...]
> a supported C compiler such as gcc (version 4.9+)"
> 
> GCC version 4.9 supports C11 [2]:
> "GCC 4.9 Changes: "ISO C11 support is now at a similar level of completeness to ISO C99 support [...]"
> 
> So why are we not going to support C11?

We should make a plan to switch to C11 during next year.


> Probably because of RHEL 7, which only provides GCC 4.8 [3].
> 
> RHEL 7 was released for GA on June 10, 2014 [4]. If someone has a server with a nine year old distro still used in production, it is probably because it is running some legacy application, which is difficult to get up and running on a newer distro. Partial conclusion: RHEL 7 is probably still widely used in production.
> 
> However, I have a hard time understanding why anyone would build and/or deploy a brand new DPDK application (based on DPDK 23.03) on such a server. Can someone please justify this?
> 
> Are we really going to postpone C11 support in DPDK until June 30, 2026, when RHEL 7 ends its Extended Life Cycle Support [4]?

RHEL does its own choices to support old software for long.
Upstream development should move forward.


> If so, then the GCC version mentioned in the DPDK Getting Started Guide should be corrected accordingly.

No let's keep GCC 4.9 as a minimum for now.
If needed we could upgrade it later.




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06 11:48             ` Bruce Richardson
  2023-01-06 12:41               ` Morten Brørup
@ 2023-01-06 18:47               ` Tyler Retzlaff
  2023-01-09  8:50                 ` Bruce Richardson
  1 sibling, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-06 18:47 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: Stephen Hemminger, Thomas Monjalon, Morten Brørup, dev,
	david.marchand

On Fri, Jan 06, 2023 at 11:48:17AM +0000, Bruce Richardson wrote:
> On Thu, Jan 05, 2023 at 04:32:40PM -0800, Stephen Hemminger wrote:
> > On Thu, 5 Jan 2023 09:21:18 -0800
> > Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:
> > 
> > > On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> > > > 05/01/2023 08:09, Morten Brørup:  
> > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > +/**
> > > > > > + * @warning
> > > > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > > > notice
> > > > > > + *
> > > > > > + * Get the count of leading 0-bits in v.
> > > > > > + *
> > > > > > + * @param v
> > > > > > + *   The value.
> > > > > > + * @return
> > > > > > + *   The count of leading zero bits.
> > > > > > + */
> > > > > > +__rte_experimental
> > > > > > +static inline unsigned int
> > > > > > +rte_clzl(unsigned long v)  
> > > > > 
> > > > > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > > > > 
> > > > > E.g.: rte_clz32(uint32_t v)  
> > > > 
> > > > I agree on using numbers.
> > > >   
> > > 
> > > love the idea, fewer functions too.
> > > 
> > > though it is a shame we cannot adopt C11 standard because we could just
> > > do away with the bit suffixes entirely.
> > 
> > We could but the project needs to support older RHEL releases
> > which have older tool sets. Though probably this is moot point given
> > how much meson seems to change.
> 
> True, though meson tends to be a bit easier to update than GCC on a system
> - no "pip3 install --upgrade gcc", sadly :-)

* on linux. :)

> 
> If we can't go all the way to C11 support, how about at least going to C99
> support? As far as I know DPDK has never updated its minimum C-standard
> version, and it might be a good idea to start the process of doing so, even
> if it is a baby step.

the thing that blurs the line a bit is how the gcc version that is
holding us back does actually allow the use of some C99 optional
features. for example we use the C99 fixed width integer types so
technically some of the code already requires C99.

i also notice at least one driver is explicitly specifying -std=gnu99 so
maybe that driver just isn't being built when the old gcc is detected?

anyway, i think we are stuck pre-c99 so long as we have RHEL 7 to
contend with. the rationale is if we could use a compiler conforming to
the new standard we could just directly use those features, but so long
as we have to support non conforming compiler at a particular level we
have to introduce an abstraction and that is where all the extra work
comes from.

a prominent example is atomics from C11, but for other reasons in our
code base that i won't go into even if we required C11 we would still
need to abstract atomics. fwiw i'm working on this patch series now and
hope to provide a first draft in the next week or two.

finally, i do think it would be good to document a minimum C compiler
conformance level rather than specific gcc versions. though i admit we
also have a hard dependency on gcc right now. my goal is to improve
portability to a level where we could just state "you need a C<N>
compliant compiler" (or as close to it as possible).

ty

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06 13:40                 ` Thomas Monjalon
@ 2023-01-06 18:58                   ` Tyler Retzlaff
  2023-01-06 20:51                     ` Thomas Monjalon
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-06 18:58 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: Bruce Richardson, Stephen Hemminger, david.marchand, dev,
	Morten Brørup, honnappa.nagarahalli, jerinj, ktraynor,
	maxime.coquelin

On Fri, Jan 06, 2023 at 02:40:59PM +0100, Thomas Monjalon wrote:
> 06/01/2023 13:41, Morten Brørup:
> > > From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> > > Sent: Friday, 6 January 2023 12.48
> > > 
> > > On Thu, Jan 05, 2023 at 04:32:40PM -0800, Stephen Hemminger wrote:
> > > > On Thu, 5 Jan 2023 09:21:18 -0800
> > > > Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:
> > > >
> > > > > On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> > > > > > 05/01/2023 08:09, Morten Brørup:
> > > > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > > > +/**
> > > > > > > > + * @warning
> > > > > > > > + * @b EXPERIMENTAL: this API may change, or be removed,
> > > without prior
> > > > > > > > notice
> > > > > > > > + *
> > > > > > > > + * Get the count of leading 0-bits in v.
> > > > > > > > + *
> > > > > > > > + * @param v
> > > > > > > > + *   The value.
> > > > > > > > + * @return
> > > > > > > > + *   The count of leading zero bits.
> > > > > > > > + */
> > > > > > > > +__rte_experimental
> > > > > > > > +static inline unsigned int
> > > > > > > > +rte_clzl(unsigned long v)
> > > > > > >
> > > > > > > Don't use l (long) and ll (long long) for names (and types),
> > > use explicit bit lengths, 32 and 64.
> > > > > > >
> > > > > > > E.g.: rte_clz32(uint32_t v)
> > > > > >
> > > > > > I agree on using numbers.
> > > > > >
> > > > >
> > > > > love the idea, fewer functions too.
> > > > >
> > > > > though it is a shame we cannot adopt C11 standard because we could
> > > just
> > > > > do away with the bit suffixes entirely.
> > > >
> > > > We could but the project needs to support older RHEL releases
> > > > which have older tool sets. Though probably this is moot point given
> > > > how much meson seems to change.
> > > 
> > > True, though meson tends to be a bit easier to update than GCC on a
> > > system
> > > - no "pip3 install --upgrade gcc", sadly :-)
> > > 
> > > If we can't go all the way to C11 support, how about at least going to
> > > C99
> > > support? As far as I know DPDK has never updated its minimum C-standard
> > > version, and it might be a good idea to start the process of doing so,
> > > even
> > > if it is a baby step.
> 
> I am in favor of this baby step: define -std=c99 porject-wise
> and see what are the effects during the year.
> 
> 
> > The DPDK Getting Started Guide [1] says:
> > 
> > "Required Tools and Libraries:
> > [...]
> > a supported C compiler such as gcc (version 4.9+)"
> > 
> > GCC version 4.9 supports C11 [2]:
> > "GCC 4.9 Changes: "ISO C11 support is now at a similar level of completeness to ISO C99 support [...]"
> > 
> > So why are we not going to support C11?
> 
> We should make a plan to switch to C11 during next year.
> 
> 
> > Probably because of RHEL 7, which only provides GCC 4.8 [3].
> > 
> > RHEL 7 was released for GA on June 10, 2014 [4]. If someone has a server with a nine year old distro still used in production, it is probably because it is running some legacy application, which is difficult to get up and running on a newer distro. Partial conclusion: RHEL 7 is probably still widely used in production.
> > 
> > However, I have a hard time understanding why anyone would build and/or deploy a brand new DPDK application (based on DPDK 23.03) on such a server. Can someone please justify this?
> > 
> > Are we really going to postpone C11 support in DPDK until June 30, 2026, when RHEL 7 ends its Extended Life Cycle Support [4]?
> 
> RHEL does its own choices to support old software for long.
> Upstream development should move forward.
> 
> 
> > If so, then the GCC version mentioned in the DPDK Getting Started Guide should be corrected accordingly.
> 
> No let's keep GCC 4.9 as a minimum for now.
> If needed we could upgrade it later.

but i think the point Morten is making is that RHEL 7 gcc is 4.8 and
therefore we implicitly no longer support it if we document requiring
gcc 4.9.

> 
> 

so i think the way to do this is through clarification at the next
release / ltsc release. starting with dpdk 23.xx will require
compiler conforming to standard X and optional features / annexes from
standard X. anyone building applications targeting that version of dpdk
release will need a conforming implementation.

from there we just need to take care not to backport any code to
stable branches that depend on standard features that exceed the
requirements documented for that release.


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06 18:58                   ` Tyler Retzlaff
@ 2023-01-06 20:51                     ` Thomas Monjalon
  2023-01-10  9:18                       ` Ferruh Yigit
  0 siblings, 1 reply; 81+ messages in thread
From: Thomas Monjalon @ 2023-01-06 20:51 UTC (permalink / raw)
  To: Tyler Retzlaff
  Cc: Bruce Richardson, Stephen Hemminger, david.marchand, dev,
	Morten Brørup, honnappa.nagarahalli, jerinj, ktraynor,
	maxime.coquelin

06/01/2023 19:58, Tyler Retzlaff:
> On Fri, Jan 06, 2023 at 02:40:59PM +0100, Thomas Monjalon wrote:
> > 06/01/2023 13:41, Morten Brørup:
> > > > From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> > > > Sent: Friday, 6 January 2023 12.48
> > > > 
> > > > On Thu, Jan 05, 2023 at 04:32:40PM -0800, Stephen Hemminger wrote:
> > > > > On Thu, 5 Jan 2023 09:21:18 -0800
> > > > > Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:
> > > > >
> > > > > > On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> > > > > > > 05/01/2023 08:09, Morten Brørup:
> > > > > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > > > > +/**
> > > > > > > > > + * @warning
> > > > > > > > > + * @b EXPERIMENTAL: this API may change, or be removed,
> > > > without prior
> > > > > > > > > notice
> > > > > > > > > + *
> > > > > > > > > + * Get the count of leading 0-bits in v.
> > > > > > > > > + *
> > > > > > > > > + * @param v
> > > > > > > > > + *   The value.
> > > > > > > > > + * @return
> > > > > > > > > + *   The count of leading zero bits.
> > > > > > > > > + */
> > > > > > > > > +__rte_experimental
> > > > > > > > > +static inline unsigned int
> > > > > > > > > +rte_clzl(unsigned long v)
> > > > > > > >
> > > > > > > > Don't use l (long) and ll (long long) for names (and types),
> > > > use explicit bit lengths, 32 and 64.
> > > > > > > >
> > > > > > > > E.g.: rte_clz32(uint32_t v)
> > > > > > >
> > > > > > > I agree on using numbers.
> > > > > > >
> > > > > >
> > > > > > love the idea, fewer functions too.
> > > > > >
> > > > > > though it is a shame we cannot adopt C11 standard because we could
> > > > just
> > > > > > do away with the bit suffixes entirely.
> > > > >
> > > > > We could but the project needs to support older RHEL releases
> > > > > which have older tool sets. Though probably this is moot point given
> > > > > how much meson seems to change.
> > > > 
> > > > True, though meson tends to be a bit easier to update than GCC on a
> > > > system
> > > > - no "pip3 install --upgrade gcc", sadly :-)
> > > > 
> > > > If we can't go all the way to C11 support, how about at least going to
> > > > C99
> > > > support? As far as I know DPDK has never updated its minimum C-standard
> > > > version, and it might be a good idea to start the process of doing so,
> > > > even
> > > > if it is a baby step.
> > 
> > I am in favor of this baby step: define -std=c99 porject-wise
> > and see what are the effects during the year.
> > 
> > 
> > > The DPDK Getting Started Guide [1] says:
> > > 
> > > "Required Tools and Libraries:
> > > [...]
> > > a supported C compiler such as gcc (version 4.9+)"
> > > 
> > > GCC version 4.9 supports C11 [2]:
> > > "GCC 4.9 Changes: "ISO C11 support is now at a similar level of completeness to ISO C99 support [...]"
> > > 
> > > So why are we not going to support C11?
> > 
> > We should make a plan to switch to C11 during next year.
> > 
> > 
> > > Probably because of RHEL 7, which only provides GCC 4.8 [3].
> > > 
> > > RHEL 7 was released for GA on June 10, 2014 [4]. If someone has a server with a nine year old distro still used in production, it is probably because it is running some legacy application, which is difficult to get up and running on a newer distro. Partial conclusion: RHEL 7 is probably still widely used in production.
> > > 
> > > However, I have a hard time understanding why anyone would build and/or deploy a brand new DPDK application (based on DPDK 23.03) on such a server. Can someone please justify this?
> > > 
> > > Are we really going to postpone C11 support in DPDK until June 30, 2026, when RHEL 7 ends its Extended Life Cycle Support [4]?
> > 
> > RHEL does its own choices to support old software for long.
> > Upstream development should move forward.
> > 
> > 
> > > If so, then the GCC version mentioned in the DPDK Getting Started Guide should be corrected accordingly.
> > 
> > No let's keep GCC 4.9 as a minimum for now.
> > If needed we could upgrade it later.
> 
> but i think the point Morten is making is that RHEL 7 gcc is 4.8 and
> therefore we implicitly no longer support it if we document requiring
> gcc 4.9.

Yes I got it.
I think everything in DPDK works on RHEL 7 today,
but I believe RHEL 7 is not a strong requirement anymore for the mainline.
Asking for confirmation here.

> so i think the way to do this is through clarification at the next
> release / ltsc release. starting with dpdk 23.xx will require
> compiler conforming to standard X and optional features / annexes from
> standard X. anyone building applications targeting that version of dpdk
> release will need a conforming implementation.
> 
> from there we just need to take care not to backport any code to
> stable branches that depend on standard features that exceed the
> requirements documented for that release.

We could even start testing C99 requirement in 23.03 I think.



^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v3 0/3] eal: provide leading and trailing zero bit count
  2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
                   ` (2 preceding siblings ...)
  2022-11-23 23:43 ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
@ 2023-01-06 22:01 ` Tyler Retzlaff
  2023-01-06 22:01   ` [PATCH v3 1/3] eal: move bit functions from common to bitops header Tyler Retzlaff
                     ` (3 more replies)
  2023-01-10 19:38 ` [PATCH v5 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
                   ` (3 subsequent siblings)
  7 siblings, 4 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-06 22:01 UTC (permalink / raw)
  To: dev; +Cc: mb, thomas, david.marchand, Tyler Retzlaff

Move existing bit manipulation, log and npow functions from
rte_common.h to rte_bitops.h

Provide leading and trailing zero bit count functions to abstract away
compiler specific implementations.

Include basic unit test for new leading/trailing zero bit count functions.

v3:
  * rename to use 32/64 instead of l/ll suffixes
  * add new functions to rte_bitops.h instead of new header
  * move other bit functions from rte_common.h to rte_bitops.h

v2:
  * use unsigned int instead of unsigned (checkpatches)
  * match multiple include guard naming convention to rte_common.h
  * add explicit extern "C" linkage to rte_bitcount.h
    note: not really needed but checkpatches required
  * add missing space around '-'

Tyler Retzlaff (3):
  eal: move bit functions from common to bitops header
  eal: provide leading and trailing zero bit count abstraction
  test/bitcount: add bitcount tests

 app/test/meson.build            |   2 +
 app/test/test_bitcount.c        |  71 +++++++
 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 460 ++++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 -------------------------
 6 files changed, 535 insertions(+), 293 deletions(-)
 create mode 100644 app/test/test_bitcount.c

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v3 1/3] eal: move bit functions from common to bitops header
  2023-01-06 22:01 ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Tyler Retzlaff
@ 2023-01-06 22:01   ` Tyler Retzlaff
  2023-01-06 22:01   ` [PATCH v3 2/3] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-06 22:01 UTC (permalink / raw)
  To: dev; +Cc: mb, thomas, david.marchand, Tyler Retzlaff

Move the following inline functions from rte_common.h to rte_bitops.h

  rte_combine32ms1b
  rte_combine64ms1b
  rte_bsf32
  rte_bsf32_safe
  rte_bsf64
  rte_bsf64_safe
  rte_fls_u32
  rte_fls_u64
  rte_is_power_of_2
  rte_align32pow2
  rte_align32prevpow2
  rte_align64pow2
  rte_align64prevpow2
  rte_log2_u32
  rte_log2_u64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 292 +++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 ----------------------------------------
 4 files changed, 294 insertions(+), 293 deletions(-)

diff --git a/app/test/test_common.c b/app/test/test_common.c
index f89e1eb..cf4a2c7 100644
--- a/app/test/test_common.c
+++ b/app/test/test_common.c
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <math.h>
 #include <rte_common.h>
+#include <rte_bitops.h>
 #include <rte_hexdump.h>
 #include <rte_pause.h>
 
diff --git a/lib/eal/common/rte_reciprocal.c b/lib/eal/common/rte_reciprocal.c
index 42dfa44..d47dc47 100644
--- a/lib/eal/common/rte_reciprocal.c
+++ b/lib/eal/common/rte_reciprocal.c
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <rte_common.h>
+#include <rte_bitops.h>
 
 #include "rte_reciprocal.h"
 
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index f50dbe4..531479e 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -275,6 +275,298 @@
 	return val & mask;
 }
 
+/**
+ * Combines 32b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param x
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint32_t
+rte_combine32ms1b(uint32_t x)
+{
+	x |= x >> 1;
+	x |= x >> 2;
+	x |= x >> 4;
+	x |= x >> 8;
+	x |= x >> 16;
+
+	return x;
+}
+
+/**
+ * Combines 64b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param v
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint64_t
+rte_combine64ms1b(uint64_t v)
+{
+	v |= v >> 1;
+	v |= v >> 2;
+	v |= v >> 4;
+	v |= v >> 8;
+	v |= v >> 16;
+	v |= v >> 32;
+
+	return v;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf32(uint32_t v)
+{
+	return (uint32_t)__builtin_ctz(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf32_safe(uint32_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf32(v);
+	return 1;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf64(uint64_t v)
+{
+	return (uint32_t)__builtin_ctzll(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf64_safe(uint64_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf64(v);
+	return 1;
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 32.
+ * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u32(uint32_t x)
+{
+	return (x == 0) ? 0 : 32 - __builtin_clz(x);
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 64.
+ * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
+ *       rte_fls_u64(0x8000000000000000) = 64
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u64(uint64_t x)
+{
+	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
+}
+
+/*********** Macros to work with powers of 2 ********/
+
+/**
+ * Macro to return 1 if n is a power of 2, 0 otherwise
+ */
+#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
+
+/**
+ * Returns true if n is a power of 2
+ * @param n
+ *     Number to check
+ * @return 1 if true, 0 otherwise
+ */
+static inline int
+rte_is_power_of_2(uint32_t n)
+{
+	return n && !(n & (n - 1));
+}
+
+/**
+ * Aligns input parameter to the next power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint32_t
+rte_align32pow2(uint32_t x)
+{
+	x--;
+	x = rte_combine32ms1b(x);
+
+	return x + 1;
+}
+
+/**
+ * Aligns input parameter to the previous power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint32_t
+rte_align32prevpow2(uint32_t x)
+{
+	x = rte_combine32ms1b(x);
+
+	return x - (x >> 1);
+}
+
+/**
+ * Aligns 64b input parameter to the next power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint64_t
+rte_align64pow2(uint64_t v)
+{
+	v--;
+	v = rte_combine64ms1b(v);
+
+	return v + 1;
+}
+
+/**
+ * Aligns 64b input parameter to the previous power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint64_t
+rte_align64prevpow2(uint64_t v)
+{
+	v = rte_combine64ms1b(v);
+
+	return v - (v >> 1);
+}
+
+/**
+ * Return the rounded-up log2 of a integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u32(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u32(uint32_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align32pow2(v);
+	return rte_bsf32(v);
+}
+
+/**
+ * Return the rounded-up log2 of a 64-bit integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u64(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u64(uint64_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align64pow2(v);
+	/* we checked for v being 0 already, so no undefined behavior */
+	return rte_bsf64(v);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eal/include/rte_common.h b/lib/eal/include/rte_common.h
index 15765b4..c5ad69c 100644
--- a/lib/eal/include/rte_common.h
+++ b/lib/eal/include/rte_common.h
@@ -471,140 +471,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 /** Marker for 8B alignment in a structure. */
 __extension__ typedef uint64_t RTE_MARKER64[0];
 
-/**
- * Combines 32b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param x
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint32_t
-rte_combine32ms1b(uint32_t x)
-{
-	x |= x >> 1;
-	x |= x >> 2;
-	x |= x >> 4;
-	x |= x >> 8;
-	x |= x >> 16;
-
-	return x;
-}
-
-/**
- * Combines 64b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param v
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint64_t
-rte_combine64ms1b(uint64_t v)
-{
-	v |= v >> 1;
-	v |= v >> 2;
-	v |= v >> 4;
-	v |= v >> 8;
-	v |= v >> 16;
-	v |= v >> 32;
-
-	return v;
-}
-
-/*********** Macros to work with powers of 2 ********/
-
-/**
- * Macro to return 1 if n is a power of 2, 0 otherwise
- */
-#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
-
-/**
- * Returns true if n is a power of 2
- * @param n
- *     Number to check
- * @return 1 if true, 0 otherwise
- */
-static inline int
-rte_is_power_of_2(uint32_t n)
-{
-	return n && !(n & (n - 1));
-}
-
-/**
- * Aligns input parameter to the next power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint32_t
-rte_align32pow2(uint32_t x)
-{
-	x--;
-	x = rte_combine32ms1b(x);
-
-	return x + 1;
-}
-
-/**
- * Aligns input parameter to the previous power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint32_t
-rte_align32prevpow2(uint32_t x)
-{
-	x = rte_combine32ms1b(x);
-
-	return x - (x >> 1);
-}
-
-/**
- * Aligns 64b input parameter to the next power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint64_t
-rte_align64pow2(uint64_t v)
-{
-	v--;
-	v = rte_combine64ms1b(v);
-
-	return v + 1;
-}
-
-/**
- * Aligns 64b input parameter to the previous power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint64_t
-rte_align64prevpow2(uint64_t v)
-{
-	v = rte_combine64ms1b(v);
-
-	return v - (v >> 1);
-}
-
 /*********** Macros for calculating min and max **********/
 
 /**
@@ -629,165 +495,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 
 /*********** Other general functions / macros ********/
 
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf32(uint32_t v)
-{
-	return (uint32_t)__builtin_ctz(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf32_safe(uint32_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf32(v);
-	return 1;
-}
-
-/**
- * Return the rounded-up log2 of a integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u32(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u32(uint32_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align32pow2(v);
-	return rte_bsf32(v);
-}
-
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 32.
- * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u32(uint32_t x)
-{
-	return (x == 0) ? 0 : 32 - __builtin_clz(x);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf64(uint64_t v)
-{
-	return (uint32_t)__builtin_ctzll(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf64_safe(uint64_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf64(v);
-	return 1;
-}
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 64.
- * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
- *       rte_fls_u64(0x8000000000000000) = 64
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u64(uint64_t x)
-{
-	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
-}
-
-/**
- * Return the rounded-up log2 of a 64-bit integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u64(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u64(uint64_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align64pow2(v);
-	/* we checked for v being 0 already, so no undefined behavior */
-	return rte_bsf64(v);
-}
-
 #ifndef offsetof
 /** Return the offset of a field in a structure. */
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v3 2/3] eal: provide leading and trailing zero bit count abstraction
  2023-01-06 22:01 ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Tyler Retzlaff
  2023-01-06 22:01   ` [PATCH v3 1/3] eal: move bit functions from common to bitops header Tyler Retzlaff
@ 2023-01-06 22:01   ` Tyler Retzlaff
  2023-01-06 22:01   ` [PATCH v3 3/3] test/bitcount: add bitcount tests Tyler Retzlaff
  2023-01-09  8:51   ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Bruce Richardson
  3 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-06 22:01 UTC (permalink / raw)
  To: dev; +Cc: mb, thomas, david.marchand, Tyler Retzlaff, Tyler Retzlaff

From: Tyler Retzlaff <roretzla@microsoft.com>

Provide an abstraction for leading and trailing zero bit counting
functions to hide compiler specific intrinsics and builtins.

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 lib/eal/include/rte_bitops.h | 168 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 168 insertions(+)

diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index 531479e..387d7aa 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2020 Arm Limited
+ * Copyright(c) 2010-2019 Intel Corporation
+ * Copyright(c) 2023 Microsoft Corporation
  */
 
 #ifndef _RTE_BITOPS_H_
@@ -275,6 +277,172 @@
 	return val & mask;
 }
 
+#ifdef RTE_TOOLCHAIN_MSVC
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+#else
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	return (unsigned int)__builtin_clz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	return (unsigned int)__builtin_clzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	return (unsigned int)__builtin_ctz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	return (unsigned int)__builtin_ctzll(v);
+}
+
+#endif
+
 /**
  * Combines 32b inputs most significant set bits into the least
  * significant bits to construct a value with the same MSBs as x
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v3 3/3] test/bitcount: add bitcount tests
  2023-01-06 22:01 ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Tyler Retzlaff
  2023-01-06 22:01   ` [PATCH v3 1/3] eal: move bit functions from common to bitops header Tyler Retzlaff
  2023-01-06 22:01   ` [PATCH v3 2/3] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2023-01-06 22:01   ` Tyler Retzlaff
  2023-01-07  8:15     ` Thomas Monjalon
  2023-01-07 13:40     ` Morten Brørup
  2023-01-09  8:51   ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Bruce Richardson
  3 siblings, 2 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-06 22:01 UTC (permalink / raw)
  To: dev; +Cc: mb, thomas, david.marchand, Tyler Retzlaff

basic unit test of following functions

    rte_clz32
    rte_clz64
    rte_ctz32
    rte_ctz64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 app/test/meson.build     |  2 ++
 app/test/test_bitcount.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+)
 create mode 100644 app/test/test_bitcount.c

diff --git a/app/test/meson.build b/app/test/meson.build
index f34d19e..d1277bc 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -13,6 +13,7 @@ test_sources = files(
         'test_alarm.c',
         'test_atomic.c',
         'test_barrier.c',
+        'test_bitcount.c',
         'test_bitops.c',
         'test_bitmap.c',
         'test_bpf.c',
@@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
 fast_tests = [
         ['acl_autotest', true, true],
         ['atomic_autotest', false, true],
+        ['bitcount_autotest', true, true],
         ['bitmap_autotest', true, true],
         ['bpf_autotest', true, true],
         ['bpf_convert_autotest', true, true],
diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
new file mode 100644
index 0000000..36eb05c
--- /dev/null
+++ b/app/test/test_bitcount.c
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#include <string.h>
+
+#include <rte_bitops.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
+
+static int
+test_clz32(void)
+{
+	uint32_t v = 1;
+	RTE_TEST_ASSERT(rte_clz32(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_clz64(void)
+{
+	uint64_t v = 1;
+	RTE_TEST_ASSERT(rte_clz64(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctz32(void)
+{
+	uint32_t v = 2;
+	RTE_TEST_ASSERT(rte_ctz32(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctz64(void)
+{
+	uint64_t v = 2;
+	RTE_TEST_ASSERT(rte_ctz64(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static struct unit_test_suite bitcount_test_suite = {
+	.suite_name = "bitcount autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+		TEST_CASE(test_clz32),
+		TEST_CASE(test_clz64),
+		TEST_CASE(test_ctz32),
+		TEST_CASE(test_ctz64),
+		TEST_CASES_END()
+	}
+};
+
+static int
+test_bitcount(void)
+{
+	return unit_test_suite_runner(&bitcount_test_suite);
+}
+
+REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v3 3/3] test/bitcount: add bitcount tests
  2023-01-06 22:01   ` [PATCH v3 3/3] test/bitcount: add bitcount tests Tyler Retzlaff
@ 2023-01-07  8:15     ` Thomas Monjalon
  2023-01-09 16:57       ` Tyler Retzlaff
  2023-01-07 13:40     ` Morten Brørup
  1 sibling, 1 reply; 81+ messages in thread
From: Thomas Monjalon @ 2023-01-07  8:15 UTC (permalink / raw)
  To: dev, Tyler Retzlaff; +Cc: mb, david.marchand

06/01/2023 23:01, Tyler Retzlaff:
> basic unit test of following functions
> 
>     rte_clz32
>     rte_clz64
>     rte_ctz32
>     rte_ctz64

This can be squashed with implementation in previous patch.




^ permalink raw reply	[flat|nested] 81+ messages in thread

* RE: [PATCH v3 3/3] test/bitcount: add bitcount tests
  2023-01-06 22:01   ` [PATCH v3 3/3] test/bitcount: add bitcount tests Tyler Retzlaff
  2023-01-07  8:15     ` Thomas Monjalon
@ 2023-01-07 13:40     ` Morten Brørup
  1 sibling, 0 replies; 81+ messages in thread
From: Morten Brørup @ 2023-01-07 13:40 UTC (permalink / raw)
  To: Tyler Retzlaff, dev; +Cc: thomas, david.marchand

> From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> Sent: Friday, 6 January 2023 23.02
> 
> basic unit test of following functions
> 
>     rte_clz32
>     rte_clz64
>     rte_ctz32
>     rte_ctz64
> 
> Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> ---

Series-acked-by: Morten Brørup <mb@smartsharesystems.com>


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06 18:47               ` Tyler Retzlaff
@ 2023-01-09  8:50                 ` Bruce Richardson
  0 siblings, 0 replies; 81+ messages in thread
From: Bruce Richardson @ 2023-01-09  8:50 UTC (permalink / raw)
  To: Tyler Retzlaff
  Cc: Stephen Hemminger, Thomas Monjalon, Morten Brørup, dev,
	david.marchand

On Fri, Jan 06, 2023 at 10:47:06AM -0800, Tyler Retzlaff wrote:
> On Fri, Jan 06, 2023 at 11:48:17AM +0000, Bruce Richardson wrote:
> > On Thu, Jan 05, 2023 at 04:32:40PM -0800, Stephen Hemminger wrote:
> > > On Thu, 5 Jan 2023 09:21:18 -0800
> > > Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:
> > > 
> > > > On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
> > > > > 05/01/2023 08:09, Morten Brørup:  
> > > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > > +/**
> > > > > > > + * @warning
> > > > > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > > > > notice
> > > > > > > + *
> > > > > > > + * Get the count of leading 0-bits in v.
> > > > > > > + *
> > > > > > > + * @param v
> > > > > > > + *   The value.
> > > > > > > + * @return
> > > > > > > + *   The count of leading zero bits.
> > > > > > > + */
> > > > > > > +__rte_experimental
> > > > > > > +static inline unsigned int
> > > > > > > +rte_clzl(unsigned long v)  
> > > > > > 
> > > > > > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > > > > > 
> > > > > > E.g.: rte_clz32(uint32_t v)  
> > > > > 
> > > > > I agree on using numbers.
> > > > >   
> > > > 
> > > > love the idea, fewer functions too.
> > > > 
> > > > though it is a shame we cannot adopt C11 standard because we could just
> > > > do away with the bit suffixes entirely.
> > > 
> > > We could but the project needs to support older RHEL releases
> > > which have older tool sets. Though probably this is moot point given
> > > how much meson seems to change.
> > 
> > True, though meson tends to be a bit easier to update than GCC on a system
> > - no "pip3 install --upgrade gcc", sadly :-)
> 
> * on linux. :)
> 
> > 
> > If we can't go all the way to C11 support, how about at least going to C99
> > support? As far as I know DPDK has never updated its minimum C-standard
> > version, and it might be a good idea to start the process of doing so, even
> > if it is a baby step.
> 
> the thing that blurs the line a bit is how the gcc version that is
> holding us back does actually allow the use of some C99 optional
> features. for example we use the C99 fixed width integer types so
> technically some of the code already requires C99.
> 
> i also notice at least one driver is explicitly specifying -std=gnu99 so
> maybe that driver just isn't being built when the old gcc is detected?
> 
> anyway, i think we are stuck pre-c99 so long as we have RHEL 7 to
> contend with. the rationale is if we could use a compiler conforming to
> the new standard we could just directly use those features, but so long
> as we have to support non conforming compiler at a particular level we
> have to introduce an abstraction and that is where all the extra work
> comes from.
> 

AFAIK the gcc 4.8 compiler on RHEL 7/Centos 7 does support C99, it's just
missing full support for C11 (which comes in 4.9). Therefore I see using
C99 as hopefully being unproblematic, and allowing us to try moving forward
revision and seeing what issues - if any - we hit. It should also allow us
to put in place infrastructure to support such version changes, since, for
example, we likely need to ensure that our headers still work with C90
compilation.

/Bruce

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v3 0/3] eal: provide leading and trailing zero bit count
  2023-01-06 22:01 ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Tyler Retzlaff
                     ` (2 preceding siblings ...)
  2023-01-06 22:01   ` [PATCH v3 3/3] test/bitcount: add bitcount tests Tyler Retzlaff
@ 2023-01-09  8:51   ` Bruce Richardson
  3 siblings, 0 replies; 81+ messages in thread
From: Bruce Richardson @ 2023-01-09  8:51 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: dev, mb, thomas, david.marchand

On Fri, Jan 06, 2023 at 02:01:42PM -0800, Tyler Retzlaff wrote:
> Move existing bit manipulation, log and npow functions from
> rte_common.h to rte_bitops.h
> 
> Provide leading and trailing zero bit count functions to abstract away
> compiler specific implementations.
> 
> Include basic unit test for new leading/trailing zero bit count functions.
> 
> v3:
>   * rename to use 32/64 instead of l/ll suffixes
>   * add new functions to rte_bitops.h instead of new header
>   * move other bit functions from rte_common.h to rte_bitops.h
> 
Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v3 3/3] test/bitcount: add bitcount tests
  2023-01-07  8:15     ` Thomas Monjalon
@ 2023-01-09 16:57       ` Tyler Retzlaff
  2023-01-09 17:26         ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-09 16:57 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev, mb, david.marchand

On Sat, Jan 07, 2023 at 09:15:27AM +0100, Thomas Monjalon wrote:
> 06/01/2023 23:01, Tyler Retzlaff:
> > basic unit test of following functions
> > 
> >     rte_clz32
> >     rte_clz64
> >     rte_ctz32
> >     rte_ctz64
> 
> This can be squashed with implementation in previous patch.
> 
> 

if you mean squashed into the patch that moves the existing functions
sure it can be, but really the addtions are a self contained change
separate from the move of the existing functions.

ordinarily i'd rather see history order be as follows.

- here is a change that just moves code (no addtions no deletions).
- here is a change that adds new apis (no moves).

you sure you want the move and additions all combined into one change?

either way confirm what you want and if needed i'll combine and push a
v4.

thanks

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v3 3/3] test/bitcount: add bitcount tests
  2023-01-09 16:57       ` Tyler Retzlaff
@ 2023-01-09 17:26         ` Tyler Retzlaff
  0 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-09 17:26 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev, mb, david.marchand

On Mon, Jan 09, 2023 at 08:57:32AM -0800, Tyler Retzlaff wrote:
> On Sat, Jan 07, 2023 at 09:15:27AM +0100, Thomas Monjalon wrote:
> > 06/01/2023 23:01, Tyler Retzlaff:
> > > basic unit test of following functions
> > > 
> > >     rte_clz32
> > >     rte_clz64
> > >     rte_ctz32
> > >     rte_ctz64
> > 
> > This can be squashed with implementation in previous patch.
> > 
> > 
> 
> if you mean squashed into the patch that moves the existing functions
> sure it can be, but really the addtions are a self contained change
> separate from the move of the existing functions.
> 
> ordinarily i'd rather see history order be as follows.
> 
> - here is a change that just moves code (no addtions no deletions).
> - here is a change that adds new apis (no moves).
> 
> you sure you want the move and additions all combined into one change?
> 
> either way confirm what you want and if needed i'll combine and push a
> v4.
> 

ignore the above, i misread what you were asking for.  i will submit a
new version with the unit tests squished in to the new function
additions.


> thanks

^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v4 0/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-23 23:43 ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
                     ` (2 preceding siblings ...)
  2023-01-04 23:46   ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
@ 2023-01-09 17:36   ` Tyler Retzlaff
  2023-01-09 17:36     ` [PATCH v4 1/2] eal: move bit operation functions from common to bitops header Tyler Retzlaff
                       ` (2 more replies)
  3 siblings, 3 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-09 17:36 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, Tyler Retzlaff

Move existing bit manipulation, log and npow functions from
rte_common.h to rte_bitops.h

Provide leading and trailing zero bit count functions to abstract away
compiler specific implementations.

Include basic unit test for new leading/trailing zero bit count functions.

v4:
  * combine unit test commit into function addition commit

v3:
  * rename to use 32/64 instead of l/ll suffixes
  * add new functions to rte_bitops.h instead of new header
  * move other bit functions from rte_common.h to rte_bitops.h

v2:
  * use unsigned int instead of unsigned (checkpatches)
  * match multiple include guard naming convention to rte_common.h
  * add explicit extern "C" linkage to rte_bitcount.h
    note: not really needed but checkpatches required
  * add missing space around '-'

Tyler Retzlaff (2):
  eal: move bit operation functions from common to bitops header
  eal: provide leading and trailing zero bit count abstraction

 app/test/meson.build            |   2 +
 app/test/test_bitcount.c        |  71 +++++++
 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 460 ++++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 -------------------------
 6 files changed, 535 insertions(+), 293 deletions(-)
 create mode 100644 app/test/test_bitcount.c

-- 

Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v4 1/2] eal: move bit operation functions from common to bitops header
  2023-01-09 17:36   ` [PATCH v4 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2023-01-09 17:36     ` Tyler Retzlaff
  2023-01-10 13:56       ` Ferruh Yigit
  2023-01-09 17:36     ` [PATCH v4 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2023-01-10 13:56     ` [PATCH v4 0/2] " Ferruh Yigit
  2 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-09 17:36 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, Tyler Retzlaff

Move the following inline functions from rte_common.h to rte_bitops.h

  rte_combine32ms1b
  rte_combine64ms1b
  rte_bsf32
  rte_bsf32_safe
  rte_bsf64
  rte_bsf64_safe
  rte_fls_u32
  rte_fls_u64
  rte_is_power_of_2
  rte_align32pow2
  rte_align32prevpow2
  rte_align64pow2
  rte_align64prevpow2
  rte_log2_u32
  rte_log2_u64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 292 +++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 ----------------------------------------
 4 files changed, 294 insertions(+), 293 deletions(-)

diff --git a/app/test/test_common.c b/app/test/test_common.c
index f89e1eb..cf4a2c7 100644
--- a/app/test/test_common.c
+++ b/app/test/test_common.c
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <math.h>
 #include <rte_common.h>
+#include <rte_bitops.h>
 #include <rte_hexdump.h>
 #include <rte_pause.h>
 
diff --git a/lib/eal/common/rte_reciprocal.c b/lib/eal/common/rte_reciprocal.c
index 42dfa44..d47dc47 100644
--- a/lib/eal/common/rte_reciprocal.c
+++ b/lib/eal/common/rte_reciprocal.c
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <rte_common.h>
+#include <rte_bitops.h>
 
 #include "rte_reciprocal.h"
 
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index f50dbe4..531479e 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -275,6 +275,298 @@
 	return val & mask;
 }
 
+/**
+ * Combines 32b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param x
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint32_t
+rte_combine32ms1b(uint32_t x)
+{
+	x |= x >> 1;
+	x |= x >> 2;
+	x |= x >> 4;
+	x |= x >> 8;
+	x |= x >> 16;
+
+	return x;
+}
+
+/**
+ * Combines 64b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param v
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint64_t
+rte_combine64ms1b(uint64_t v)
+{
+	v |= v >> 1;
+	v |= v >> 2;
+	v |= v >> 4;
+	v |= v >> 8;
+	v |= v >> 16;
+	v |= v >> 32;
+
+	return v;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf32(uint32_t v)
+{
+	return (uint32_t)__builtin_ctz(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf32_safe(uint32_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf32(v);
+	return 1;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf64(uint64_t v)
+{
+	return (uint32_t)__builtin_ctzll(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf64_safe(uint64_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf64(v);
+	return 1;
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 32.
+ * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u32(uint32_t x)
+{
+	return (x == 0) ? 0 : 32 - __builtin_clz(x);
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 64.
+ * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
+ *       rte_fls_u64(0x8000000000000000) = 64
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u64(uint64_t x)
+{
+	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
+}
+
+/*********** Macros to work with powers of 2 ********/
+
+/**
+ * Macro to return 1 if n is a power of 2, 0 otherwise
+ */
+#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
+
+/**
+ * Returns true if n is a power of 2
+ * @param n
+ *     Number to check
+ * @return 1 if true, 0 otherwise
+ */
+static inline int
+rte_is_power_of_2(uint32_t n)
+{
+	return n && !(n & (n - 1));
+}
+
+/**
+ * Aligns input parameter to the next power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint32_t
+rte_align32pow2(uint32_t x)
+{
+	x--;
+	x = rte_combine32ms1b(x);
+
+	return x + 1;
+}
+
+/**
+ * Aligns input parameter to the previous power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint32_t
+rte_align32prevpow2(uint32_t x)
+{
+	x = rte_combine32ms1b(x);
+
+	return x - (x >> 1);
+}
+
+/**
+ * Aligns 64b input parameter to the next power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint64_t
+rte_align64pow2(uint64_t v)
+{
+	v--;
+	v = rte_combine64ms1b(v);
+
+	return v + 1;
+}
+
+/**
+ * Aligns 64b input parameter to the previous power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint64_t
+rte_align64prevpow2(uint64_t v)
+{
+	v = rte_combine64ms1b(v);
+
+	return v - (v >> 1);
+}
+
+/**
+ * Return the rounded-up log2 of a integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u32(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u32(uint32_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align32pow2(v);
+	return rte_bsf32(v);
+}
+
+/**
+ * Return the rounded-up log2 of a 64-bit integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u64(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u64(uint64_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align64pow2(v);
+	/* we checked for v being 0 already, so no undefined behavior */
+	return rte_bsf64(v);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eal/include/rte_common.h b/lib/eal/include/rte_common.h
index 15765b4..c5ad69c 100644
--- a/lib/eal/include/rte_common.h
+++ b/lib/eal/include/rte_common.h
@@ -471,140 +471,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 /** Marker for 8B alignment in a structure. */
 __extension__ typedef uint64_t RTE_MARKER64[0];
 
-/**
- * Combines 32b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param x
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint32_t
-rte_combine32ms1b(uint32_t x)
-{
-	x |= x >> 1;
-	x |= x >> 2;
-	x |= x >> 4;
-	x |= x >> 8;
-	x |= x >> 16;
-
-	return x;
-}
-
-/**
- * Combines 64b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param v
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint64_t
-rte_combine64ms1b(uint64_t v)
-{
-	v |= v >> 1;
-	v |= v >> 2;
-	v |= v >> 4;
-	v |= v >> 8;
-	v |= v >> 16;
-	v |= v >> 32;
-
-	return v;
-}
-
-/*********** Macros to work with powers of 2 ********/
-
-/**
- * Macro to return 1 if n is a power of 2, 0 otherwise
- */
-#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
-
-/**
- * Returns true if n is a power of 2
- * @param n
- *     Number to check
- * @return 1 if true, 0 otherwise
- */
-static inline int
-rte_is_power_of_2(uint32_t n)
-{
-	return n && !(n & (n - 1));
-}
-
-/**
- * Aligns input parameter to the next power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint32_t
-rte_align32pow2(uint32_t x)
-{
-	x--;
-	x = rte_combine32ms1b(x);
-
-	return x + 1;
-}
-
-/**
- * Aligns input parameter to the previous power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint32_t
-rte_align32prevpow2(uint32_t x)
-{
-	x = rte_combine32ms1b(x);
-
-	return x - (x >> 1);
-}
-
-/**
- * Aligns 64b input parameter to the next power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint64_t
-rte_align64pow2(uint64_t v)
-{
-	v--;
-	v = rte_combine64ms1b(v);
-
-	return v + 1;
-}
-
-/**
- * Aligns 64b input parameter to the previous power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint64_t
-rte_align64prevpow2(uint64_t v)
-{
-	v = rte_combine64ms1b(v);
-
-	return v - (v >> 1);
-}
-
 /*********** Macros for calculating min and max **********/
 
 /**
@@ -629,165 +495,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 
 /*********** Other general functions / macros ********/
 
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf32(uint32_t v)
-{
-	return (uint32_t)__builtin_ctz(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf32_safe(uint32_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf32(v);
-	return 1;
-}
-
-/**
- * Return the rounded-up log2 of a integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u32(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u32(uint32_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align32pow2(v);
-	return rte_bsf32(v);
-}
-
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 32.
- * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u32(uint32_t x)
-{
-	return (x == 0) ? 0 : 32 - __builtin_clz(x);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf64(uint64_t v)
-{
-	return (uint32_t)__builtin_ctzll(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf64_safe(uint64_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf64(v);
-	return 1;
-}
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 64.
- * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
- *       rte_fls_u64(0x8000000000000000) = 64
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u64(uint64_t x)
-{
-	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
-}
-
-/**
- * Return the rounded-up log2 of a 64-bit integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u64(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u64(uint64_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align64pow2(v);
-	/* we checked for v being 0 already, so no undefined behavior */
-	return rte_bsf64(v);
-}
-
 #ifndef offsetof
 /** Return the offset of a field in a structure. */
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v4 2/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-09 17:36   ` [PATCH v4 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2023-01-09 17:36     ` [PATCH v4 1/2] eal: move bit operation functions from common to bitops header Tyler Retzlaff
@ 2023-01-09 17:36     ` Tyler Retzlaff
  2023-01-10 13:55       ` Ferruh Yigit
  2023-01-10 13:56     ` [PATCH v4 0/2] " Ferruh Yigit
  2 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-09 17:36 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, Tyler Retzlaff, Tyler Retzlaff

From: Tyler Retzlaff <roretzla@microsoft.com>

Provide an abstraction for leading and trailing zero bit counting
functions to hide compiler specific intrinsics and builtins.

Include basic unit test of following functions added.

    rte_clz32
    rte_clz64
    rte_ctz32
    rte_ctz64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 app/test/meson.build         |   2 +
 app/test/test_bitcount.c     |  71 ++++++++++++++++++
 lib/eal/include/rte_bitops.h | 168 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 241 insertions(+)
 create mode 100644 app/test/test_bitcount.c

diff --git a/app/test/meson.build b/app/test/meson.build
index f34d19e..d1277bc 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -13,6 +13,7 @@ test_sources = files(
         'test_alarm.c',
         'test_atomic.c',
         'test_barrier.c',
+        'test_bitcount.c',
         'test_bitops.c',
         'test_bitmap.c',
         'test_bpf.c',
@@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
 fast_tests = [
         ['acl_autotest', true, true],
         ['atomic_autotest', false, true],
+        ['bitcount_autotest', true, true],
         ['bitmap_autotest', true, true],
         ['bpf_autotest', true, true],
         ['bpf_convert_autotest', true, true],
diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
new file mode 100644
index 0000000..36eb05c
--- /dev/null
+++ b/app/test/test_bitcount.c
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#include <string.h>
+
+#include <rte_bitops.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
+
+static int
+test_clz32(void)
+{
+	uint32_t v = 1;
+	RTE_TEST_ASSERT(rte_clz32(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_clz64(void)
+{
+	uint64_t v = 1;
+	RTE_TEST_ASSERT(rte_clz64(v) == sizeof(v) * CHAR_BIT - 1,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctz32(void)
+{
+	uint32_t v = 2;
+	RTE_TEST_ASSERT(rte_ctz32(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_ctz64(void)
+{
+	uint64_t v = 2;
+	RTE_TEST_ASSERT(rte_ctz64(v) == 1, "Unexpected count.");
+
+	return 0;
+}
+
+static struct unit_test_suite bitcount_test_suite = {
+	.suite_name = "bitcount autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+		TEST_CASE(test_clz32),
+		TEST_CASE(test_clz64),
+		TEST_CASE(test_ctz32),
+		TEST_CASE(test_ctz64),
+		TEST_CASES_END()
+	}
+};
+
+static int
+test_bitcount(void)
+{
+	return unit_test_suite_runner(&bitcount_test_suite);
+}
+
+REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index 531479e..387d7aa 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2020 Arm Limited
+ * Copyright(c) 2010-2019 Intel Corporation
+ * Copyright(c) 2023 Microsoft Corporation
  */
 
 #ifndef _RTE_BITOPS_H_
@@ -275,6 +277,172 @@
 	return val & mask;
 }
 
+#ifdef RTE_TOOLCHAIN_MSVC
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+#else
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	return (unsigned int)__builtin_clz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	return (unsigned int)__builtin_clzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	return (unsigned int)__builtin_ctz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	return (unsigned int)__builtin_ctzll(v);
+}
+
+#endif
+
 /**
  * Combines 32b inputs most significant set bits into the least
  * significant bits to construct a value with the same MSBs as x
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-06 20:51                     ` Thomas Monjalon
@ 2023-01-10  9:18                       ` Ferruh Yigit
  0 siblings, 0 replies; 81+ messages in thread
From: Ferruh Yigit @ 2023-01-10  9:18 UTC (permalink / raw)
  To: Thomas Monjalon, Tyler Retzlaff
  Cc: Bruce Richardson, Stephen Hemminger, david.marchand, dev,
	Morten Brørup, honnappa.nagarahalli, jerinj, ktraynor,
	maxime.coquelin

On 1/6/2023 8:51 PM, Thomas Monjalon wrote:
> 06/01/2023 19:58, Tyler Retzlaff:
>> On Fri, Jan 06, 2023 at 02:40:59PM +0100, Thomas Monjalon wrote:
>>> 06/01/2023 13:41, Morten Brørup:
>>>>> From: Bruce Richardson [mailto:bruce.richardson@intel.com]
>>>>> Sent: Friday, 6 January 2023 12.48
>>>>>
>>>>> On Thu, Jan 05, 2023 at 04:32:40PM -0800, Stephen Hemminger wrote:
>>>>>> On Thu, 5 Jan 2023 09:21:18 -0800
>>>>>> Tyler Retzlaff <roretzla@linux.microsoft.com> wrote:
>>>>>>
>>>>>>> On Thu, Jan 05, 2023 at 10:01:31AM +0100, Thomas Monjalon wrote:
>>>>>>>> 05/01/2023 08:09, Morten Brørup:
>>>>>>>>>> From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
>>>>>>>>>> +/**
>>>>>>>>>> + * @warning
>>>>>>>>>> + * @b EXPERIMENTAL: this API may change, or be removed,
>>>>> without prior
>>>>>>>>>> notice
>>>>>>>>>> + *
>>>>>>>>>> + * Get the count of leading 0-bits in v.
>>>>>>>>>> + *
>>>>>>>>>> + * @param v
>>>>>>>>>> + *   The value.
>>>>>>>>>> + * @return
>>>>>>>>>> + *   The count of leading zero bits.
>>>>>>>>>> + */
>>>>>>>>>> +__rte_experimental
>>>>>>>>>> +static inline unsigned int
>>>>>>>>>> +rte_clzl(unsigned long v)
>>>>>>>>>
>>>>>>>>> Don't use l (long) and ll (long long) for names (and types),
>>>>> use explicit bit lengths, 32 and 64.
>>>>>>>>>
>>>>>>>>> E.g.: rte_clz32(uint32_t v)
>>>>>>>>
>>>>>>>> I agree on using numbers.
>>>>>>>>
>>>>>>>
>>>>>>> love the idea, fewer functions too.
>>>>>>>
>>>>>>> though it is a shame we cannot adopt C11 standard because we could
>>>>> just
>>>>>>> do away with the bit suffixes entirely.
>>>>>>
>>>>>> We could but the project needs to support older RHEL releases
>>>>>> which have older tool sets. Though probably this is moot point given
>>>>>> how much meson seems to change.
>>>>>
>>>>> True, though meson tends to be a bit easier to update than GCC on a
>>>>> system
>>>>> - no "pip3 install --upgrade gcc", sadly :-)
>>>>>
>>>>> If we can't go all the way to C11 support, how about at least going to
>>>>> C99
>>>>> support? As far as I know DPDK has never updated its minimum C-standard
>>>>> version, and it might be a good idea to start the process of doing so,
>>>>> even
>>>>> if it is a baby step.
>>>
>>> I am in favor of this baby step: define -std=c99 porject-wise
>>> and see what are the effects during the year.
>>>
>>>
>>>> The DPDK Getting Started Guide [1] says:
>>>>
>>>> "Required Tools and Libraries:
>>>> [...]
>>>> a supported C compiler such as gcc (version 4.9+)"
>>>>
>>>> GCC version 4.9 supports C11 [2]:
>>>> "GCC 4.9 Changes: "ISO C11 support is now at a similar level of completeness to ISO C99 support [...]"
>>>>
>>>> So why are we not going to support C11?
>>>
>>> We should make a plan to switch to C11 during next year.
>>>
>>>
>>>> Probably because of RHEL 7, which only provides GCC 4.8 [3].
>>>>
>>>> RHEL 7 was released for GA on June 10, 2014 [4]. If someone has a server with a nine year old distro still used in production, it is probably because it is running some legacy application, which is difficult to get up and running on a newer distro. Partial conclusion: RHEL 7 is probably still widely used in production.
>>>>
>>>> However, I have a hard time understanding why anyone would build and/or deploy a brand new DPDK application (based on DPDK 23.03) on such a server. Can someone please justify this?
>>>>
>>>> Are we really going to postpone C11 support in DPDK until June 30, 2026, when RHEL 7 ends its Extended Life Cycle Support [4]?
>>>
>>> RHEL does its own choices to support old software for long.
>>> Upstream development should move forward.
>>>
>>>
>>>> If so, then the GCC version mentioned in the DPDK Getting Started Guide should be corrected accordingly.
>>>
>>> No let's keep GCC 4.9 as a minimum for now.
>>> If needed we could upgrade it later.
>>
>> but i think the point Morten is making is that RHEL 7 gcc is 4.8 and
>> therefore we implicitly no longer support it if we document requiring
>> gcc 4.9.
> 
> Yes I got it.
> I think everything in DPDK works on RHEL 7 today,
> but I believe RHEL 7 is not a strong requirement anymore for the mainline.
> Asking for confirmation here.
> 
>> so i think the way to do this is through clarification at the next
>> release / ltsc release. starting with dpdk 23.xx will require
>> compiler conforming to standard X and optional features / annexes from
>> standard X. anyone building applications targeting that version of dpdk
>> release will need a conforming implementation.
>>
>> from there we just need to take care not to backport any code to
>> stable branches that depend on standard features that exceed the
>> requirements documented for that release.
> 
> We could even start testing C99 requirement in 23.03 I think.
> 
> 

I missed discussion in this thread, but replied in other thread,
replying here too.


+1 to switch C99 support.
There are bunch of C99 features used within DPDK already, and there were
some drivers compiled with c89 support, that restriction is removed now,
so it should be OK to move to C99 support.


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v4 2/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-09 17:36     ` [PATCH v4 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2023-01-10 13:55       ` Ferruh Yigit
  2023-01-10 17:34         ` Tyler Retzlaff
  2023-01-10 18:37         ` Tyler Retzlaff
  0 siblings, 2 replies; 81+ messages in thread
From: Ferruh Yigit @ 2023-01-10 13:55 UTC (permalink / raw)
  To: Tyler Retzlaff, dev; +Cc: thomas, mb, bruce.richardson, Tyler Retzlaff

On 1/9/2023 5:36 PM, Tyler Retzlaff wrote:
> From: Tyler Retzlaff <roretzla@microsoft.com>
> 
> Provide an abstraction for leading and trailing zero bit counting
> functions to hide compiler specific intrinsics and builtins.
> 
> Include basic unit test of following functions added.
> 
>     rte_clz32
>     rte_clz64
>     rte_ctz32
>     rte_ctz64
> 
> Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> ---
>  app/test/meson.build         |   2 +
>  app/test/test_bitcount.c     |  71 ++++++++++++++++++
>  lib/eal/include/rte_bitops.h | 168 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 241 insertions(+)
>  create mode 100644 app/test/test_bitcount.c
> 
> diff --git a/app/test/meson.build b/app/test/meson.build
> index f34d19e..d1277bc 100644
> --- a/app/test/meson.build
> +++ b/app/test/meson.build
> @@ -13,6 +13,7 @@ test_sources = files(
>          'test_alarm.c',
>          'test_atomic.c',
>          'test_barrier.c',
> +        'test_bitcount.c',
>          'test_bitops.c',
>          'test_bitmap.c',
>          'test_bpf.c',
> @@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
>  fast_tests = [
>          ['acl_autotest', true, true],
>          ['atomic_autotest', false, true],
> +        ['bitcount_autotest', true, true],
>          ['bitmap_autotest', true, true],
>          ['bpf_autotest', true, true],
>          ['bpf_convert_autotest', true, true],
> diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
> new file mode 100644
> index 0000000..36eb05c
> --- /dev/null
> +++ b/app/test/test_bitcount.c
> @@ -0,0 +1,71 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (C) 2022 Microsoft Corporation
> + */
> +
> +#include <string.h>
> +
> +#include <rte_bitops.h>
> +#include <rte_debug.h>
> +
> +#include "test.h"
> +
> +RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
> +
> +static int
> +test_clz32(void)
> +{
> +	uint32_t v = 1;
> +	RTE_TEST_ASSERT(rte_clz32(v) == sizeof(v) * CHAR_BIT - 1,
> +	    "Unexpected count.");
> +
> +	return 0;
> +}
> +
> +static int
> +test_clz64(void)
> +{
> +	uint64_t v = 1;
> +	RTE_TEST_ASSERT(rte_clz64(v) == sizeof(v) * CHAR_BIT - 1,
> +	    "Unexpected count.");
> +
> +	return 0;
> +}
> +
> +static int
> +test_ctz32(void)
> +{
> +	uint32_t v = 2;
> +	RTE_TEST_ASSERT(rte_ctz32(v) == 1, "Unexpected count.");
> +
> +	return 0;
> +}
> +
> +static int
> +test_ctz64(void)
> +{
> +	uint64_t v = 2;
> +	RTE_TEST_ASSERT(rte_ctz64(v) == 1, "Unexpected count.");
> +
> +	return 0;
> +}
> +
> +static struct unit_test_suite bitcount_test_suite = {
> +	.suite_name = "bitcount autotest",
> +	.setup = NULL,
> +	.teardown = NULL,
> +	.unit_test_cases = {
> +		TEST_CASE(test_clz32),
> +		TEST_CASE(test_clz64),
> +		TEST_CASE(test_ctz32),
> +		TEST_CASE(test_ctz64),
> +		TEST_CASES_END()
> +	}
> +};
> +
> +static int
> +test_bitcount(void)
> +{
> +	return unit_test_suite_runner(&bitcount_test_suite);
> +}
> +
> +REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
> diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
> index 531479e..387d7aa 100644
> --- a/lib/eal/include/rte_bitops.h
> +++ b/lib/eal/include/rte_bitops.h
> @@ -1,5 +1,7 @@
>  /* SPDX-License-Identifier: BSD-3-Clause
>   * Copyright(c) 2020 Arm Limited
> + * Copyright(c) 2010-2019 Intel Corporation
> + * Copyright(c) 2023 Microsoft Corporation
>   */
>  
>  #ifndef _RTE_BITOPS_H_
> @@ -275,6 +277,172 @@
>  	return val & mask;
>  }
>  
> +#ifdef RTE_TOOLCHAIN_MSVC
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_clz32(uint32_t v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanReverse(&rv, v);
> +
> +	return (unsigned int)rv;
> +}


OK, this looks wrong to me,


'_BitScanReverse' is [1]:
"Search the mask data from most significant bit (MSB) to least
significant bit (LSB) for a set bit (1)."

As far as I can see index starts from zero and from lsb to msb.

So _BitScanReverse() returns following index values:
0x2 => 1
0xffffffff => 31

If above is correct, above function doesn't return number of leading
zeros, but it should return "31 - (unsigned int)rv".

Please check godbolt experiment for above:
https://godbolt.org/z/znYn54f57


As far as I can see unit test is correct, so above should fail with
windows compiler, and I assume you run unit test with windows compiler,
so probably I am missing something but please help me understand.



[1]
https://learn.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64?view=msvc-170

> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_clz64(uint64_t v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanReverse64(&rv, v);
> +
> +	return (unsigned int)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_ctz32(uint32_t v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanForward(&rv, v);
> +
> +	return (unsigned int)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_ctz64(uint64_t v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanForward64(&rv, v);
> +
> +	return (unsigned int)rv;
> +}
> +
> +#else
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_clz32(uint32_t v)
> +{
> +	return (unsigned int)__builtin_clz(v);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_clz64(uint64_t v)
> +{
> +	return (unsigned int)__builtin_clzll(v);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_ctz32(uint32_t v)
> +{
> +	return (unsigned int)__builtin_ctz(v);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned int
> +rte_ctz64(uint64_t v)
> +{
> +	return (unsigned int)__builtin_ctzll(v);
> +}

'rte_ctz32()' & 'rte_ctz64()' are practically exact same with
'rte_bsf32()' & 'rte_bsf64()',

Although I can see description is different, do we need same
functionality with new function name,
why not add 'rte_bsf32()' & 'rte_bsf64()' versions for the Windows?



btw, do you guys know what 'bsf' & 'fls' (rte_fls_u32) stands for?

> +
> +#endif
> +
>  /**
>   * Combines 32b inputs most significant set bits into the least
>   * significant bits to construct a value with the same MSBs as x


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v4 1/2] eal: move bit operation functions from common to bitops header
  2023-01-09 17:36     ` [PATCH v4 1/2] eal: move bit operation functions from common to bitops header Tyler Retzlaff
@ 2023-01-10 13:56       ` Ferruh Yigit
  0 siblings, 0 replies; 81+ messages in thread
From: Ferruh Yigit @ 2023-01-10 13:56 UTC (permalink / raw)
  To: Tyler Retzlaff, dev; +Cc: thomas, mb, bruce.richardson

On 1/9/2023 5:36 PM, Tyler Retzlaff wrote:
> Move the following inline functions from rte_common.h to rte_bitops.h
> 
>   rte_combine32ms1b
>   rte_combine64ms1b
>   rte_bsf32
>   rte_bsf32_safe
>   rte_bsf64
>   rte_bsf64_safe
>   rte_fls_u32
>   rte_fls_u64
>   rte_is_power_of_2
>   rte_align32pow2
>   rte_align32prevpow2
>   rte_align64pow2
>   rte_align64prevpow2
>   rte_log2_u32
>   rte_log2_u64
> 
> Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v4 0/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-09 17:36   ` [PATCH v4 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2023-01-09 17:36     ` [PATCH v4 1/2] eal: move bit operation functions from common to bitops header Tyler Retzlaff
  2023-01-09 17:36     ` [PATCH v4 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2023-01-10 13:56     ` Ferruh Yigit
  2 siblings, 0 replies; 81+ messages in thread
From: Ferruh Yigit @ 2023-01-10 13:56 UTC (permalink / raw)
  To: Tyler Retzlaff, dev; +Cc: thomas, mb, bruce.richardson

On 1/9/2023 5:36 PM, Tyler Retzlaff wrote:
> Move existing bit manipulation, log and npow functions from
> rte_common.h to rte_bitops.h
> 
> Provide leading and trailing zero bit count functions to abstract away
> compiler specific implementations.
> 
> Include basic unit test for new leading/trailing zero bit count functions.
> 
> v4:
>   * combine unit test commit into function addition commit
> 
> v3:
>   * rename to use 32/64 instead of l/ll suffixes
>   * add new functions to rte_bitops.h instead of new header
>   * move other bit functions from rte_common.h to rte_bitops.h
> 
> v2:
>   * use unsigned int instead of unsigned (checkpatches)
>   * match multiple include guard naming convention to rte_common.h
>   * add explicit extern "C" linkage to rte_bitcount.h
>     note: not really needed but checkpatches required
>   * add missing space around '-'
> 
> Tyler Retzlaff (2):
>   eal: move bit operation functions from common to bitops header
>   eal: provide leading and trailing zero bit count abstraction
> 

There are checkpatch / checkgitlog errors, can you please check them:

 - checkpatches:

### [PATCH] eal: provide leading and trailing zero bit count abstraction

WARNING:FROM_SIGN_OFF_MISMATCH: From:/Signed-off-by: email address
mismatch: 'From: Tyler Retzlaff <roretzla@microsoft.com>' !=
'Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>'

total: 0 errors, 1 warnings, 264 lines checked

1/2 valid patch

- check-git-log:
Headline too long:
        eal: move bit operation functions from common to bitops header



^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v4 2/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-10 13:55       ` Ferruh Yigit
@ 2023-01-10 17:34         ` Tyler Retzlaff
  2023-01-10 18:37         ` Tyler Retzlaff
  1 sibling, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-10 17:34 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, thomas, mb, bruce.richardson, Tyler Retzlaff

On Tue, Jan 10, 2023 at 01:55:59PM +0000, Ferruh Yigit wrote:
> On 1/9/2023 5:36 PM, Tyler Retzlaff wrote:
> > From: Tyler Retzlaff <roretzla@microsoft.com>
> > 
> > Provide an abstraction for leading and trailing zero bit counting
> > functions to hide compiler specific intrinsics and builtins.
> > 
> > Include basic unit test of following functions added.
> > 
> >     rte_clz32
> >     rte_clz64
> >     rte_ctz32
> >     rte_ctz64
> > 
> > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > ---
> >  app/test/meson.build         |   2 +
> >  app/test/test_bitcount.c     |  71 ++++++++++++++++++
> >  lib/eal/include/rte_bitops.h | 168 +++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 241 insertions(+)
> >  create mode 100644 app/test/test_bitcount.c
> > 
> > diff --git a/app/test/meson.build b/app/test/meson.build
> > index f34d19e..d1277bc 100644
> > --- a/app/test/meson.build
> > +++ b/app/test/meson.build
> > @@ -13,6 +13,7 @@ test_sources = files(
> >          'test_alarm.c',
> >          'test_atomic.c',
> >          'test_barrier.c',
> > +        'test_bitcount.c',
> >          'test_bitops.c',
> >          'test_bitmap.c',
> >          'test_bpf.c',
> > @@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
> >  fast_tests = [
> >          ['acl_autotest', true, true],
> >          ['atomic_autotest', false, true],
> > +        ['bitcount_autotest', true, true],
> >          ['bitmap_autotest', true, true],
> >          ['bpf_autotest', true, true],
> >          ['bpf_convert_autotest', true, true],
> > diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
> > new file mode 100644
> > index 0000000..36eb05c
> > --- /dev/null
> > +++ b/app/test/test_bitcount.c
> > @@ -0,0 +1,71 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright (C) 2022 Microsoft Corporation
> > + */
> > +
> > +#include <string.h>
> > +
> > +#include <rte_bitops.h>
> > +#include <rte_debug.h>
> > +
> > +#include "test.h"
> > +
> > +RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
> > +
> > +static int
> > +test_clz32(void)
> > +{
> > +	uint32_t v = 1;
> > +	RTE_TEST_ASSERT(rte_clz32(v) == sizeof(v) * CHAR_BIT - 1,
> > +	    "Unexpected count.");
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +test_clz64(void)
> > +{
> > +	uint64_t v = 1;
> > +	RTE_TEST_ASSERT(rte_clz64(v) == sizeof(v) * CHAR_BIT - 1,
> > +	    "Unexpected count.");
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +test_ctz32(void)
> > +{
> > +	uint32_t v = 2;
> > +	RTE_TEST_ASSERT(rte_ctz32(v) == 1, "Unexpected count.");
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +test_ctz64(void)
> > +{
> > +	uint64_t v = 2;
> > +	RTE_TEST_ASSERT(rte_ctz64(v) == 1, "Unexpected count.");
> > +
> > +	return 0;
> > +}
> > +
> > +static struct unit_test_suite bitcount_test_suite = {
> > +	.suite_name = "bitcount autotest",
> > +	.setup = NULL,
> > +	.teardown = NULL,
> > +	.unit_test_cases = {
> > +		TEST_CASE(test_clz32),
> > +		TEST_CASE(test_clz64),
> > +		TEST_CASE(test_ctz32),
> > +		TEST_CASE(test_ctz64),
> > +		TEST_CASES_END()
> > +	}
> > +};
> > +
> > +static int
> > +test_bitcount(void)
> > +{
> > +	return unit_test_suite_runner(&bitcount_test_suite);
> > +}
> > +
> > +REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
> > diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
> > index 531479e..387d7aa 100644
> > --- a/lib/eal/include/rte_bitops.h
> > +++ b/lib/eal/include/rte_bitops.h
> > @@ -1,5 +1,7 @@
> >  /* SPDX-License-Identifier: BSD-3-Clause
> >   * Copyright(c) 2020 Arm Limited
> > + * Copyright(c) 2010-2019 Intel Corporation
> > + * Copyright(c) 2023 Microsoft Corporation
> >   */
> >  
> >  #ifndef _RTE_BITOPS_H_
> > @@ -275,6 +277,172 @@
> >  	return val & mask;
> >  }
> >  
> > +#ifdef RTE_TOOLCHAIN_MSVC
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of leading 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of leading zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_clz32(uint32_t v)
> > +{
> > +	unsigned long rv;
> > +
> > +	(void)_BitScanReverse(&rv, v);
> > +
> > +	return (unsigned int)rv;
> > +}
> 
> 
> OK, this looks wrong to me,
> 
> 
> '_BitScanReverse' is [1]:
> "Search the mask data from most significant bit (MSB) to least
> significant bit (LSB) for a set bit (1)."
> 
> As far as I can see index starts from zero and from lsb to msb.
> 
> So _BitScanReverse() returns following index values:
> 0x2 => 1
> 0xffffffff => 31
> 
> If above is correct, above function doesn't return number of leading
> zeros, but it should return "31 - (unsigned int)rv".
> 
> Please check godbolt experiment for above:
> https://godbolt.org/z/znYn54f57
> 
> 
> As far as I can see unit test is correct, so above should fail with
> windows compiler, and I assume you run unit test with windows compiler,
> so probably I am missing something but please help me understand.
> 
> 
> 
> [1]
> https://learn.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64?view=msvc-170
> 
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of leading 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of leading zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_clz64(uint64_t v)
> > +{
> > +	unsigned long rv;
> > +
> > +	(void)_BitScanReverse64(&rv, v);
> > +
> > +	return (unsigned int)rv;
> > +}
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of trailing 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of trailing zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_ctz32(uint32_t v)
> > +{
> > +	unsigned long rv;
> > +
> > +	(void)_BitScanForward(&rv, v);
> > +
> > +	return (unsigned int)rv;
> > +}
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of trailing 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of trailing zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_ctz64(uint64_t v)
> > +{
> > +	unsigned long rv;
> > +
> > +	(void)_BitScanForward64(&rv, v);
> > +
> > +	return (unsigned int)rv;
> > +}
> > +
> > +#else
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of leading 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of leading zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_clz32(uint32_t v)
> > +{
> > +	return (unsigned int)__builtin_clz(v);
> > +}
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of leading 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of leading zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_clz64(uint64_t v)
> > +{
> > +	return (unsigned int)__builtin_clzll(v);
> > +}
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of trailing 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of trailing zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_ctz32(uint32_t v)
> > +{
> > +	return (unsigned int)__builtin_ctz(v);
> > +}
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of trailing 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of trailing zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_ctz64(uint64_t v)
> > +{
> > +	return (unsigned int)__builtin_ctzll(v);
> > +}
> 
> 'rte_ctz32()' & 'rte_ctz64()' are practically exact same with
> 'rte_bsf32()' & 'rte_bsf64()',
> 
> Although I can see description is different, do we need same
> functionality with new function name,
> why not add 'rte_bsf32()' & 'rte_bsf64()' versions for the Windows?

i agree. i need a consensus from reviewers if they think this series
should be changed.

if we do take bsf{32,64} instead then does that mean we ban the use of
__ctz{32,64} in dpdk? keeping in mind the end goal is portability.

> 
> 
> 
> btw, do you guys know what 'bsf' & 'fls' (rte_fls_u32) stands for?

no idea. before my time.

> 
> > +
> > +#endif
> > +
> >  /**
> >   * Combines 32b inputs most significant set bits into the least
> >   * significant bits to construct a value with the same MSBs as x

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v4 2/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-10 13:55       ` Ferruh Yigit
  2023-01-10 17:34         ` Tyler Retzlaff
@ 2023-01-10 18:37         ` Tyler Retzlaff
  1 sibling, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-10 18:37 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, thomas, mb, bruce.richardson, Tyler Retzlaff

On Tue, Jan 10, 2023 at 01:55:59PM +0000, Ferruh Yigit wrote:
> On 1/9/2023 5:36 PM, Tyler Retzlaff wrote:
> > From: Tyler Retzlaff <roretzla@microsoft.com>
> > 
> > Provide an abstraction for leading and trailing zero bit counting
> > functions to hide compiler specific intrinsics and builtins.
> > 
> > Include basic unit test of following functions added.
> > 
> >     rte_clz32
> >     rte_clz64
> >     rte_ctz32
> >     rte_ctz64
> > 
> > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > ---
> >  app/test/meson.build         |   2 +
> >  app/test/test_bitcount.c     |  71 ++++++++++++++++++
> >  lib/eal/include/rte_bitops.h | 168 +++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 241 insertions(+)
> >  create mode 100644 app/test/test_bitcount.c
> > 
> > diff --git a/app/test/meson.build b/app/test/meson.build
> > index f34d19e..d1277bc 100644
> > --- a/app/test/meson.build
> > +++ b/app/test/meson.build
> > @@ -13,6 +13,7 @@ test_sources = files(
> >          'test_alarm.c',
> >          'test_atomic.c',
> >          'test_barrier.c',
> > +        'test_bitcount.c',
> >          'test_bitops.c',
> >          'test_bitmap.c',
> >          'test_bpf.c',
> > @@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
> >  fast_tests = [
> >          ['acl_autotest', true, true],
> >          ['atomic_autotest', false, true],
> > +        ['bitcount_autotest', true, true],
> >          ['bitmap_autotest', true, true],
> >          ['bpf_autotest', true, true],
> >          ['bpf_convert_autotest', true, true],
> > diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
> > new file mode 100644
> > index 0000000..36eb05c
> > --- /dev/null
> > +++ b/app/test/test_bitcount.c
> > @@ -0,0 +1,71 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright (C) 2022 Microsoft Corporation
> > + */
> > +
> > +#include <string.h>
> > +
> > +#include <rte_bitops.h>
> > +#include <rte_debug.h>
> > +
> > +#include "test.h"
> > +
> > +RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
> > +
> > +static int
> > +test_clz32(void)
> > +{
> > +	uint32_t v = 1;
> > +	RTE_TEST_ASSERT(rte_clz32(v) == sizeof(v) * CHAR_BIT - 1,
> > +	    "Unexpected count.");
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +test_clz64(void)
> > +{
> > +	uint64_t v = 1;
> > +	RTE_TEST_ASSERT(rte_clz64(v) == sizeof(v) * CHAR_BIT - 1,
> > +	    "Unexpected count.");
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +test_ctz32(void)
> > +{
> > +	uint32_t v = 2;
> > +	RTE_TEST_ASSERT(rte_ctz32(v) == 1, "Unexpected count.");
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +test_ctz64(void)
> > +{
> > +	uint64_t v = 2;
> > +	RTE_TEST_ASSERT(rte_ctz64(v) == 1, "Unexpected count.");
> > +
> > +	return 0;
> > +}
> > +
> > +static struct unit_test_suite bitcount_test_suite = {
> > +	.suite_name = "bitcount autotest",
> > +	.setup = NULL,
> > +	.teardown = NULL,
> > +	.unit_test_cases = {
> > +		TEST_CASE(test_clz32),
> > +		TEST_CASE(test_clz64),
> > +		TEST_CASE(test_ctz32),
> > +		TEST_CASE(test_ctz64),
> > +		TEST_CASES_END()
> > +	}
> > +};
> > +
> > +static int
> > +test_bitcount(void)
> > +{
> > +	return unit_test_suite_runner(&bitcount_test_suite);
> > +}
> > +
> > +REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
> > diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
> > index 531479e..387d7aa 100644
> > --- a/lib/eal/include/rte_bitops.h
> > +++ b/lib/eal/include/rte_bitops.h
> > @@ -1,5 +1,7 @@
> >  /* SPDX-License-Identifier: BSD-3-Clause
> >   * Copyright(c) 2020 Arm Limited
> > + * Copyright(c) 2010-2019 Intel Corporation
> > + * Copyright(c) 2023 Microsoft Corporation
> >   */
> >  
> >  #ifndef _RTE_BITOPS_H_
> > @@ -275,6 +277,172 @@
> >  	return val & mask;
> >  }
> >  
> > +#ifdef RTE_TOOLCHAIN_MSVC
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get the count of leading 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of leading zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_clz32(uint32_t v)
> > +{
> > +	unsigned long rv;
> > +
> > +	(void)_BitScanReverse(&rv, v);
> > +
> > +	return (unsigned int)rv;
> > +}
> 
> 
> OK, this looks wrong to me,
> 
> 
> '_BitScanReverse' is [1]:
> "Search the mask data from most significant bit (MSB) to least
> significant bit (LSB) for a set bit (1)."
> 
> As far as I can see index starts from zero and from lsb to msb.
> 
> So _BitScanReverse() returns following index values:
> 0x2 => 1
> 0xffffffff => 31
> 
> If above is correct, above function doesn't return number of leading
> zeros, but it should return "31 - (unsigned int)rv".
> 
> Please check godbolt experiment for above:
> https://godbolt.org/z/znYn54f57
> 
> 
> As far as I can see unit test is correct, so above should fail with
> windows compiler, and I assume you run unit test with windows compiler,
> so probably I am missing something but please help me understand.

the test is wrong, i will fix both the test and the implementation.

thank you for the careful review.


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v5 0/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
                   ` (3 preceding siblings ...)
  2023-01-06 22:01 ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Tyler Retzlaff
@ 2023-01-10 19:38 ` Tyler Retzlaff
  2023-01-10 19:38   ` [PATCH v5 1/2] eal: move bit operation common to bitops header Tyler Retzlaff
  2023-01-10 19:38   ` [PATCH v5 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2023-01-10 19:46 ` [PATCH v6 0/2] " Tyler Retzlaff
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-10 19:38 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, ferruh.yigit, Tyler Retzlaff

Move existing bit manipulation, log and npow functions from
rte_common.h to rte_bitops.h

Provide leading and trailing zero bit count functions to abstract away
compiler specific implementations.

Include basic unit test for new leading/trailing zero bit count functions.

v5:
  * fix implementation of msvc versions of rte_clz{32,64}
    incorrect use of _BitscanReverse{,64} index.
  * fix and expand unit test to exercise full range of counting
    over uint{32,64}_t input values. (which would have caught
    above mistake).
  * reduce commit title length
  * correct commit author

v4:
  * combine unit test commit into function addition commit

v3:
  * rename to use 32/64 instead of l/ll suffixes
  * add new functions to rte_bitops.h instead of new header
  * move other bit functions from rte_common.h to rte_bitops.h

v2:
  * use unsigned int instead of unsigned (checkpatches)
  * match multiple include guard naming convention to rte_common.h
  * add explicit extern "C" linkage to rte_bitcount.h
    note: not really needed but checkpatches required
  * add missing space around '-'


Tyler Retzlaff (2):
  eal: move bit operation common to bitops header
  eal: provide leading and trailing zero bit count abstraction

 app/test/meson.build            |   2 +
 app/test/test_bitcount.c        |  86 ++++++++
 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 460 ++++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 -------------------------
 6 files changed, 550 insertions(+), 293 deletions(-)
 create mode 100644 app/test/test_bitcount.c

-- 

Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v5 1/2] eal: move bit operation common to bitops header
  2023-01-10 19:38 ` [PATCH v5 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2023-01-10 19:38   ` Tyler Retzlaff
  2023-01-10 19:38   ` [PATCH v5 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  1 sibling, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-10 19:38 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, ferruh.yigit, Tyler Retzlaff

Move the following inline functions from rte_common.h to rte_bitops.h

  rte_combine32ms1b
  rte_combine64ms1b
  rte_bsf32
  rte_bsf32_safe
  rte_bsf64
  rte_bsf64_safe
  rte_fls_u32
  rte_fls_u64
  rte_is_power_of_2
  rte_align32pow2
  rte_align32prevpow2
  rte_align64pow2
  rte_align64prevpow2
  rte_log2_u32
  rte_log2_u64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 292 +++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 ----------------------------------------
 4 files changed, 294 insertions(+), 293 deletions(-)

diff --git a/app/test/test_common.c b/app/test/test_common.c
index f89e1eb..cf4a2c7 100644
--- a/app/test/test_common.c
+++ b/app/test/test_common.c
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <math.h>
 #include <rte_common.h>
+#include <rte_bitops.h>
 #include <rte_hexdump.h>
 #include <rte_pause.h>
 
diff --git a/lib/eal/common/rte_reciprocal.c b/lib/eal/common/rte_reciprocal.c
index 42dfa44..d47dc47 100644
--- a/lib/eal/common/rte_reciprocal.c
+++ b/lib/eal/common/rte_reciprocal.c
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <rte_common.h>
+#include <rte_bitops.h>
 
 #include "rte_reciprocal.h"
 
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index f50dbe4..531479e 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -275,6 +275,298 @@
 	return val & mask;
 }
 
+/**
+ * Combines 32b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param x
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint32_t
+rte_combine32ms1b(uint32_t x)
+{
+	x |= x >> 1;
+	x |= x >> 2;
+	x |= x >> 4;
+	x |= x >> 8;
+	x |= x >> 16;
+
+	return x;
+}
+
+/**
+ * Combines 64b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param v
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint64_t
+rte_combine64ms1b(uint64_t v)
+{
+	v |= v >> 1;
+	v |= v >> 2;
+	v |= v >> 4;
+	v |= v >> 8;
+	v |= v >> 16;
+	v |= v >> 32;
+
+	return v;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf32(uint32_t v)
+{
+	return (uint32_t)__builtin_ctz(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf32_safe(uint32_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf32(v);
+	return 1;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf64(uint64_t v)
+{
+	return (uint32_t)__builtin_ctzll(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf64_safe(uint64_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf64(v);
+	return 1;
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 32.
+ * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u32(uint32_t x)
+{
+	return (x == 0) ? 0 : 32 - __builtin_clz(x);
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 64.
+ * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
+ *       rte_fls_u64(0x8000000000000000) = 64
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u64(uint64_t x)
+{
+	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
+}
+
+/*********** Macros to work with powers of 2 ********/
+
+/**
+ * Macro to return 1 if n is a power of 2, 0 otherwise
+ */
+#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
+
+/**
+ * Returns true if n is a power of 2
+ * @param n
+ *     Number to check
+ * @return 1 if true, 0 otherwise
+ */
+static inline int
+rte_is_power_of_2(uint32_t n)
+{
+	return n && !(n & (n - 1));
+}
+
+/**
+ * Aligns input parameter to the next power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint32_t
+rte_align32pow2(uint32_t x)
+{
+	x--;
+	x = rte_combine32ms1b(x);
+
+	return x + 1;
+}
+
+/**
+ * Aligns input parameter to the previous power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint32_t
+rte_align32prevpow2(uint32_t x)
+{
+	x = rte_combine32ms1b(x);
+
+	return x - (x >> 1);
+}
+
+/**
+ * Aligns 64b input parameter to the next power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint64_t
+rte_align64pow2(uint64_t v)
+{
+	v--;
+	v = rte_combine64ms1b(v);
+
+	return v + 1;
+}
+
+/**
+ * Aligns 64b input parameter to the previous power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint64_t
+rte_align64prevpow2(uint64_t v)
+{
+	v = rte_combine64ms1b(v);
+
+	return v - (v >> 1);
+}
+
+/**
+ * Return the rounded-up log2 of a integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u32(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u32(uint32_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align32pow2(v);
+	return rte_bsf32(v);
+}
+
+/**
+ * Return the rounded-up log2 of a 64-bit integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u64(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u64(uint64_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align64pow2(v);
+	/* we checked for v being 0 already, so no undefined behavior */
+	return rte_bsf64(v);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eal/include/rte_common.h b/lib/eal/include/rte_common.h
index 15765b4..c5ad69c 100644
--- a/lib/eal/include/rte_common.h
+++ b/lib/eal/include/rte_common.h
@@ -471,140 +471,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 /** Marker for 8B alignment in a structure. */
 __extension__ typedef uint64_t RTE_MARKER64[0];
 
-/**
- * Combines 32b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param x
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint32_t
-rte_combine32ms1b(uint32_t x)
-{
-	x |= x >> 1;
-	x |= x >> 2;
-	x |= x >> 4;
-	x |= x >> 8;
-	x |= x >> 16;
-
-	return x;
-}
-
-/**
- * Combines 64b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param v
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint64_t
-rte_combine64ms1b(uint64_t v)
-{
-	v |= v >> 1;
-	v |= v >> 2;
-	v |= v >> 4;
-	v |= v >> 8;
-	v |= v >> 16;
-	v |= v >> 32;
-
-	return v;
-}
-
-/*********** Macros to work with powers of 2 ********/
-
-/**
- * Macro to return 1 if n is a power of 2, 0 otherwise
- */
-#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
-
-/**
- * Returns true if n is a power of 2
- * @param n
- *     Number to check
- * @return 1 if true, 0 otherwise
- */
-static inline int
-rte_is_power_of_2(uint32_t n)
-{
-	return n && !(n & (n - 1));
-}
-
-/**
- * Aligns input parameter to the next power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint32_t
-rte_align32pow2(uint32_t x)
-{
-	x--;
-	x = rte_combine32ms1b(x);
-
-	return x + 1;
-}
-
-/**
- * Aligns input parameter to the previous power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint32_t
-rte_align32prevpow2(uint32_t x)
-{
-	x = rte_combine32ms1b(x);
-
-	return x - (x >> 1);
-}
-
-/**
- * Aligns 64b input parameter to the next power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint64_t
-rte_align64pow2(uint64_t v)
-{
-	v--;
-	v = rte_combine64ms1b(v);
-
-	return v + 1;
-}
-
-/**
- * Aligns 64b input parameter to the previous power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint64_t
-rte_align64prevpow2(uint64_t v)
-{
-	v = rte_combine64ms1b(v);
-
-	return v - (v >> 1);
-}
-
 /*********** Macros for calculating min and max **********/
 
 /**
@@ -629,165 +495,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 
 /*********** Other general functions / macros ********/
 
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf32(uint32_t v)
-{
-	return (uint32_t)__builtin_ctz(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf32_safe(uint32_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf32(v);
-	return 1;
-}
-
-/**
- * Return the rounded-up log2 of a integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u32(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u32(uint32_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align32pow2(v);
-	return rte_bsf32(v);
-}
-
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 32.
- * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u32(uint32_t x)
-{
-	return (x == 0) ? 0 : 32 - __builtin_clz(x);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf64(uint64_t v)
-{
-	return (uint32_t)__builtin_ctzll(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf64_safe(uint64_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf64(v);
-	return 1;
-}
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 64.
- * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
- *       rte_fls_u64(0x8000000000000000) = 64
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u64(uint64_t x)
-{
-	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
-}
-
-/**
- * Return the rounded-up log2 of a 64-bit integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u64(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u64(uint64_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align64pow2(v);
-	/* we checked for v being 0 already, so no undefined behavior */
-	return rte_bsf64(v);
-}
-
 #ifndef offsetof
 /** Return the offset of a field in a structure. */
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v5 2/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-10 19:38 ` [PATCH v5 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2023-01-10 19:38   ` [PATCH v5 1/2] eal: move bit operation common to bitops header Tyler Retzlaff
@ 2023-01-10 19:38   ` Tyler Retzlaff
  1 sibling, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-10 19:38 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, ferruh.yigit, Tyler Retzlaff

Provide an abstraction for leading and trailing zero bit counting
functions to hide compiler specific intrinsics and builtins.

Include basic unit test of following functions added.

    rte_clz32
    rte_clz64
    rte_ctz32
    rte_ctz64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 app/test/meson.build         |   2 +
 app/test/test_bitcount.c     |  94 ++++++++++++++++++++++++
 lib/eal/include/rte_bitops.h | 168 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 264 insertions(+)
 create mode 100644 app/test/test_bitcount.c

diff --git a/app/test/meson.build b/app/test/meson.build
index f34d19e..d1277bc 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -13,6 +13,7 @@ test_sources = files(
         'test_alarm.c',
         'test_atomic.c',
         'test_barrier.c',
+        'test_bitcount.c',
         'test_bitops.c',
         'test_bitmap.c',
         'test_bpf.c',
@@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
 fast_tests = [
         ['acl_autotest', true, true],
         ['atomic_autotest', false, true],
+        ['bitcount_autotest', true, true],
         ['bitmap_autotest', true, true],
         ['bpf_autotest', true, true],
         ['bpf_convert_autotest', true, true],
diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
new file mode 100644
index 0000000..1359bed
--- /dev/null
+++ b/app/test/test_bitcount.c
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <rte_bitops.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
+
+static int
+test_clz32(void)
+{
+	size_t leading;
+	uint32_t v = 0xffffffff;
+
+	for (leading = 0; v; leading++) {
+		RTE_TEST_ASSERT(rte_clz32(v) == leading,
+		    "Unexpected count.");
+		v >>= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_clz64(void)
+{
+	size_t leading;
+	uint64_t v = 0xffffffffffffffff;
+
+	for (leading = 0; v; leading++) {
+		RTE_TEST_ASSERT(rte_clz64(v) == leading,
+		    "Unexpected count.");
+		v >>= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_ctz32(void)
+{
+	size_t trailing;
+	uint32_t v = 1;
+
+	for (trailing = 0; v; trailing++) {
+		RTE_TEST_ASSERT(rte_ctz32(v) == trailing,
+		    "Unexpected count.");
+		v <<= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_ctz64(void)
+{
+	size_t trailing;
+	uint64_t v = 1;
+
+	for (trailing = 0; v; trailing++) {
+		RTE_TEST_ASSERT(rte_ctz64(v) == trailing,
+		    "Unexpected count.");
+		v <<= 1;
+	}
+
+	return 0;
+}
+
+static struct unit_test_suite bitcount_test_suite = {
+	.suite_name = "bitcount autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+		TEST_CASE(test_clz32),
+		TEST_CASE(test_clz64),
+		TEST_CASE(test_ctz32),
+		TEST_CASE(test_ctz64),
+		TEST_CASES_END()
+	}
+};
+
+static int
+test_bitcount(void)
+{
+	return unit_test_suite_runner(&bitcount_test_suite);
+}
+
+REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index 531479e..e578fc1 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2020 Arm Limited
+ * Copyright(c) 2010-2019 Intel Corporation
+ * Copyright(c) 2023 Microsoft Corporation
  */
 
 #ifndef _RTE_BITOPS_H_
@@ -275,6 +277,172 @@
 	return val & mask;
 }
 
+#ifdef RTE_TOOLCHAIN_MSVC
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse64(&rv, v);
+
+	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+#else
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	return (unsigned int)__builtin_clz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	return (unsigned int)__builtin_clzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	return (unsigned int)__builtin_ctz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	return (unsigned int)__builtin_ctzll(v);
+}
+
+#endif
+
 /**
  * Combines 32b inputs most significant set bits into the least
  * significant bits to construct a value with the same MSBs as x
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v6 0/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
                   ` (4 preceding siblings ...)
  2023-01-10 19:38 ` [PATCH v5 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2023-01-10 19:46 ` Tyler Retzlaff
  2023-01-10 19:46   ` [PATCH v6 1/2] eal: move bit operation common to bitops header Tyler Retzlaff
                     ` (2 more replies)
  2023-04-01  0:45 ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Tyler Retzlaff
  2023-04-04  0:11 ` [PATCH v8 0/3] " Tyler Retzlaff
  7 siblings, 3 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-10 19:46 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, ferruh.yigit, Tyler Retzlaff

v6:
  * remove stray #include <stdio.h>

v5:
  * fix implementation of msvc versions of rte_clz{32,64}
    incorrect use of _BitscanReverse{,64} index.
  * fix and expand unit test to exercise full range of counting
    over uint{32,64}_t input values. (which would have caught
    above mistake).
  * reduce commit title length
  * correct commit author

v4:
  * combine unit test commit into function addition commit

v3:
  * rename to use 32/64 instead of l/ll suffixes
  * add new functions to rte_bitops.h instead of new header
  * move other bit functions from rte_common.h to rte_bitops.h

v2:
  * use unsigned int instead of unsigned (checkpatches)
  * match multiple include guard naming convention to rte_common.h
  * add explicit extern "C" linkage to rte_bitcount.h
    note: not really needed but checkpatches required
  * add missing space around '-'

Tyler Retzlaff (2):
  eal: move bit operation common to bitops header
  eal: provide leading and trailing zero bit count abstraction

 app/test/meson.build            |   2 +
 app/test/test_bitcount.c        |  93 ++++++++
 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 460 ++++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 -------------------------
 6 files changed, 557 insertions(+), 293 deletions(-)
 create mode 100644 app/test/test_bitcount.c

-- 

Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v6 1/2] eal: move bit operation common to bitops header
  2023-01-10 19:46 ` [PATCH v6 0/2] " Tyler Retzlaff
@ 2023-01-10 19:46   ` Tyler Retzlaff
  2023-01-10 19:46   ` [PATCH v6 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
  2023-01-20 22:14   ` [PATCH v6 0/2] " Tyler Retzlaff
  2 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-10 19:46 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, ferruh.yigit, Tyler Retzlaff

Move the following inline functions from rte_common.h to rte_bitops.h

  rte_combine32ms1b
  rte_combine64ms1b
  rte_bsf32
  rte_bsf32_safe
  rte_bsf64
  rte_bsf64_safe
  rte_fls_u32
  rte_fls_u64
  rte_is_power_of_2
  rte_align32pow2
  rte_align32prevpow2
  rte_align64pow2
  rte_align64prevpow2
  rte_log2_u32
  rte_log2_u64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---

Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 292 +++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 ----------------------------------------
 4 files changed, 294 insertions(+), 293 deletions(-)

diff --git a/app/test/test_common.c b/app/test/test_common.c
index f89e1eb..cf4a2c7 100644
--- a/app/test/test_common.c
+++ b/app/test/test_common.c
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <math.h>
 #include <rte_common.h>
+#include <rte_bitops.h>
 #include <rte_hexdump.h>
 #include <rte_pause.h>
 
diff --git a/lib/eal/common/rte_reciprocal.c b/lib/eal/common/rte_reciprocal.c
index 42dfa44..d47dc47 100644
--- a/lib/eal/common/rte_reciprocal.c
+++ b/lib/eal/common/rte_reciprocal.c
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <rte_common.h>
+#include <rte_bitops.h>
 
 #include "rte_reciprocal.h"
 
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index f50dbe4..531479e 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -275,6 +275,298 @@
 	return val & mask;
 }
 
+/**
+ * Combines 32b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param x
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint32_t
+rte_combine32ms1b(uint32_t x)
+{
+	x |= x >> 1;
+	x |= x >> 2;
+	x |= x >> 4;
+	x |= x >> 8;
+	x |= x >> 16;
+
+	return x;
+}
+
+/**
+ * Combines 64b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param v
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint64_t
+rte_combine64ms1b(uint64_t v)
+{
+	v |= v >> 1;
+	v |= v >> 2;
+	v |= v >> 4;
+	v |= v >> 8;
+	v |= v >> 16;
+	v |= v >> 32;
+
+	return v;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf32(uint32_t v)
+{
+	return (uint32_t)__builtin_ctz(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf32_safe(uint32_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf32(v);
+	return 1;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf64(uint64_t v)
+{
+	return (uint32_t)__builtin_ctzll(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf64_safe(uint64_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf64(v);
+	return 1;
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 32.
+ * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u32(uint32_t x)
+{
+	return (x == 0) ? 0 : 32 - __builtin_clz(x);
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 64.
+ * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
+ *       rte_fls_u64(0x8000000000000000) = 64
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u64(uint64_t x)
+{
+	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
+}
+
+/*********** Macros to work with powers of 2 ********/
+
+/**
+ * Macro to return 1 if n is a power of 2, 0 otherwise
+ */
+#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
+
+/**
+ * Returns true if n is a power of 2
+ * @param n
+ *     Number to check
+ * @return 1 if true, 0 otherwise
+ */
+static inline int
+rte_is_power_of_2(uint32_t n)
+{
+	return n && !(n & (n - 1));
+}
+
+/**
+ * Aligns input parameter to the next power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint32_t
+rte_align32pow2(uint32_t x)
+{
+	x--;
+	x = rte_combine32ms1b(x);
+
+	return x + 1;
+}
+
+/**
+ * Aligns input parameter to the previous power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint32_t
+rte_align32prevpow2(uint32_t x)
+{
+	x = rte_combine32ms1b(x);
+
+	return x - (x >> 1);
+}
+
+/**
+ * Aligns 64b input parameter to the next power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint64_t
+rte_align64pow2(uint64_t v)
+{
+	v--;
+	v = rte_combine64ms1b(v);
+
+	return v + 1;
+}
+
+/**
+ * Aligns 64b input parameter to the previous power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint64_t
+rte_align64prevpow2(uint64_t v)
+{
+	v = rte_combine64ms1b(v);
+
+	return v - (v >> 1);
+}
+
+/**
+ * Return the rounded-up log2 of a integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u32(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u32(uint32_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align32pow2(v);
+	return rte_bsf32(v);
+}
+
+/**
+ * Return the rounded-up log2 of a 64-bit integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u64(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u64(uint64_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align64pow2(v);
+	/* we checked for v being 0 already, so no undefined behavior */
+	return rte_bsf64(v);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eal/include/rte_common.h b/lib/eal/include/rte_common.h
index 15765b4..c5ad69c 100644
--- a/lib/eal/include/rte_common.h
+++ b/lib/eal/include/rte_common.h
@@ -471,140 +471,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 /** Marker for 8B alignment in a structure. */
 __extension__ typedef uint64_t RTE_MARKER64[0];
 
-/**
- * Combines 32b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param x
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint32_t
-rte_combine32ms1b(uint32_t x)
-{
-	x |= x >> 1;
-	x |= x >> 2;
-	x |= x >> 4;
-	x |= x >> 8;
-	x |= x >> 16;
-
-	return x;
-}
-
-/**
- * Combines 64b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param v
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint64_t
-rte_combine64ms1b(uint64_t v)
-{
-	v |= v >> 1;
-	v |= v >> 2;
-	v |= v >> 4;
-	v |= v >> 8;
-	v |= v >> 16;
-	v |= v >> 32;
-
-	return v;
-}
-
-/*********** Macros to work with powers of 2 ********/
-
-/**
- * Macro to return 1 if n is a power of 2, 0 otherwise
- */
-#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
-
-/**
- * Returns true if n is a power of 2
- * @param n
- *     Number to check
- * @return 1 if true, 0 otherwise
- */
-static inline int
-rte_is_power_of_2(uint32_t n)
-{
-	return n && !(n & (n - 1));
-}
-
-/**
- * Aligns input parameter to the next power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint32_t
-rte_align32pow2(uint32_t x)
-{
-	x--;
-	x = rte_combine32ms1b(x);
-
-	return x + 1;
-}
-
-/**
- * Aligns input parameter to the previous power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint32_t
-rte_align32prevpow2(uint32_t x)
-{
-	x = rte_combine32ms1b(x);
-
-	return x - (x >> 1);
-}
-
-/**
- * Aligns 64b input parameter to the next power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint64_t
-rte_align64pow2(uint64_t v)
-{
-	v--;
-	v = rte_combine64ms1b(v);
-
-	return v + 1;
-}
-
-/**
- * Aligns 64b input parameter to the previous power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint64_t
-rte_align64prevpow2(uint64_t v)
-{
-	v = rte_combine64ms1b(v);
-
-	return v - (v >> 1);
-}
-
 /*********** Macros for calculating min and max **********/
 
 /**
@@ -629,165 +495,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 
 /*********** Other general functions / macros ********/
 
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf32(uint32_t v)
-{
-	return (uint32_t)__builtin_ctz(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf32_safe(uint32_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf32(v);
-	return 1;
-}
-
-/**
- * Return the rounded-up log2 of a integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u32(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u32(uint32_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align32pow2(v);
-	return rte_bsf32(v);
-}
-
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 32.
- * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u32(uint32_t x)
-{
-	return (x == 0) ? 0 : 32 - __builtin_clz(x);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf64(uint64_t v)
-{
-	return (uint32_t)__builtin_ctzll(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf64_safe(uint64_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf64(v);
-	return 1;
-}
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 64.
- * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
- *       rte_fls_u64(0x8000000000000000) = 64
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u64(uint64_t x)
-{
-	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
-}
-
-/**
- * Return the rounded-up log2 of a 64-bit integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u64(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u64(uint64_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align64pow2(v);
-	/* we checked for v being 0 already, so no undefined behavior */
-	return rte_bsf64(v);
-}
-
 #ifndef offsetof
 /** Return the offset of a field in a structure. */
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v6 2/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-10 19:46 ` [PATCH v6 0/2] " Tyler Retzlaff
  2023-01-10 19:46   ` [PATCH v6 1/2] eal: move bit operation common to bitops header Tyler Retzlaff
@ 2023-01-10 19:46   ` Tyler Retzlaff
  2023-01-20 22:14   ` [PATCH v6 0/2] " Tyler Retzlaff
  2 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-10 19:46 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, ferruh.yigit, Tyler Retzlaff

Provide an abstraction for leading and trailing zero bit counting
functions to hide compiler specific intrinsics and builtins.

Include basic unit test of following functions added.

    rte_clz32
    rte_clz64
    rte_ctz32
    rte_ctz64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 app/test/meson.build         |   2 +
 app/test/test_bitcount.c     |  93 ++++++++++++++++++++++++
 lib/eal/include/rte_bitops.h | 168 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 263 insertions(+)
 create mode 100644 app/test/test_bitcount.c

diff --git a/app/test/meson.build b/app/test/meson.build
index f34d19e..d1277bc 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -13,6 +13,7 @@ test_sources = files(
         'test_alarm.c',
         'test_atomic.c',
         'test_barrier.c',
+        'test_bitcount.c',
         'test_bitops.c',
         'test_bitmap.c',
         'test_bpf.c',
@@ -160,6 +161,7 @@ test_deps += ['bus_pci', 'bus_vdev']
 fast_tests = [
         ['acl_autotest', true, true],
         ['atomic_autotest', false, true],
+        ['bitcount_autotest', true, true],
         ['bitmap_autotest', true, true],
         ['bpf_autotest', true, true],
         ['bpf_convert_autotest', true, true],
diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
new file mode 100644
index 0000000..a3ef2a5
--- /dev/null
+++ b/app/test/test_bitcount.c
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#include <string.h>
+
+#include <rte_bitops.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
+
+static int
+test_clz32(void)
+{
+	size_t leading;
+	uint32_t v = 0xffffffff;
+
+	for (leading = 0; v; leading++) {
+		RTE_TEST_ASSERT(rte_clz32(v) == leading,
+		    "Unexpected count.");
+		v >>= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_clz64(void)
+{
+	size_t leading;
+	uint64_t v = 0xffffffffffffffff;
+
+	for (leading = 0; v; leading++) {
+		RTE_TEST_ASSERT(rte_clz64(v) == leading,
+		    "Unexpected count.");
+		v >>= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_ctz32(void)
+{
+	size_t trailing;
+	uint32_t v = 1;
+
+	for (trailing = 0; v; trailing++) {
+		RTE_TEST_ASSERT(rte_ctz32(v) == trailing,
+		    "Unexpected count.");
+		v <<= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_ctz64(void)
+{
+	size_t trailing;
+	uint64_t v = 1;
+
+	for (trailing = 0; v; trailing++) {
+		RTE_TEST_ASSERT(rte_ctz64(v) == trailing,
+		    "Unexpected count.");
+		v <<= 1;
+	}
+
+	return 0;
+}
+
+static struct unit_test_suite bitcount_test_suite = {
+	.suite_name = "bitcount autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+		TEST_CASE(test_clz32),
+		TEST_CASE(test_clz64),
+		TEST_CASE(test_ctz32),
+		TEST_CASE(test_ctz64),
+		TEST_CASES_END()
+	}
+};
+
+static int
+test_bitcount(void)
+{
+	return unit_test_suite_runner(&bitcount_test_suite);
+}
+
+REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index 531479e..e578fc1 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2020 Arm Limited
+ * Copyright(c) 2010-2019 Intel Corporation
+ * Copyright(c) 2023 Microsoft Corporation
  */
 
 #ifndef _RTE_BITOPS_H_
@@ -275,6 +277,172 @@
 	return val & mask;
 }
 
+#ifdef RTE_TOOLCHAIN_MSVC
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse64(&rv, v);
+
+	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+#else
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	return (unsigned int)__builtin_clz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	return (unsigned int)__builtin_clzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	return (unsigned int)__builtin_ctz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	return (unsigned int)__builtin_ctzll(v);
+}
+
+#endif
+
 /**
  * Combines 32b inputs most significant set bits into the least
  * significant bits to construct a value with the same MSBs as x
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v6 0/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-10 19:46 ` [PATCH v6 0/2] " Tyler Retzlaff
  2023-01-10 19:46   ` [PATCH v6 1/2] eal: move bit operation common to bitops header Tyler Retzlaff
  2023-01-10 19:46   ` [PATCH v6 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2023-01-20 22:14   ` Tyler Retzlaff
  2023-02-02  9:14     ` David Marchand
  2 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-01-20 22:14 UTC (permalink / raw)
  To: dev; +Cc: thomas, mb, bruce.richardson, ferruh.yigit, david.marchand

hi folks,

i think this one can probably be merged?

Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>
patch 1/2 Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

thanks!

On Tue, Jan 10, 2023 at 11:46:39AM -0800, Tyler Retzlaff wrote:
> v6:
>   * remove stray #include <stdio.h>
> 
> v5:
>   * fix implementation of msvc versions of rte_clz{32,64}
>     incorrect use of _BitscanReverse{,64} index.
>   * fix and expand unit test to exercise full range of counting
>     over uint{32,64}_t input values. (which would have caught
>     above mistake).
>   * reduce commit title length
>   * correct commit author
> 
> v4:
>   * combine unit test commit into function addition commit
> 
> v3:
>   * rename to use 32/64 instead of l/ll suffixes
>   * add new functions to rte_bitops.h instead of new header
>   * move other bit functions from rte_common.h to rte_bitops.h
> 
> v2:
>   * use unsigned int instead of unsigned (checkpatches)
>   * match multiple include guard naming convention to rte_common.h
>   * add explicit extern "C" linkage to rte_bitcount.h
>     note: not really needed but checkpatches required
>   * add missing space around '-'
> 
> Tyler Retzlaff (2):
>   eal: move bit operation common to bitops header
>   eal: provide leading and trailing zero bit count abstraction
> 
>  app/test/meson.build            |   2 +
>  app/test/test_bitcount.c        |  93 ++++++++
>  app/test/test_common.c          |   1 +
>  lib/eal/common/rte_reciprocal.c |   1 +
>  lib/eal/include/rte_bitops.h    | 460 ++++++++++++++++++++++++++++++++++++++++
>  lib/eal/include/rte_common.h    | 293 -------------------------
>  6 files changed, 557 insertions(+), 293 deletions(-)
>  create mode 100644 app/test/test_bitcount.c
> 
> -- 
> 
> Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
> Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v6 0/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-20 22:14   ` [PATCH v6 0/2] " Tyler Retzlaff
@ 2023-02-02  9:14     ` David Marchand
  2023-02-02 10:56       ` David Marchand
  2023-02-02 15:56       ` Tyler Retzlaff
  0 siblings, 2 replies; 81+ messages in thread
From: David Marchand @ 2023-02-02  9:14 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: dev, thomas, mb, bruce.richardson, ferruh.yigit

Hello Tyler,

On Fri, Jan 20, 2023 at 11:14 PM Tyler Retzlaff
<roretzla@linux.microsoft.com> wrote:
>
> hi folks,
>
> i think this one can probably be merged?
>
> Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
> Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>
> patch 1/2 Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>

I like the cleanup of rte_common.h and additional unit tests, but the
MSVC bits don't belong here.
Please move them in your MSVC enablement series
https://patchwork.dpdk.org/project/dpdk/list/?series=26662&state=%2A&archive=both.


Thanks.
-- 
David Marchand


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v6 0/2] eal: provide leading and trailing zero bit count abstraction
  2023-02-02  9:14     ` David Marchand
@ 2023-02-02 10:56       ` David Marchand
  2023-02-02 15:57         ` Tyler Retzlaff
  2023-02-02 15:56       ` Tyler Retzlaff
  1 sibling, 1 reply; 81+ messages in thread
From: David Marchand @ 2023-02-02 10:56 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: dev, thomas, mb, bruce.richardson, ferruh.yigit

On Thu, Feb 2, 2023 at 10:14 AM David Marchand
<david.marchand@redhat.com> wrote:
>
> Hello Tyler,
>
> On Fri, Jan 20, 2023 at 11:14 PM Tyler Retzlaff
> <roretzla@linux.microsoft.com> wrote:
> >
> > hi folks,
> >
> > i think this one can probably be merged?
> >
> > Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
> > Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>
> > patch 1/2 Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>
>
> I like the cleanup of rte_common.h and additional unit tests, but the
> MSVC bits don't belong here.
> Please move them in your MSVC enablement series
> https://patchwork.dpdk.org/project/dpdk/list/?series=26662&state=%2A&archive=both.

Addendum, running the series through my checks, I can see that
test_bitcount.c is left unattended wrt the MAINTAINERS file.
app/test/test_bitcount.c must be put under the "EAL API and common
code" section.

Thanks.
-- 
David Marchand


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v6 0/2] eal: provide leading and trailing zero bit count abstraction
  2023-02-02  9:14     ` David Marchand
  2023-02-02 10:56       ` David Marchand
@ 2023-02-02 15:56       ` Tyler Retzlaff
  2023-02-03  9:21         ` David Marchand
  1 sibling, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-02-02 15:56 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, thomas, mb, bruce.richardson, ferruh.yigit

On Thu, Feb 02, 2023 at 10:14:41AM +0100, David Marchand wrote:
> Hello Tyler,
> 
> On Fri, Jan 20, 2023 at 11:14 PM Tyler Retzlaff
> <roretzla@linux.microsoft.com> wrote:
> >
> > hi folks,
> >
> > i think this one can probably be merged?
> >
> > Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
> > Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>
> > patch 1/2 Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>
> 
> I like the cleanup of rte_common.h and additional unit tests, but the
> MSVC bits don't belong here.
> Please move them in your MSVC enablement series

hm, the way i'm approaching this is to keep specific features together
similar to if i added new platform functionality for threads i add
windows or linux in the same series. similarly, in this case i'm adding
msvc and gcc in the same series.

the msvc enablement series introduces the changes for the build system
so it's about enabling a compiler not adding functionality to dpdk so
this change/API really aren't related to the other, but i agree the other
series is part of converging on the platform, toolchain combination
being enabled overall.

reconsider? if not i guess i'll just withdraw the actual API for now
and have to resubmit and review later since i don't think it belongs
mixed in with the compiler enablement.

> https://patchwork.dpdk.org/project/dpdk/list/?series=26662&state=%2A&archive=both.

if the msvc series were just merged, i think the above discussion would be
moot no?

anyway, i'll abide by whatever decision you go with.

thanks!

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v6 0/2] eal: provide leading and trailing zero bit count abstraction
  2023-02-02 10:56       ` David Marchand
@ 2023-02-02 15:57         ` Tyler Retzlaff
  2023-02-03  9:14           ` David Marchand
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-02-02 15:57 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, thomas, mb, bruce.richardson, ferruh.yigit

On Thu, Feb 02, 2023 at 11:56:41AM +0100, David Marchand wrote:
> On Thu, Feb 2, 2023 at 10:14 AM David Marchand
> <david.marchand@redhat.com> wrote:
> >
> > Hello Tyler,
> >
> > On Fri, Jan 20, 2023 at 11:14 PM Tyler Retzlaff
> > <roretzla@linux.microsoft.com> wrote:
> > >
> > > hi folks,
> > >
> > > i think this one can probably be merged?
> > >
> > > Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
> > > Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>
> > > patch 1/2 Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>
> >
> > I like the cleanup of rte_common.h and additional unit tests, but the
> > MSVC bits don't belong here.
> > Please move them in your MSVC enablement series
> > https://patchwork.dpdk.org/project/dpdk/list/?series=26662&state=%2A&archive=both.
> 
> Addendum, running the series through my checks, I can see that
> test_bitcount.c is left unattended wrt the MAINTAINERS file.
> app/test/test_bitcount.c must be put under the "EAL API and common
> code" section.

is this an automated check i should have run prior to submission?

either way i'll fix that up, sorry for the mistake.

> 
> Thanks.
> -- 
> David Marchand

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v6 0/2] eal: provide leading and trailing zero bit count abstraction
  2023-02-02 15:57         ` Tyler Retzlaff
@ 2023-02-03  9:14           ` David Marchand
  0 siblings, 0 replies; 81+ messages in thread
From: David Marchand @ 2023-02-03  9:14 UTC (permalink / raw)
  To: Tyler Retzlaff, thomas; +Cc: dev, mb, bruce.richardson, ferruh.yigit

On Thu, Feb 2, 2023 at 4:57 PM Tyler Retzlaff
<roretzla@linux.microsoft.com> wrote:
> > > I like the cleanup of rte_common.h and additional unit tests, but the
> > > MSVC bits don't belong here.
> > > Please move them in your MSVC enablement series
> > > https://patchwork.dpdk.org/project/dpdk/list/?series=26662&state=%2A&archive=both.
> >
> > Addendum, running the series through my checks, I can see that
> > test_bitcount.c is left unattended wrt the MAINTAINERS file.
> > app/test/test_bitcount.c must be put under the "EAL API and common
> > code" section.
>
> is this an automated check i should have run prior to submission?

The script is devtools/check-maintainers.sh.
But unfortunately it is not run in the CI as its author never made it
reliable enough: it has false positives / known issues / accepted
issues.
Users (I guess Thomas and I, maybe some subtree maintainers) keep a
local reference of this script output, and compare against it.

This is something that is rarely needed: in general additions are done
as a single component in MAINTAINERS, so people naturally add
themselves with the top level directory, and that's it.
So I guess our current check is good enough.


>
> either way i'll fix that up, sorry for the mistake.

No worries, this is not something you could easily find unless
grepping and looking how things were done for other unit tests.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v6 0/2] eal: provide leading and trailing zero bit count abstraction
  2023-02-02 15:56       ` Tyler Retzlaff
@ 2023-02-03  9:21         ` David Marchand
  0 siblings, 0 replies; 81+ messages in thread
From: David Marchand @ 2023-02-03  9:21 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: dev, thomas, mb, bruce.richardson, ferruh.yigit

On Thu, Feb 2, 2023 at 4:56 PM Tyler Retzlaff
<roretzla@linux.microsoft.com> wrote:
>
> On Thu, Feb 02, 2023 at 10:14:41AM +0100, David Marchand wrote:
> > Hello Tyler,
> >
> > On Fri, Jan 20, 2023 at 11:14 PM Tyler Retzlaff
> > <roretzla@linux.microsoft.com> wrote:
> > >
> > > hi folks,
> > >
> > > i think this one can probably be merged?
> > >
> > > Series-acked-by: Morten Brørup <mb@smartsharesystems.com>
> > > Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>
> > > patch 1/2 Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>
> >
> > I like the cleanup of rte_common.h and additional unit tests, but the
> > MSVC bits don't belong here.
> > Please move them in your MSVC enablement series
>
> hm, the way i'm approaching this is to keep specific features together
> similar to if i added new platform functionality for threads i add
> windows or linux in the same series. similarly, in this case i'm adding
> msvc and gcc in the same series.
>
> the msvc enablement series introduces the changes for the build system
> so it's about enabling a compiler not adding functionality to dpdk so
> this change/API really aren't related to the other, but i agree the other
> series is part of converging on the platform, toolchain combination
> being enabled overall.
>
> reconsider? if not i guess i'll just withdraw the actual API for now
> and have to resubmit and review later since i don't think it belongs
> mixed in with the compiler enablement.
>
> > https://patchwork.dpdk.org/project/dpdk/list/?series=26662&state=%2A&archive=both.
>
> if the msvc series were just merged, i think the above discussion would be
> moot no?

Indeed, but until we have support for MSVC, this part of the patch is
putting dead (untested) code in the tree.
It is also confusing to see references to MSVC in the tree while we
have nothing setting this config item, and no documentation explaining
how/when this will be actually usable.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v7 0/4] eal: provide abstracted bit counting functions
  2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
                   ` (5 preceding siblings ...)
  2023-01-10 19:46 ` [PATCH v6 0/2] " Tyler Retzlaff
@ 2023-04-01  0:45 ` Tyler Retzlaff
  2023-04-01  0:45   ` [PATCH v7 1/4] eal: move bit count functions to bitops header Tyler Retzlaff
                     ` (4 more replies)
  2023-04-04  0:11 ` [PATCH v8 0/3] " Tyler Retzlaff
  7 siblings, 5 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-01  0:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

As discussed technical board meeting 2023-02-22
http://mails.dpdk.org/archives/dev/2023-February/263516.html

We will bring support in pieces for the MSVC compiler, there will be
some abstractions and functions introduced before the compiler is
capable of compiling DPDK in order to make parallel progress
while waiting for standard atomics in 23.07.

A higher level plan / order of work is available in the Microsoft
roadmap for 23.07 and 23.11.

note:
Morten Brørup and Bruce Richardson previous acks have been preserved
but be aware of the two additional functions introduced in v7. If you
wish to withdraw your ack, please let me know but I believe the 2
additions are consistent with previous.

v7:
  * add 2 additional counting functions rte_popcount{32,64}
    including basic unit tests
  * fix patch 1 title link (CI complained too long)
  * add test_bitcount.c entry to MAINTAINERS file

v6:
  * remove stray #include <stdio.h>

v5:
  * fix implementation of msvc versions of rte_clz{32,64}
    incorrect use of _BitscanReverse{,64} index.
  * fix and expand unit test to exercise full range of counting
    over uint{32,64}_t input values. (which would have caught
    above mistake).
  * reduce commit title length
  * correct commit author

v4:
  * combine unit test commit into function addition commit

v3:
  * rename to use 32/64 instead of l/ll suffixes
  * add new functions to rte_bitops.h instead of new header
  * move other bit functions from rte_common.h to rte_bitops.h

v2:
  * use unsigned int instead of unsigned (checkpatches)
  * match multiple include guard naming convention to rte_common.h
  * add explicit extern "C" linkage to rte_bitcount.h
    note: not really needed but checkpatches required
  * add missing space around '-'


Tyler Retzlaff (4):
  eal: move bit count functions to bitops header
  eal: provide abstracted bit count functions
  pipeline: add include of bitops
  maintainers: add bitcount test under EAL API and common code

 MAINTAINERS                              |   1 +
 app/test/meson.build                     |   2 +
 app/test/test_bitcount.c                 | 136 ++++++++
 app/test/test_common.c                   |   1 +
 lib/eal/common/rte_reciprocal.c          |   1 +
 lib/eal/include/rte_bitops.h             | 532 +++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h             | 293 -----------------
 lib/pipeline/rte_swx_pipeline_internal.h |   1 +
 8 files changed, 674 insertions(+), 293 deletions(-)
 create mode 100644 app/test/test_bitcount.c

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v7 1/4] eal: move bit count functions to bitops header
  2023-04-01  0:45 ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Tyler Retzlaff
@ 2023-04-01  0:45   ` Tyler Retzlaff
  2023-04-01  0:45   ` [PATCH v7 2/4] eal: provide abstracted bit count functions Tyler Retzlaff
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-01  0:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

Move the following inline functions from rte_common.h to rte_bitops.h

  rte_combine32ms1b
  rte_combine64ms1b
  rte_bsf32
  rte_bsf32_safe
  rte_bsf64
  rte_bsf64_safe
  rte_fls_u32
  rte_fls_u64
  rte_is_power_of_2
  rte_align32pow2
  rte_align32prevpow2
  rte_align64pow2
  rte_align64prevpow2
  rte_log2_u32
  rte_log2_u64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 app/test/test_common.c          |   1 +
 lib/eal/common/rte_reciprocal.c |   1 +
 lib/eal/include/rte_bitops.h    | 292 +++++++++++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h    | 293 ----------------------------------------
 4 files changed, 294 insertions(+), 293 deletions(-)

diff --git a/app/test/test_common.c b/app/test/test_common.c
index f89e1eb..cf4a2c7 100644
--- a/app/test/test_common.c
+++ b/app/test/test_common.c
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <math.h>
 #include <rte_common.h>
+#include <rte_bitops.h>
 #include <rte_hexdump.h>
 #include <rte_pause.h>
 
diff --git a/lib/eal/common/rte_reciprocal.c b/lib/eal/common/rte_reciprocal.c
index 42dfa44..d47dc47 100644
--- a/lib/eal/common/rte_reciprocal.c
+++ b/lib/eal/common/rte_reciprocal.c
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <rte_common.h>
+#include <rte_bitops.h>
 
 #include "rte_reciprocal.h"
 
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index f50dbe4..531479e 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -275,6 +275,298 @@
 	return val & mask;
 }
 
+/**
+ * Combines 32b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param x
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint32_t
+rte_combine32ms1b(uint32_t x)
+{
+	x |= x >> 1;
+	x |= x >> 2;
+	x |= x >> 4;
+	x |= x >> 8;
+	x |= x >> 16;
+
+	return x;
+}
+
+/**
+ * Combines 64b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param v
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint64_t
+rte_combine64ms1b(uint64_t v)
+{
+	v |= v >> 1;
+	v |= v >> 2;
+	v |= v >> 4;
+	v |= v >> 8;
+	v |= v >> 16;
+	v |= v >> 32;
+
+	return v;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf32(uint32_t v)
+{
+	return (uint32_t)__builtin_ctz(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf32_safe(uint32_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf32(v);
+	return 1;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf64(uint64_t v)
+{
+	return (uint32_t)__builtin_ctzll(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf64_safe(uint64_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf64(v);
+	return 1;
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 32.
+ * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u32(uint32_t x)
+{
+	return (x == 0) ? 0 : 32 - __builtin_clz(x);
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 64.
+ * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
+ *       rte_fls_u64(0x8000000000000000) = 64
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u64(uint64_t x)
+{
+	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
+}
+
+/*********** Macros to work with powers of 2 ********/
+
+/**
+ * Macro to return 1 if n is a power of 2, 0 otherwise
+ */
+#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
+
+/**
+ * Returns true if n is a power of 2
+ * @param n
+ *     Number to check
+ * @return 1 if true, 0 otherwise
+ */
+static inline int
+rte_is_power_of_2(uint32_t n)
+{
+	return n && !(n & (n - 1));
+}
+
+/**
+ * Aligns input parameter to the next power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint32_t
+rte_align32pow2(uint32_t x)
+{
+	x--;
+	x = rte_combine32ms1b(x);
+
+	return x + 1;
+}
+
+/**
+ * Aligns input parameter to the previous power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint32_t
+rte_align32prevpow2(uint32_t x)
+{
+	x = rte_combine32ms1b(x);
+
+	return x - (x >> 1);
+}
+
+/**
+ * Aligns 64b input parameter to the next power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint64_t
+rte_align64pow2(uint64_t v)
+{
+	v--;
+	v = rte_combine64ms1b(v);
+
+	return v + 1;
+}
+
+/**
+ * Aligns 64b input parameter to the previous power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint64_t
+rte_align64prevpow2(uint64_t v)
+{
+	v = rte_combine64ms1b(v);
+
+	return v - (v >> 1);
+}
+
+/**
+ * Return the rounded-up log2 of a integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u32(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u32(uint32_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align32pow2(v);
+	return rte_bsf32(v);
+}
+
+/**
+ * Return the rounded-up log2 of a 64-bit integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u64(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u64(uint64_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align64pow2(v);
+	/* we checked for v being 0 already, so no undefined behavior */
+	return rte_bsf64(v);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eal/include/rte_common.h b/lib/eal/include/rte_common.h
index 15765b4..c5ad69c 100644
--- a/lib/eal/include/rte_common.h
+++ b/lib/eal/include/rte_common.h
@@ -471,140 +471,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 /** Marker for 8B alignment in a structure. */
 __extension__ typedef uint64_t RTE_MARKER64[0];
 
-/**
- * Combines 32b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param x
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint32_t
-rte_combine32ms1b(uint32_t x)
-{
-	x |= x >> 1;
-	x |= x >> 2;
-	x |= x >> 4;
-	x |= x >> 8;
-	x |= x >> 16;
-
-	return x;
-}
-
-/**
- * Combines 64b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param v
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint64_t
-rte_combine64ms1b(uint64_t v)
-{
-	v |= v >> 1;
-	v |= v >> 2;
-	v |= v >> 4;
-	v |= v >> 8;
-	v |= v >> 16;
-	v |= v >> 32;
-
-	return v;
-}
-
-/*********** Macros to work with powers of 2 ********/
-
-/**
- * Macro to return 1 if n is a power of 2, 0 otherwise
- */
-#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
-
-/**
- * Returns true if n is a power of 2
- * @param n
- *     Number to check
- * @return 1 if true, 0 otherwise
- */
-static inline int
-rte_is_power_of_2(uint32_t n)
-{
-	return n && !(n & (n - 1));
-}
-
-/**
- * Aligns input parameter to the next power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint32_t
-rte_align32pow2(uint32_t x)
-{
-	x--;
-	x = rte_combine32ms1b(x);
-
-	return x + 1;
-}
-
-/**
- * Aligns input parameter to the previous power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint32_t
-rte_align32prevpow2(uint32_t x)
-{
-	x = rte_combine32ms1b(x);
-
-	return x - (x >> 1);
-}
-
-/**
- * Aligns 64b input parameter to the next power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint64_t
-rte_align64pow2(uint64_t v)
-{
-	v--;
-	v = rte_combine64ms1b(v);
-
-	return v + 1;
-}
-
-/**
- * Aligns 64b input parameter to the previous power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint64_t
-rte_align64prevpow2(uint64_t v)
-{
-	v = rte_combine64ms1b(v);
-
-	return v - (v >> 1);
-}
-
 /*********** Macros for calculating min and max **********/
 
 /**
@@ -629,165 +495,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 
 /*********** Other general functions / macros ********/
 
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf32(uint32_t v)
-{
-	return (uint32_t)__builtin_ctz(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf32_safe(uint32_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf32(v);
-	return 1;
-}
-
-/**
- * Return the rounded-up log2 of a integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u32(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u32(uint32_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align32pow2(v);
-	return rte_bsf32(v);
-}
-
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 32.
- * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u32(uint32_t x)
-{
-	return (x == 0) ? 0 : 32 - __builtin_clz(x);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf64(uint64_t v)
-{
-	return (uint32_t)__builtin_ctzll(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf64_safe(uint64_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf64(v);
-	return 1;
-}
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 64.
- * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
- *       rte_fls_u64(0x8000000000000000) = 64
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u64(uint64_t x)
-{
-	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
-}
-
-/**
- * Return the rounded-up log2 of a 64-bit integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u64(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u64(uint64_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align64pow2(v);
-	/* we checked for v being 0 already, so no undefined behavior */
-	return rte_bsf64(v);
-}
-
 #ifndef offsetof
 /** Return the offset of a field in a structure. */
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v7 2/4] eal: provide abstracted bit count functions
  2023-04-01  0:45 ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Tyler Retzlaff
  2023-04-01  0:45   ` [PATCH v7 1/4] eal: move bit count functions to bitops header Tyler Retzlaff
@ 2023-04-01  0:45   ` Tyler Retzlaff
  2023-04-01  0:45   ` [PATCH v7 3/4] pipeline: add include of bitops Tyler Retzlaff
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-01  0:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

Provide abstracted bit counting functions for count, leading and
trailing bits in v to hide compiler specific intrinsics and builtins.

Include basic unit test of following functions added.

    rte_clz32
    rte_clz64
    rte_ctz32
    rte_ctz64
    rte_popcount32
    rte_popcount64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 app/test/meson.build         |   2 +
 app/test/test_bitcount.c     | 136 ++++++++++++++++++++++++
 lib/eal/include/rte_bitops.h | 240 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 378 insertions(+)
 create mode 100644 app/test/test_bitcount.c

diff --git a/app/test/meson.build b/app/test/meson.build
index b9b5432..dafd509 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -13,6 +13,7 @@ test_sources = files(
         'test_alarm.c',
         'test_atomic.c',
         'test_barrier.c',
+        'test_bitcount.c',
         'test_bitops.c',
         'test_bitmap.c',
         'test_bpf.c',
@@ -161,6 +162,7 @@ test_deps += ['bus_pci', 'bus_vdev']
 fast_tests = [
         ['acl_autotest', true, true],
         ['atomic_autotest', false, true],
+        ['bitcount_autotest', true, true],
         ['bitmap_autotest', true, true],
         ['bpf_autotest', true, true],
         ['bpf_convert_autotest', true, true],
diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
new file mode 100644
index 0000000..5287ef7
--- /dev/null
+++ b/app/test/test_bitcount.c
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#include <limits.h>
+#include <string.h>
+
+#include <rte_bitops.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
+
+static int
+test_clz32(void)
+{
+	size_t leading;
+	uint32_t v = 0xffffffff;
+
+	for (leading = 0; v; leading++) {
+		RTE_TEST_ASSERT(rte_clz32(v) == leading,
+		    "Unexpected count.");
+		v >>= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_clz64(void)
+{
+	size_t leading;
+	uint64_t v = 0xffffffffffffffff;
+
+	for (leading = 0; v; leading++) {
+		RTE_TEST_ASSERT(rte_clz64(v) == leading,
+		    "Unexpected count.");
+		v >>= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_ctz32(void)
+{
+	size_t trailing;
+	uint32_t v = 1;
+
+	for (trailing = 0; v; trailing++) {
+		RTE_TEST_ASSERT(rte_ctz32(v) == trailing,
+		    "Unexpected count.");
+		v <<= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_ctz64(void)
+{
+	size_t trailing;
+	uint64_t v = 1;
+
+	for (trailing = 0; v; trailing++) {
+		RTE_TEST_ASSERT(rte_ctz64(v) == trailing,
+		    "Unexpected count.");
+		v <<= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_popcount32(void)
+{
+	size_t shift;
+	uint32_t v = 0;
+	const size_t bits = sizeof(v) * CHAR_BIT;
+
+	for (shift = 0; shift < bits; shift++) {
+		RTE_TEST_ASSERT(rte_popcount32(v) == shift,
+		    "Unexpected count.");
+		v <<= 1;
+		v |= 1;
+	}
+
+	RTE_TEST_ASSERT(rte_popcount32(v) == bits,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_popcount64(void)
+{
+	size_t shift;
+	uint64_t v = 0;
+	const size_t bits = sizeof(v) * CHAR_BIT;
+
+	for (shift = 0; shift < bits; shift++) {
+		RTE_TEST_ASSERT(rte_popcount64(v) == shift,
+		    "Unexpected count.");
+		v <<= 1;
+		v |= 1;
+	}
+
+	RTE_TEST_ASSERT(rte_popcount64(v) == bits,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static struct unit_test_suite bitcount_test_suite = {
+	.suite_name = "bitcount autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+		TEST_CASE(test_clz32),
+		TEST_CASE(test_clz64),
+		TEST_CASE(test_ctz32),
+		TEST_CASE(test_ctz64),
+		TEST_CASE(test_popcount32),
+		TEST_CASE(test_popcount64),
+		TEST_CASES_END()
+	}
+};
+
+static int
+test_bitcount(void)
+{
+	return unit_test_suite_runner(&bitcount_test_suite);
+}
+
+REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index 531479e..d45aa54 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2020 Arm Limited
+ * Copyright(c) 2010-2019 Intel Corporation
+ * Copyright(c) 2023 Microsoft Corporation
  */
 
 #ifndef _RTE_BITOPS_H_
@@ -275,6 +277,244 @@
 	return val & mask;
 }
 
+#ifdef RTE_TOOLCHAIN_MSVC
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse64(&rv, v);
+
+	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of 1-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of 1-bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_popcount32(uint32_t v)
+{
+	return (unsigned int)__popcnt(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of 1-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of 1-bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_popcount64(uint64_t v)
+{
+	return (unsigned int)__popcnt64(v);
+}
+
+#else
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	return (unsigned int)__builtin_clz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	return (unsigned int)__builtin_clzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	return (unsigned int)__builtin_ctz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	return (unsigned int)__builtin_ctzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of 1-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of 1-bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_popcount32(uint32_t v)
+{
+	return (unsigned int)__builtin_popcount(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of 1-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of 1-bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_popcount64(uint64_t v)
+{
+	return (unsigned int)__builtin_popcountll(v);
+}
+
+#endif
+
 /**
  * Combines 32b inputs most significant set bits into the least
  * significant bits to construct a value with the same MSBs as x
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v7 3/4] pipeline: add include of bitops
  2023-04-01  0:45 ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Tyler Retzlaff
  2023-04-01  0:45   ` [PATCH v7 1/4] eal: move bit count functions to bitops header Tyler Retzlaff
  2023-04-01  0:45   ` [PATCH v7 2/4] eal: provide abstracted bit count functions Tyler Retzlaff
@ 2023-04-01  0:45   ` Tyler Retzlaff
  2023-04-01  0:45   ` [PATCH v7 4/4] maintainers: add bitcount test under EAL API and common code Tyler Retzlaff
  2023-04-01  7:08   ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Morten Brørup
  4 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-01  0:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

Include rte_bitops.h with the inline functions moving this include is
now needed.

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 lib/pipeline/rte_swx_pipeline_internal.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index 2f24e1a..a67b6e9 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -8,6 +8,7 @@
 #include <string.h>
 #include <sys/queue.h>
 
+#include <rte_bitops.h>
 #include <rte_byteorder.h>
 #include <rte_common.h>
 #include <rte_cycles.h>
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v7 4/4] maintainers: add bitcount test under EAL API and common code
  2023-04-01  0:45 ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Tyler Retzlaff
                     ` (2 preceding siblings ...)
  2023-04-01  0:45   ` [PATCH v7 3/4] pipeline: add include of bitops Tyler Retzlaff
@ 2023-04-01  0:45   ` Tyler Retzlaff
  2023-04-01  7:08   ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Morten Brørup
  4 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-01  0:45 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

List app/test/test_bitcount.c under EAL API and common code.

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8df23e5..c2995bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -155,6 +155,7 @@ F: doc/guides/prog_guide/env_abstraction_layer.rst
 F: app/test/test_alarm.c
 F: app/test/test_atomic.c
 F: app/test/test_barrier.c
+F: app/test/test_bitcount.c
 F: app/test/test_byteorder.c
 F: app/test/test_common.c
 F: app/test/test_cpuflags.c
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* RE: [PATCH v7 0/4] eal: provide abstracted bit counting functions
  2023-04-01  0:45 ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Tyler Retzlaff
                     ` (3 preceding siblings ...)
  2023-04-01  0:45   ` [PATCH v7 4/4] maintainers: add bitcount test under EAL API and common code Tyler Retzlaff
@ 2023-04-01  7:08   ` Morten Brørup
  4 siblings, 0 replies; 81+ messages in thread
From: Morten Brørup @ 2023-04-01  7:08 UTC (permalink / raw)
  To: Tyler Retzlaff, dev
  Cc: thomas, stephen, bruce.richardson, ferruh.yigit, david.marchand

> From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> Sent: Saturday, 1 April 2023 02.45

[...]

> 
> note:
> Morten Brørup and Bruce Richardson previous acks have been preserved
> but be aware of the two additional functions introduced in v7. If you
> wish to withdraw your ack, please let me know but I believe the 2
> additions are consistent with previous.

The additions check out OK. My Ack remains. :-)


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH 1/2] eal: provide leading and trailing zero bit count abstraction
  2022-11-23 22:14 ` [PATCH 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
@ 2023-04-03 21:46   ` Mattias Rönnblom
  0 siblings, 0 replies; 81+ messages in thread
From: Mattias Rönnblom @ 2023-04-03 21:46 UTC (permalink / raw)
  To: Tyler Retzlaff, dev

On 2022-11-23 23:14, Tyler Retzlaff wrote:
> Provide an abstraction for leading and trailing zero bit counting
> functions to hide compiler specific intrinsics and builtins.
> 
> Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> ---
>   lib/eal/include/meson.build    |   1 +
>   lib/eal/include/rte_bitcount.h | 257 +++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 258 insertions(+)
>   create mode 100644 lib/eal/include/rte_bitcount.h
> 
> diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
> index cfcd40a..8ff1d65 100644
> --- a/lib/eal/include/meson.build
> +++ b/lib/eal/include/meson.build
> @@ -5,6 +5,7 @@ includes += include_directories('.')
>   
>   headers += files(
>           'rte_alarm.h',
> +        'rte_bitcount.h',

Maybe rte_bitops.h should be the home of these new wrappers.

>           'rte_bitmap.h',
>           'rte_bitops.h',
>           'rte_branch_prediction.h',
> diff --git a/lib/eal/include/rte_bitcount.h b/lib/eal/include/rte_bitcount.h
> new file mode 100644
> index 0000000..2f4dd38
> --- /dev/null
> +++ b/lib/eal/include/rte_bitcount.h
> @@ -0,0 +1,257 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (C) 2022 Microsoft Corporation
> + */
> +
> +#ifndef EAL_BITCOUNT_H
> +#define EAL_BITCOUNT_H
> +
> +#include <rte_compat.h>
> +
> +#ifdef RTE_TOOLCHAIN_MSVC
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned

unsigned int

If you want to be __builtin_clz()-compatible, you should stay with "int" 
as the return type.

If you don't, you might want to change more than just the return type. 
In particular, it would be useful to have size-specific variants 
(although in practice they are on most [all?] DPDK-supported platforms).

unsigned int
rte_clz(uint32_t v);

or rte_clz32(), to follow the naming convention from some other wrapper 
RFC you posted.

> +rte_clz(unsigned int v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanReverse(&rv, v);
> +
> +	return (unsigned)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_clzl(unsigned long v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanReverse(&rv, v);
> +
> +	return (unsigned)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_clzll(unsigned long long v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanReverse64(&rv, v);
> +
> +	return (unsigned)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_ctz(unsigned int v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanForward(&rv, v);
> +
> +	return (unsigned)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_ctzl(unsigned long v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanForward(&rv, v);
> +
> +	return (unsigned)rv;
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_ctzll(unsigned long long v)
> +{
> +	unsigned long rv;
> +
> +	(void)_BitScanForward64(&rv, v);
> +
> +	return (unsigned)rv;
> +}
> +
> +#else
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_clz(unsigned int v)
> +{
> +	return (unsigned)__builtin_clz(v);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_clzl(unsigned long v)
> +{
> +	return (unsigned)__builtin_clzl(v);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of leading 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of leading zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_clzll(unsigned long v)
> +{
> +	return (unsigned)__builtin_clzll(v);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_ctz(unsigned int v)
> +{
> +	return (unsigned)__builtin_ctz(v);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_ctzl(unsigned long v)
> +{
> +	return (unsigned)__builtin_ctzl(v);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get the count of trailing 0-bits in v.
> + *
> + * @param v
> + *   The value.
> + * @return
> + *   The count of trailing zero bits.
> + */
> +__rte_experimental
> +static inline unsigned
> +rte_ctzll(unsigned long v)
> +{
> +	return (unsigned)__builtin_ctzll(v);
> +}
> +
> +#endif
> +
> +#endif /* EAL_BITCOUNT_H */
> +


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v8 0/3] eal: provide abstracted bit counting functions
  2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
                   ` (6 preceding siblings ...)
  2023-04-01  0:45 ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Tyler Retzlaff
@ 2023-04-04  0:11 ` Tyler Retzlaff
  2023-04-04  0:11   ` [PATCH v8 1/3] eal: move bit count functions to bitops header Tyler Retzlaff
                     ` (4 more replies)
  7 siblings, 5 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-04  0:11 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

As discussed technical board meeting 2023-02-22
http://mails.dpdk.org/archives/dev/2023-February/263516.html

We will bring support in pieces for the MSVC compiler, there will be
some abstractions and functions introduced before the compiler is
capable of compiling DPDK in order to make parallel progress
while waiting for standard atomics in 23.07.

A higher level plan / order of work is available in the Microsoft
roadmap for 23.07 and 23.11.

note:
Bruce Richardson previous acks have been preserved but be aware of
the two additional functions introduced in v7. If you wish to withdraw
your ack, please let me know but I believe the 2 additions are consistent
with previous.

v8:
  * squish patch including rte_bitops.h in lib/pipeline into
    first patch.

v7:
  * add 2 additional counting functions rte_popcount{32,64}
    including basic unit tests
  * fix patch 1 title link (CI complained too long)
  * add test_bitcount.c entry to MAINTAINERS file

v6:
  * remove stray #include <stdio.h>

v5:
  * fix implementation of msvc versions of rte_clz{32,64}
    incorrect use of _BitscanReverse{,64} index.
  * fix and expand unit test to exercise full range of counting
    over uint{32,64}_t input values. (which would have caught
    above mistake).
  * reduce commit title length
  * correct commit author

v4:
  * combine unit test commit into function addition commit

v3:
  * rename to use 32/64 instead of l/ll suffixes
  * add new functions to rte_bitops.h instead of new header
  * move other bit functions from rte_common.h to rte_bitops.h

v2:
  * use unsigned int instead of unsigned (checkpatches)
  * match multiple include guard naming convention to rte_common.h
  * add explicit extern "C" linkage to rte_bitcount.h
    note: not really needed but checkpatches required
  * add missing space around '-'

Tyler Retzlaff (3):
  eal: move bit count functions to bitops header
  eal: provide abstracted bit count functions
  maintainers: add bitcount test under EAL API and common code

 MAINTAINERS                              |   1 +
 app/test/meson.build                     |   2 +
 app/test/test_bitcount.c                 | 136 ++++++++
 app/test/test_common.c                   |   1 +
 lib/eal/common/rte_reciprocal.c          |   1 +
 lib/eal/include/rte_bitops.h             | 532 +++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h             | 293 -----------------
 lib/pipeline/rte_swx_pipeline_internal.h |   1 +
 8 files changed, 674 insertions(+), 293 deletions(-)
 create mode 100644 app/test/test_bitcount.c

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v8 1/3] eal: move bit count functions to bitops header
  2023-04-04  0:11 ` [PATCH v8 0/3] " Tyler Retzlaff
@ 2023-04-04  0:11   ` Tyler Retzlaff
  2023-04-04  0:11   ` [PATCH v8 2/3] eal: provide abstracted bit count functions Tyler Retzlaff
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-04  0:11 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

Move the following inline functions from rte_common.h to rte_bitops.h

  rte_combine32ms1b
  rte_combine64ms1b
  rte_bsf32
  rte_bsf32_safe
  rte_bsf64
  rte_bsf64_safe
  rte_fls_u32
  rte_fls_u64
  rte_is_power_of_2
  rte_align32pow2
  rte_align32prevpow2
  rte_align64pow2
  rte_align64prevpow2
  rte_log2_u32
  rte_log2_u64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
Acked-by: Ferruh Yigit <ferruh.yigit@amd.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 app/test/test_common.c                   |   1 +
 lib/eal/common/rte_reciprocal.c          |   1 +
 lib/eal/include/rte_bitops.h             | 292 ++++++++++++++++++++++++++++++
 lib/eal/include/rte_common.h             | 293 -------------------------------
 lib/pipeline/rte_swx_pipeline_internal.h |   1 +
 5 files changed, 295 insertions(+), 293 deletions(-)

diff --git a/app/test/test_common.c b/app/test/test_common.c
index f89e1eb..cf4a2c7 100644
--- a/app/test/test_common.c
+++ b/app/test/test_common.c
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <math.h>
 #include <rte_common.h>
+#include <rte_bitops.h>
 #include <rte_hexdump.h>
 #include <rte_pause.h>
 
diff --git a/lib/eal/common/rte_reciprocal.c b/lib/eal/common/rte_reciprocal.c
index 42dfa44..d47dc47 100644
--- a/lib/eal/common/rte_reciprocal.c
+++ b/lib/eal/common/rte_reciprocal.c
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <rte_common.h>
+#include <rte_bitops.h>
 
 #include "rte_reciprocal.h"
 
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index f50dbe4..531479e 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -275,6 +275,298 @@
 	return val & mask;
 }
 
+/**
+ * Combines 32b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param x
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint32_t
+rte_combine32ms1b(uint32_t x)
+{
+	x |= x >> 1;
+	x |= x >> 2;
+	x |= x >> 4;
+	x |= x >> 8;
+	x |= x >> 16;
+
+	return x;
+}
+
+/**
+ * Combines 64b inputs most significant set bits into the least
+ * significant bits to construct a value with the same MSBs as x
+ * but all 1's under it.
+ *
+ * @param v
+ *    The integer whose MSBs need to be combined with its LSBs
+ * @return
+ *    The combined value.
+ */
+static inline uint64_t
+rte_combine64ms1b(uint64_t v)
+{
+	v |= v >> 1;
+	v |= v >> 2;
+	v |= v >> 4;
+	v |= v >> 8;
+	v |= v >> 16;
+	v |= v >> 32;
+
+	return v;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf32(uint32_t v)
+{
+	return (uint32_t)__builtin_ctz(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf32_safe(uint32_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf32(v);
+	return 1;
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero).
+ * If a least significant 1 bit is found, its bit index is returned.
+ * If the content of the input parameter is zero, then the content of the return
+ * value is undefined.
+ * @param v
+ *     input parameter, should not be zero.
+ * @return
+ *     least significant set bit in the input parameter.
+ */
+static inline uint32_t
+rte_bsf64(uint64_t v)
+{
+	return (uint32_t)__builtin_ctzll(v);
+}
+
+/**
+ * Searches the input parameter for the least significant set bit
+ * (starting from zero). Safe version (checks for input parameter being zero).
+ *
+ * @warning ``pos`` must be a valid pointer. It is not checked!
+ *
+ * @param v
+ *     The input parameter.
+ * @param pos
+ *     If ``v`` was not 0, this value will contain position of least significant
+ *     bit within the input parameter.
+ * @return
+ *     Returns 0 if ``v`` was 0, otherwise returns 1.
+ */
+static inline int
+rte_bsf64_safe(uint64_t v, uint32_t *pos)
+{
+	if (v == 0)
+		return 0;
+
+	*pos = rte_bsf64(v);
+	return 1;
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 32.
+ * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u32(uint32_t x)
+{
+	return (x == 0) ? 0 : 32 - __builtin_clz(x);
+}
+
+/**
+ * Return the last (most-significant) bit set.
+ *
+ * @note The last (most significant) bit is at position 64.
+ * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
+ *       rte_fls_u64(0x8000000000000000) = 64
+ *
+ * @param x
+ *     The input parameter.
+ * @return
+ *     The last (most-significant) bit set, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_fls_u64(uint64_t x)
+{
+	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
+}
+
+/*********** Macros to work with powers of 2 ********/
+
+/**
+ * Macro to return 1 if n is a power of 2, 0 otherwise
+ */
+#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
+
+/**
+ * Returns true if n is a power of 2
+ * @param n
+ *     Number to check
+ * @return 1 if true, 0 otherwise
+ */
+static inline int
+rte_is_power_of_2(uint32_t n)
+{
+	return n && !(n & (n - 1));
+}
+
+/**
+ * Aligns input parameter to the next power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint32_t
+rte_align32pow2(uint32_t x)
+{
+	x--;
+	x = rte_combine32ms1b(x);
+
+	return x + 1;
+}
+
+/**
+ * Aligns input parameter to the previous power of 2
+ *
+ * @param x
+ *   The integer value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint32_t
+rte_align32prevpow2(uint32_t x)
+{
+	x = rte_combine32ms1b(x);
+
+	return x - (x >> 1);
+}
+
+/**
+ * Aligns 64b input parameter to the next power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the next power of 2
+ */
+static inline uint64_t
+rte_align64pow2(uint64_t v)
+{
+	v--;
+	v = rte_combine64ms1b(v);
+
+	return v + 1;
+}
+
+/**
+ * Aligns 64b input parameter to the previous power of 2
+ *
+ * @param v
+ *   The 64b value to align
+ *
+ * @return
+ *   Input parameter aligned to the previous power of 2
+ */
+static inline uint64_t
+rte_align64prevpow2(uint64_t v)
+{
+	v = rte_combine64ms1b(v);
+
+	return v - (v >> 1);
+}
+
+/**
+ * Return the rounded-up log2 of a integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u32(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u32(uint32_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align32pow2(v);
+	return rte_bsf32(v);
+}
+
+/**
+ * Return the rounded-up log2 of a 64-bit integer.
+ *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u64(0) == 0 and not -inf.
+ *
+ * @param v
+ *     The input parameter.
+ * @return
+ *     The rounded-up log2 of the input, or 0 if the input is 0.
+ */
+static inline uint32_t
+rte_log2_u64(uint64_t v)
+{
+	if (v == 0)
+		return 0;
+	v = rte_align64pow2(v);
+	/* we checked for v being 0 already, so no undefined behavior */
+	return rte_bsf64(v);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eal/include/rte_common.h b/lib/eal/include/rte_common.h
index 15765b4..c5ad69c 100644
--- a/lib/eal/include/rte_common.h
+++ b/lib/eal/include/rte_common.h
@@ -471,140 +471,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 /** Marker for 8B alignment in a structure. */
 __extension__ typedef uint64_t RTE_MARKER64[0];
 
-/**
- * Combines 32b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param x
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint32_t
-rte_combine32ms1b(uint32_t x)
-{
-	x |= x >> 1;
-	x |= x >> 2;
-	x |= x >> 4;
-	x |= x >> 8;
-	x |= x >> 16;
-
-	return x;
-}
-
-/**
- * Combines 64b inputs most significant set bits into the least
- * significant bits to construct a value with the same MSBs as x
- * but all 1's under it.
- *
- * @param v
- *    The integer whose MSBs need to be combined with its LSBs
- * @return
- *    The combined value.
- */
-static inline uint64_t
-rte_combine64ms1b(uint64_t v)
-{
-	v |= v >> 1;
-	v |= v >> 2;
-	v |= v >> 4;
-	v |= v >> 8;
-	v |= v >> 16;
-	v |= v >> 32;
-
-	return v;
-}
-
-/*********** Macros to work with powers of 2 ********/
-
-/**
- * Macro to return 1 if n is a power of 2, 0 otherwise
- */
-#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
-
-/**
- * Returns true if n is a power of 2
- * @param n
- *     Number to check
- * @return 1 if true, 0 otherwise
- */
-static inline int
-rte_is_power_of_2(uint32_t n)
-{
-	return n && !(n & (n - 1));
-}
-
-/**
- * Aligns input parameter to the next power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint32_t
-rte_align32pow2(uint32_t x)
-{
-	x--;
-	x = rte_combine32ms1b(x);
-
-	return x + 1;
-}
-
-/**
- * Aligns input parameter to the previous power of 2
- *
- * @param x
- *   The integer value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint32_t
-rte_align32prevpow2(uint32_t x)
-{
-	x = rte_combine32ms1b(x);
-
-	return x - (x >> 1);
-}
-
-/**
- * Aligns 64b input parameter to the next power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the next power of 2
- */
-static inline uint64_t
-rte_align64pow2(uint64_t v)
-{
-	v--;
-	v = rte_combine64ms1b(v);
-
-	return v + 1;
-}
-
-/**
- * Aligns 64b input parameter to the previous power of 2
- *
- * @param v
- *   The 64b value to align
- *
- * @return
- *   Input parameter aligned to the previous power of 2
- */
-static inline uint64_t
-rte_align64prevpow2(uint64_t v)
-{
-	v = rte_combine64ms1b(v);
-
-	return v - (v >> 1);
-}
-
 /*********** Macros for calculating min and max **********/
 
 /**
@@ -629,165 +495,6 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 
 /*********** Other general functions / macros ********/
 
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf32(uint32_t v)
-{
-	return (uint32_t)__builtin_ctz(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf32_safe(uint32_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf32(v);
-	return 1;
-}
-
-/**
- * Return the rounded-up log2 of a integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u32(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u32(uint32_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align32pow2(v);
-	return rte_bsf32(v);
-}
-
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 32.
- * @note rte_fls_u32(0) = 0, rte_fls_u32(1) = 1, rte_fls_u32(0x80000000) = 32
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u32(uint32_t x)
-{
-	return (x == 0) ? 0 : 32 - __builtin_clz(x);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero).
- * If a least significant 1 bit is found, its bit index is returned.
- * If the content of the input parameter is zero, then the content of the return
- * value is undefined.
- * @param v
- *     input parameter, should not be zero.
- * @return
- *     least significant set bit in the input parameter.
- */
-static inline uint32_t
-rte_bsf64(uint64_t v)
-{
-	return (uint32_t)__builtin_ctzll(v);
-}
-
-/**
- * Searches the input parameter for the least significant set bit
- * (starting from zero). Safe version (checks for input parameter being zero).
- *
- * @warning ``pos`` must be a valid pointer. It is not checked!
- *
- * @param v
- *     The input parameter.
- * @param pos
- *     If ``v`` was not 0, this value will contain position of least significant
- *     bit within the input parameter.
- * @return
- *     Returns 0 if ``v`` was 0, otherwise returns 1.
- */
-static inline int
-rte_bsf64_safe(uint64_t v, uint32_t *pos)
-{
-	if (v == 0)
-		return 0;
-
-	*pos = rte_bsf64(v);
-	return 1;
-}
-
-/**
- * Return the last (most-significant) bit set.
- *
- * @note The last (most significant) bit is at position 64.
- * @note rte_fls_u64(0) = 0, rte_fls_u64(1) = 1,
- *       rte_fls_u64(0x8000000000000000) = 64
- *
- * @param x
- *     The input parameter.
- * @return
- *     The last (most-significant) bit set, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_fls_u64(uint64_t x)
-{
-	return (x == 0) ? 0 : 64 - __builtin_clzll(x);
-}
-
-/**
- * Return the rounded-up log2 of a 64-bit integer.
- *
- * @note Contrary to the logarithm mathematical operation,
- * rte_log2_u64(0) == 0 and not -inf.
- *
- * @param v
- *     The input parameter.
- * @return
- *     The rounded-up log2 of the input, or 0 if the input is 0.
- */
-static inline uint32_t
-rte_log2_u64(uint64_t v)
-{
-	if (v == 0)
-		return 0;
-	v = rte_align64pow2(v);
-	/* we checked for v being 0 already, so no undefined behavior */
-	return rte_bsf64(v);
-}
-
 #ifndef offsetof
 /** Return the offset of a field in a structure. */
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index 2f24e1a..a67b6e9 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -8,6 +8,7 @@
 #include <string.h>
 #include <sys/queue.h>
 
+#include <rte_bitops.h>
 #include <rte_byteorder.h>
 #include <rte_common.h>
 #include <rte_cycles.h>
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v8 2/3] eal: provide abstracted bit count functions
  2023-04-04  0:11 ` [PATCH v8 0/3] " Tyler Retzlaff
  2023-04-04  0:11   ` [PATCH v8 1/3] eal: move bit count functions to bitops header Tyler Retzlaff
@ 2023-04-04  0:11   ` Tyler Retzlaff
  2023-04-04  0:11   ` [PATCH v8 3/3] maintainers: add bitcount test under EAL API and common code Tyler Retzlaff
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-04  0:11 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

Provide abstracted bit counting functions for count, leading and
trailing bits in v to hide compiler specific intrinsics and builtins.

Include basic unit test of following functions added.

    rte_clz32
    rte_clz64
    rte_ctz32
    rte_ctz64
    rte_popcount32
    rte_popcount64

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 app/test/meson.build         |   2 +
 app/test/test_bitcount.c     | 136 ++++++++++++++++++++++++
 lib/eal/include/rte_bitops.h | 240 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 378 insertions(+)
 create mode 100644 app/test/test_bitcount.c

diff --git a/app/test/meson.build b/app/test/meson.build
index b9b5432..dafd509 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -13,6 +13,7 @@ test_sources = files(
         'test_alarm.c',
         'test_atomic.c',
         'test_barrier.c',
+        'test_bitcount.c',
         'test_bitops.c',
         'test_bitmap.c',
         'test_bpf.c',
@@ -161,6 +162,7 @@ test_deps += ['bus_pci', 'bus_vdev']
 fast_tests = [
         ['acl_autotest', true, true],
         ['atomic_autotest', false, true],
+        ['bitcount_autotest', true, true],
         ['bitmap_autotest', true, true],
         ['bpf_autotest', true, true],
         ['bpf_convert_autotest', true, true],
diff --git a/app/test/test_bitcount.c b/app/test/test_bitcount.c
new file mode 100644
index 0000000..5287ef7
--- /dev/null
+++ b/app/test/test_bitcount.c
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2022 Microsoft Corporation
+ */
+
+#include <limits.h>
+#include <string.h>
+
+#include <rte_bitops.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+RTE_LOG_REGISTER(bitcount_logtype_test, test.bitcount, INFO);
+
+static int
+test_clz32(void)
+{
+	size_t leading;
+	uint32_t v = 0xffffffff;
+
+	for (leading = 0; v; leading++) {
+		RTE_TEST_ASSERT(rte_clz32(v) == leading,
+		    "Unexpected count.");
+		v >>= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_clz64(void)
+{
+	size_t leading;
+	uint64_t v = 0xffffffffffffffff;
+
+	for (leading = 0; v; leading++) {
+		RTE_TEST_ASSERT(rte_clz64(v) == leading,
+		    "Unexpected count.");
+		v >>= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_ctz32(void)
+{
+	size_t trailing;
+	uint32_t v = 1;
+
+	for (trailing = 0; v; trailing++) {
+		RTE_TEST_ASSERT(rte_ctz32(v) == trailing,
+		    "Unexpected count.");
+		v <<= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_ctz64(void)
+{
+	size_t trailing;
+	uint64_t v = 1;
+
+	for (trailing = 0; v; trailing++) {
+		RTE_TEST_ASSERT(rte_ctz64(v) == trailing,
+		    "Unexpected count.");
+		v <<= 1;
+	}
+
+	return 0;
+}
+
+static int
+test_popcount32(void)
+{
+	size_t shift;
+	uint32_t v = 0;
+	const size_t bits = sizeof(v) * CHAR_BIT;
+
+	for (shift = 0; shift < bits; shift++) {
+		RTE_TEST_ASSERT(rte_popcount32(v) == shift,
+		    "Unexpected count.");
+		v <<= 1;
+		v |= 1;
+	}
+
+	RTE_TEST_ASSERT(rte_popcount32(v) == bits,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static int
+test_popcount64(void)
+{
+	size_t shift;
+	uint64_t v = 0;
+	const size_t bits = sizeof(v) * CHAR_BIT;
+
+	for (shift = 0; shift < bits; shift++) {
+		RTE_TEST_ASSERT(rte_popcount64(v) == shift,
+		    "Unexpected count.");
+		v <<= 1;
+		v |= 1;
+	}
+
+	RTE_TEST_ASSERT(rte_popcount64(v) == bits,
+	    "Unexpected count.");
+
+	return 0;
+}
+
+static struct unit_test_suite bitcount_test_suite = {
+	.suite_name = "bitcount autotest",
+	.setup = NULL,
+	.teardown = NULL,
+	.unit_test_cases = {
+		TEST_CASE(test_clz32),
+		TEST_CASE(test_clz64),
+		TEST_CASE(test_ctz32),
+		TEST_CASE(test_ctz64),
+		TEST_CASE(test_popcount32),
+		TEST_CASE(test_popcount64),
+		TEST_CASES_END()
+	}
+};
+
+static int
+test_bitcount(void)
+{
+	return unit_test_suite_runner(&bitcount_test_suite);
+}
+
+REGISTER_TEST_COMMAND(bitcount_autotest, test_bitcount);
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index 531479e..d45aa54 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2020 Arm Limited
+ * Copyright(c) 2010-2019 Intel Corporation
+ * Copyright(c) 2023 Microsoft Corporation
  */
 
 #ifndef _RTE_BITOPS_H_
@@ -275,6 +277,244 @@
 	return val & mask;
 }
 
+#ifdef RTE_TOOLCHAIN_MSVC
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse(&rv, v);
+
+	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanReverse64(&rv, v);
+
+	return (unsigned int)(sizeof(v) * CHAR_BIT - 1 - rv);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	unsigned long rv;
+
+	(void)_BitScanForward64(&rv, v);
+
+	return (unsigned int)rv;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of 1-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of 1-bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_popcount32(uint32_t v)
+{
+	return (unsigned int)__popcnt(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of 1-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of 1-bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_popcount64(uint64_t v)
+{
+	return (unsigned int)__popcnt64(v);
+}
+
+#else
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz32(uint32_t v)
+{
+	return (unsigned int)__builtin_clz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of leading 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of leading zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_clz64(uint64_t v)
+{
+	return (unsigned int)__builtin_clzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz32(uint32_t v)
+{
+	return (unsigned int)__builtin_ctz(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of trailing 0-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of trailing zero bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_ctz64(uint64_t v)
+{
+	return (unsigned int)__builtin_ctzll(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of 1-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of 1-bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_popcount32(uint32_t v)
+{
+	return (unsigned int)__builtin_popcount(v);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get the count of 1-bits in v.
+ *
+ * @param v
+ *   The value.
+ * @return
+ *   The count of 1-bits.
+ */
+__rte_experimental
+static inline unsigned int
+rte_popcount64(uint64_t v)
+{
+	return (unsigned int)__builtin_popcountll(v);
+}
+
+#endif
+
 /**
  * Combines 32b inputs most significant set bits into the least
  * significant bits to construct a value with the same MSBs as x
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* [PATCH v8 3/3] maintainers: add bitcount test under EAL API and common code
  2023-04-04  0:11 ` [PATCH v8 0/3] " Tyler Retzlaff
  2023-04-04  0:11   ` [PATCH v8 1/3] eal: move bit count functions to bitops header Tyler Retzlaff
  2023-04-04  0:11   ` [PATCH v8 2/3] eal: provide abstracted bit count functions Tyler Retzlaff
@ 2023-04-04  0:11   ` Tyler Retzlaff
  2023-04-04  8:27   ` [PATCH v8 0/3] eal: provide abstracted bit counting functions Bruce Richardson
  2023-08-25  8:41   ` David Marchand
  4 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-04  0:11 UTC (permalink / raw)
  To: dev
  Cc: thomas, stephen, mb, bruce.richardson, ferruh.yigit,
	david.marchand, Tyler Retzlaff

List app/test/test_bitcount.c under EAL API and common code.

Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8df23e5..c2995bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -155,6 +155,7 @@ F: doc/guides/prog_guide/env_abstraction_layer.rst
 F: app/test/test_alarm.c
 F: app/test/test_atomic.c
 F: app/test/test_barrier.c
+F: app/test/test_bitcount.c
 F: app/test/test_byteorder.c
 F: app/test/test_common.c
 F: app/test/test_cpuflags.c
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 0/3] eal: provide abstracted bit counting functions
  2023-04-04  0:11 ` [PATCH v8 0/3] " Tyler Retzlaff
                     ` (2 preceding siblings ...)
  2023-04-04  0:11   ` [PATCH v8 3/3] maintainers: add bitcount test under EAL API and common code Tyler Retzlaff
@ 2023-04-04  8:27   ` Bruce Richardson
  2023-08-25  8:41   ` David Marchand
  4 siblings, 0 replies; 81+ messages in thread
From: Bruce Richardson @ 2023-04-04  8:27 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: dev, thomas, stephen, mb, ferruh.yigit, david.marchand

On Mon, Apr 03, 2023 at 05:11:55PM -0700, Tyler Retzlaff wrote:
> As discussed technical board meeting 2023-02-22
> http://mails.dpdk.org/archives/dev/2023-February/263516.html
> 
> We will bring support in pieces for the MSVC compiler, there will be
> some abstractions and functions introduced before the compiler is
> capable of compiling DPDK in order to make parallel progress
> while waiting for standard atomics in 23.07.
> 
> A higher level plan / order of work is available in the Microsoft
> roadmap for 23.07 and 23.11.
> 
> note:
> Bruce Richardson previous acks have been preserved but be aware of
> the two additional functions introduced in v7. If you wish to withdraw
> your ack, please let me know but I believe the 2 additions are consistent
> with previous.
>
All good, keeping them is fine.
Thanks,
/Bruce 

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-01-05  7:09     ` Morten Brørup
  2023-01-05  9:01       ` Thomas Monjalon
@ 2023-04-04 21:23       ` Tyler Retzlaff
  2023-04-05  8:44         ` Bruce Richardson
  1 sibling, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-04 21:23 UTC (permalink / raw)
  To: Morten Brørup; +Cc: dev, david.marchand, thomas

On Thu, Jan 05, 2023 at 08:09:19AM +0100, Morten Brørup wrote:
> > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > Sent: Thursday, 24 November 2022 00.43
> > 
> > Provide an abstraction for leading and trailing zero bit counting
> > functions to hide compiler specific intrinsics and builtins.
> > 
> > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > ---
> >  lib/eal/include/meson.build    |   1 +
> >  lib/eal/include/rte_bitcount.h | 265
> > +++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 266 insertions(+)
> >  create mode 100644 lib/eal/include/rte_bitcount.h
> > 
> > diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
> > index cfcd40a..8ff1d65 100644
> > --- a/lib/eal/include/meson.build
> > +++ b/lib/eal/include/meson.build
> > @@ -5,6 +5,7 @@ includes += include_directories('.')
> > 
> >  headers += files(
> >          'rte_alarm.h',
> > +        'rte_bitcount.h',
> >          'rte_bitmap.h',
> >          'rte_bitops.h',
> >          'rte_branch_prediction.h',
> > diff --git a/lib/eal/include/rte_bitcount.h
> > b/lib/eal/include/rte_bitcount.h
> > new file mode 100644
> > index 0000000..587de52
> > --- /dev/null
> > +++ b/lib/eal/include/rte_bitcount.h
> > @@ -0,0 +1,265 @@
> > +/* SPDX-License-Identifier: BSD-3-Clause
> > + * Copyright (C) 2022 Microsoft Corporation
> > + */
> > +
> > +#ifndef _RTE_BITCOUNT_H_
> > +#define _RTE_BITCOUNT_H_
> > +
> > +#include <rte_compat.h>
> > +
> > +#ifdef __cplusplus
> > +extern "C" {
> > +#endif
> > +
> > +#ifdef RTE_TOOLCHAIN_MSVC
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > notice
> > + *
> > + * Get the count of leading 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of leading zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_clz(unsigned int v)
> > +{
> > +	unsigned long rv;
> > +
> > +	(void)_BitScanReverse(&rv, v);
> > +
> > +	return (unsigned int)rv;
> > +}
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > notice
> > + *
> > + * Get the count of leading 0-bits in v.
> > + *
> > + * @param v
> > + *   The value.
> > + * @return
> > + *   The count of leading zero bits.
> > + */
> > +__rte_experimental
> > +static inline unsigned int
> > +rte_clzl(unsigned long v)
> 
> Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> 
> E.g.: rte_clz32(uint32_t v)

so i just noticed this, but sometimes these functions receive size_t so
naming them specifically 32/64 bit becomes problematic because are going
to end up with promotion on sizeof(size_t) == sizeof(long) == 4
platforms.

i.e.
size_t s = ...;
x = rte_clz64(s); // assume 64-bit today

this code is now broken because on 32-bit platform s will get promoted
and the extra 32 zero-bits will be returned in the result breaking
calculations.

any thoughts? should we go back to l, ll?

ty

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-04-04 21:23       ` Tyler Retzlaff
@ 2023-04-05  8:44         ` Bruce Richardson
  2023-04-05 15:22           ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Bruce Richardson @ 2023-04-05  8:44 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: Morten Brørup, dev, david.marchand, thomas

On Tue, Apr 04, 2023 at 02:23:22PM -0700, Tyler Retzlaff wrote:
> On Thu, Jan 05, 2023 at 08:09:19AM +0100, Morten Brørup wrote:
> > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > Sent: Thursday, 24 November 2022 00.43
> > > 
> > > Provide an abstraction for leading and trailing zero bit counting
> > > functions to hide compiler specific intrinsics and builtins.
> > > 
> > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > ---
> > >  lib/eal/include/meson.build    |   1 +
> > >  lib/eal/include/rte_bitcount.h | 265
> > > +++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 266 insertions(+)
> > >  create mode 100644 lib/eal/include/rte_bitcount.h
> > > 
> > > diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
> > > index cfcd40a..8ff1d65 100644
> > > --- a/lib/eal/include/meson.build
> > > +++ b/lib/eal/include/meson.build
> > > @@ -5,6 +5,7 @@ includes += include_directories('.')
> > > 
> > >  headers += files(
> > >          'rte_alarm.h',
> > > +        'rte_bitcount.h',
> > >          'rte_bitmap.h',
> > >          'rte_bitops.h',
> > >          'rte_branch_prediction.h',
> > > diff --git a/lib/eal/include/rte_bitcount.h
> > > b/lib/eal/include/rte_bitcount.h
> > > new file mode 100644
> > > index 0000000..587de52
> > > --- /dev/null
> > > +++ b/lib/eal/include/rte_bitcount.h
> > > @@ -0,0 +1,265 @@
> > > +/* SPDX-License-Identifier: BSD-3-Clause
> > > + * Copyright (C) 2022 Microsoft Corporation
> > > + */
> > > +
> > > +#ifndef _RTE_BITCOUNT_H_
> > > +#define _RTE_BITCOUNT_H_
> > > +
> > > +#include <rte_compat.h>
> > > +
> > > +#ifdef __cplusplus
> > > +extern "C" {
> > > +#endif
> > > +
> > > +#ifdef RTE_TOOLCHAIN_MSVC
> > > +
> > > +/**
> > > + * @warning
> > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > notice
> > > + *
> > > + * Get the count of leading 0-bits in v.
> > > + *
> > > + * @param v
> > > + *   The value.
> > > + * @return
> > > + *   The count of leading zero bits.
> > > + */
> > > +__rte_experimental
> > > +static inline unsigned int
> > > +rte_clz(unsigned int v)
> > > +{
> > > +	unsigned long rv;
> > > +
> > > +	(void)_BitScanReverse(&rv, v);
> > > +
> > > +	return (unsigned int)rv;
> > > +}
> > > +
> > > +/**
> > > + * @warning
> > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > notice
> > > + *
> > > + * Get the count of leading 0-bits in v.
> > > + *
> > > + * @param v
> > > + *   The value.
> > > + * @return
> > > + *   The count of leading zero bits.
> > > + */
> > > +__rte_experimental
> > > +static inline unsigned int
> > > +rte_clzl(unsigned long v)
> > 
> > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > 
> > E.g.: rte_clz32(uint32_t v)
> 
> so i just noticed this, but sometimes these functions receive size_t so
> naming them specifically 32/64 bit becomes problematic because are going
> to end up with promotion on sizeof(size_t) == sizeof(long) == 4
> platforms.
> 
> i.e.
> size_t s = ...;
> x = rte_clz64(s); // assume 64-bit today
> 
> this code is now broken because on 32-bit platform s will get promoted
> and the extra 32 zero-bits will be returned in the result breaking
> calculations.
> 
> any thoughts? should we go back to l, ll?
> 

Yes, promotion will happen, but I still think that the 32 and 64 versions
are far clearer here in all cases. Anyone looking at the code will
recognise that the result will be the leading zero count of a 64-bit number
irrespective of the type actually passed in. It's less confusing now IMHO.

/Bruce

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-04-05  8:44         ` Bruce Richardson
@ 2023-04-05 15:22           ` Tyler Retzlaff
  2023-04-05 15:51             ` Bruce Richardson
  0 siblings, 1 reply; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-05 15:22 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: Morten Brørup, dev, david.marchand, thomas

On Wed, Apr 05, 2023 at 09:44:54AM +0100, Bruce Richardson wrote:
> On Tue, Apr 04, 2023 at 02:23:22PM -0700, Tyler Retzlaff wrote:
> > On Thu, Jan 05, 2023 at 08:09:19AM +0100, Morten Brørup wrote:
> > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > Sent: Thursday, 24 November 2022 00.43
> > > > 
> > > > Provide an abstraction for leading and trailing zero bit counting
> > > > functions to hide compiler specific intrinsics and builtins.
> > > > 
> > > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > > ---
> > > >  lib/eal/include/meson.build    |   1 +
> > > >  lib/eal/include/rte_bitcount.h | 265
> > > > +++++++++++++++++++++++++++++++++++++++++
> > > >  2 files changed, 266 insertions(+)
> > > >  create mode 100644 lib/eal/include/rte_bitcount.h
> > > > 
> > > > diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
> > > > index cfcd40a..8ff1d65 100644
> > > > --- a/lib/eal/include/meson.build
> > > > +++ b/lib/eal/include/meson.build
> > > > @@ -5,6 +5,7 @@ includes += include_directories('.')
> > > > 
> > > >  headers += files(
> > > >          'rte_alarm.h',
> > > > +        'rte_bitcount.h',
> > > >          'rte_bitmap.h',
> > > >          'rte_bitops.h',
> > > >          'rte_branch_prediction.h',
> > > > diff --git a/lib/eal/include/rte_bitcount.h
> > > > b/lib/eal/include/rte_bitcount.h
> > > > new file mode 100644
> > > > index 0000000..587de52
> > > > --- /dev/null
> > > > +++ b/lib/eal/include/rte_bitcount.h
> > > > @@ -0,0 +1,265 @@
> > > > +/* SPDX-License-Identifier: BSD-3-Clause
> > > > + * Copyright (C) 2022 Microsoft Corporation
> > > > + */
> > > > +
> > > > +#ifndef _RTE_BITCOUNT_H_
> > > > +#define _RTE_BITCOUNT_H_
> > > > +
> > > > +#include <rte_compat.h>
> > > > +
> > > > +#ifdef __cplusplus
> > > > +extern "C" {
> > > > +#endif
> > > > +
> > > > +#ifdef RTE_TOOLCHAIN_MSVC
> > > > +
> > > > +/**
> > > > + * @warning
> > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > notice
> > > > + *
> > > > + * Get the count of leading 0-bits in v.
> > > > + *
> > > > + * @param v
> > > > + *   The value.
> > > > + * @return
> > > > + *   The count of leading zero bits.
> > > > + */
> > > > +__rte_experimental
> > > > +static inline unsigned int
> > > > +rte_clz(unsigned int v)
> > > > +{
> > > > +	unsigned long rv;
> > > > +
> > > > +	(void)_BitScanReverse(&rv, v);
> > > > +
> > > > +	return (unsigned int)rv;
> > > > +}
> > > > +
> > > > +/**
> > > > + * @warning
> > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > notice
> > > > + *
> > > > + * Get the count of leading 0-bits in v.
> > > > + *
> > > > + * @param v
> > > > + *   The value.
> > > > + * @return
> > > > + *   The count of leading zero bits.
> > > > + */
> > > > +__rte_experimental
> > > > +static inline unsigned int
> > > > +rte_clzl(unsigned long v)
> > > 
> > > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > > 
> > > E.g.: rte_clz32(uint32_t v)
> > 
> > so i just noticed this, but sometimes these functions receive size_t so
> > naming them specifically 32/64 bit becomes problematic because are going
> > to end up with promotion on sizeof(size_t) == sizeof(long) == 4
> > platforms.
> > 
> > i.e.
> > size_t s = ...;
> > x = rte_clz64(s); // assume 64-bit today
> > 
> > this code is now broken because on 32-bit platform s will get promoted
> > and the extra 32 zero-bits will be returned in the result breaking
> > calculations.
> > 
> > any thoughts? should we go back to l, ll?
> > 
> 
> Yes, promotion will happen, but I still think that the 32 and 64 versions
> are far clearer here in all cases. Anyone looking at the code will
> recognise that the result will be the leading zero count of a 64-bit number
> irrespective of the type actually passed in. It's less confusing now IMHO.

here's an example in the code that would result in a bad calculation or
at least i believe so at a glance. switching to rte_clz32() would break
on 64-bit since it would truncate.

lib/eal/common/malloc_elem.c

-log2 = sizeof(size) * 8 - __builtin_clzl(size);
+log2 = sizeof(size) * 8 - rte_clz64(size);

if i'm right you'd have to conditionally compile at the site.

#ifdef 64-bit
rte_clz64()
#else
rte_clz32()
#endif

and that seems very undesirable. another solution is to defer this
change until post 23.07 release (where C11 can be used) and we could
then just provide a single generic.

with C11 i can provide a single macro that doesn't need 8/16/32/64
suffix.

size_t v;
n = rte_clz(v); // sizeof(v) doesn't matter.

> 
> /Bruce

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-04-05 15:22           ` Tyler Retzlaff
@ 2023-04-05 15:51             ` Bruce Richardson
  2023-04-05 17:25               ` Tyler Retzlaff
  0 siblings, 1 reply; 81+ messages in thread
From: Bruce Richardson @ 2023-04-05 15:51 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: Morten Brørup, dev, david.marchand, thomas

On Wed, Apr 05, 2023 at 08:22:16AM -0700, Tyler Retzlaff wrote:
> On Wed, Apr 05, 2023 at 09:44:54AM +0100, Bruce Richardson wrote:
> > On Tue, Apr 04, 2023 at 02:23:22PM -0700, Tyler Retzlaff wrote:
> > > On Thu, Jan 05, 2023 at 08:09:19AM +0100, Morten Brørup wrote:
> > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > Sent: Thursday, 24 November 2022 00.43
> > > > > 
> > > > > Provide an abstraction for leading and trailing zero bit counting
> > > > > functions to hide compiler specific intrinsics and builtins.
> > > > > 
> > > > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > > > ---
> > > > >  lib/eal/include/meson.build    |   1 +
> > > > >  lib/eal/include/rte_bitcount.h | 265
> > > > > +++++++++++++++++++++++++++++++++++++++++
> > > > >  2 files changed, 266 insertions(+)
> > > > >  create mode 100644 lib/eal/include/rte_bitcount.h
> > > > > 
> > > > > diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
> > > > > index cfcd40a..8ff1d65 100644
> > > > > --- a/lib/eal/include/meson.build
> > > > > +++ b/lib/eal/include/meson.build
> > > > > @@ -5,6 +5,7 @@ includes += include_directories('.')
> > > > > 
> > > > >  headers += files(
> > > > >          'rte_alarm.h',
> > > > > +        'rte_bitcount.h',
> > > > >          'rte_bitmap.h',
> > > > >          'rte_bitops.h',
> > > > >          'rte_branch_prediction.h',
> > > > > diff --git a/lib/eal/include/rte_bitcount.h
> > > > > b/lib/eal/include/rte_bitcount.h
> > > > > new file mode 100644
> > > > > index 0000000..587de52
> > > > > --- /dev/null
> > > > > +++ b/lib/eal/include/rte_bitcount.h
> > > > > @@ -0,0 +1,265 @@
> > > > > +/* SPDX-License-Identifier: BSD-3-Clause
> > > > > + * Copyright (C) 2022 Microsoft Corporation
> > > > > + */
> > > > > +
> > > > > +#ifndef _RTE_BITCOUNT_H_
> > > > > +#define _RTE_BITCOUNT_H_
> > > > > +
> > > > > +#include <rte_compat.h>
> > > > > +
> > > > > +#ifdef __cplusplus
> > > > > +extern "C" {
> > > > > +#endif
> > > > > +
> > > > > +#ifdef RTE_TOOLCHAIN_MSVC
> > > > > +
> > > > > +/**
> > > > > + * @warning
> > > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > > notice
> > > > > + *
> > > > > + * Get the count of leading 0-bits in v.
> > > > > + *
> > > > > + * @param v
> > > > > + *   The value.
> > > > > + * @return
> > > > > + *   The count of leading zero bits.
> > > > > + */
> > > > > +__rte_experimental
> > > > > +static inline unsigned int
> > > > > +rte_clz(unsigned int v)
> > > > > +{
> > > > > +	unsigned long rv;
> > > > > +
> > > > > +	(void)_BitScanReverse(&rv, v);
> > > > > +
> > > > > +	return (unsigned int)rv;
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + * @warning
> > > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > > notice
> > > > > + *
> > > > > + * Get the count of leading 0-bits in v.
> > > > > + *
> > > > > + * @param v
> > > > > + *   The value.
> > > > > + * @return
> > > > > + *   The count of leading zero bits.
> > > > > + */
> > > > > +__rte_experimental
> > > > > +static inline unsigned int
> > > > > +rte_clzl(unsigned long v)
> > > > 
> > > > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > > > 
> > > > E.g.: rte_clz32(uint32_t v)
> > > 
> > > so i just noticed this, but sometimes these functions receive size_t so
> > > naming them specifically 32/64 bit becomes problematic because are going
> > > to end up with promotion on sizeof(size_t) == sizeof(long) == 4
> > > platforms.
> > > 
> > > i.e.
> > > size_t s = ...;
> > > x = rte_clz64(s); // assume 64-bit today
> > > 
> > > this code is now broken because on 32-bit platform s will get promoted
> > > and the extra 32 zero-bits will be returned in the result breaking
> > > calculations.
> > > 
> > > any thoughts? should we go back to l, ll?
> > > 
> > 
> > Yes, promotion will happen, but I still think that the 32 and 64 versions
> > are far clearer here in all cases. Anyone looking at the code will
> > recognise that the result will be the leading zero count of a 64-bit number
> > irrespective of the type actually passed in. It's less confusing now IMHO.
> 
> here's an example in the code that would result in a bad calculation or
> at least i believe so at a glance. switching to rte_clz32() would break
> on 64-bit since it would truncate.
> 
> lib/eal/common/malloc_elem.c
> 
> -log2 = sizeof(size) * 8 - __builtin_clzl(size);
> +log2 = sizeof(size) * 8 - rte_clz64(size);
> 
> if i'm right you'd have to conditionally compile at the site.
> 
> #ifdef 64-bit
> rte_clz64()
> #else
> rte_clz32()
> #endif
> 

Why can clz64 not be used in both 32 and 64 bit cases? You know the result
will always include zeros in high bits of a 64-bit value, and the result
will still fit inside even an 8-bit variable?

/Bruce

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction
  2023-04-05 15:51             ` Bruce Richardson
@ 2023-04-05 17:25               ` Tyler Retzlaff
  0 siblings, 0 replies; 81+ messages in thread
From: Tyler Retzlaff @ 2023-04-05 17:25 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: Morten Brørup, dev, david.marchand, thomas

On Wed, Apr 05, 2023 at 04:51:42PM +0100, Bruce Richardson wrote:
> On Wed, Apr 05, 2023 at 08:22:16AM -0700, Tyler Retzlaff wrote:
> > On Wed, Apr 05, 2023 at 09:44:54AM +0100, Bruce Richardson wrote:
> > > On Tue, Apr 04, 2023 at 02:23:22PM -0700, Tyler Retzlaff wrote:
> > > > On Thu, Jan 05, 2023 at 08:09:19AM +0100, Morten Brørup wrote:
> > > > > > From: Tyler Retzlaff [mailto:roretzla@linux.microsoft.com]
> > > > > > Sent: Thursday, 24 November 2022 00.43
> > > > > > 
> > > > > > Provide an abstraction for leading and trailing zero bit counting
> > > > > > functions to hide compiler specific intrinsics and builtins.
> > > > > > 
> > > > > > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > > > > > ---
> > > > > >  lib/eal/include/meson.build    |   1 +
> > > > > >  lib/eal/include/rte_bitcount.h | 265
> > > > > > +++++++++++++++++++++++++++++++++++++++++
> > > > > >  2 files changed, 266 insertions(+)
> > > > > >  create mode 100644 lib/eal/include/rte_bitcount.h
> > > > > > 
> > > > > > diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
> > > > > > index cfcd40a..8ff1d65 100644
> > > > > > --- a/lib/eal/include/meson.build
> > > > > > +++ b/lib/eal/include/meson.build
> > > > > > @@ -5,6 +5,7 @@ includes += include_directories('.')
> > > > > > 
> > > > > >  headers += files(
> > > > > >          'rte_alarm.h',
> > > > > > +        'rte_bitcount.h',
> > > > > >          'rte_bitmap.h',
> > > > > >          'rte_bitops.h',
> > > > > >          'rte_branch_prediction.h',
> > > > > > diff --git a/lib/eal/include/rte_bitcount.h
> > > > > > b/lib/eal/include/rte_bitcount.h
> > > > > > new file mode 100644
> > > > > > index 0000000..587de52
> > > > > > --- /dev/null
> > > > > > +++ b/lib/eal/include/rte_bitcount.h
> > > > > > @@ -0,0 +1,265 @@
> > > > > > +/* SPDX-License-Identifier: BSD-3-Clause
> > > > > > + * Copyright (C) 2022 Microsoft Corporation
> > > > > > + */
> > > > > > +
> > > > > > +#ifndef _RTE_BITCOUNT_H_
> > > > > > +#define _RTE_BITCOUNT_H_
> > > > > > +
> > > > > > +#include <rte_compat.h>
> > > > > > +
> > > > > > +#ifdef __cplusplus
> > > > > > +extern "C" {
> > > > > > +#endif
> > > > > > +
> > > > > > +#ifdef RTE_TOOLCHAIN_MSVC
> > > > > > +
> > > > > > +/**
> > > > > > + * @warning
> > > > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > > > notice
> > > > > > + *
> > > > > > + * Get the count of leading 0-bits in v.
> > > > > > + *
> > > > > > + * @param v
> > > > > > + *   The value.
> > > > > > + * @return
> > > > > > + *   The count of leading zero bits.
> > > > > > + */
> > > > > > +__rte_experimental
> > > > > > +static inline unsigned int
> > > > > > +rte_clz(unsigned int v)
> > > > > > +{
> > > > > > +	unsigned long rv;
> > > > > > +
> > > > > > +	(void)_BitScanReverse(&rv, v);
> > > > > > +
> > > > > > +	return (unsigned int)rv;
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + * @warning
> > > > > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > > > > notice
> > > > > > + *
> > > > > > + * Get the count of leading 0-bits in v.
> > > > > > + *
> > > > > > + * @param v
> > > > > > + *   The value.
> > > > > > + * @return
> > > > > > + *   The count of leading zero bits.
> > > > > > + */
> > > > > > +__rte_experimental
> > > > > > +static inline unsigned int
> > > > > > +rte_clzl(unsigned long v)
> > > > > 
> > > > > Don't use l (long) and ll (long long) for names (and types), use explicit bit lengths, 32 and 64.
> > > > > 
> > > > > E.g.: rte_clz32(uint32_t v)
> > > > 
> > > > so i just noticed this, but sometimes these functions receive size_t so
> > > > naming them specifically 32/64 bit becomes problematic because are going
> > > > to end up with promotion on sizeof(size_t) == sizeof(long) == 4
> > > > platforms.
> > > > 
> > > > i.e.
> > > > size_t s = ...;
> > > > x = rte_clz64(s); // assume 64-bit today
> > > > 
> > > > this code is now broken because on 32-bit platform s will get promoted
> > > > and the extra 32 zero-bits will be returned in the result breaking
> > > > calculations.
> > > > 
> > > > any thoughts? should we go back to l, ll?
> > > > 
> > > 
> > > Yes, promotion will happen, but I still think that the 32 and 64 versions
> > > are far clearer here in all cases. Anyone looking at the code will
> > > recognise that the result will be the leading zero count of a 64-bit number
> > > irrespective of the type actually passed in. It's less confusing now IMHO.
> > 
> > here's an example in the code that would result in a bad calculation or
> > at least i believe so at a glance. switching to rte_clz32() would break
> > on 64-bit since it would truncate.
> > 
> > lib/eal/common/malloc_elem.c
> > 
> > -log2 = sizeof(size) * 8 - __builtin_clzl(size);
> > +log2 = sizeof(size) * 8 - rte_clz64(size);
> > 
> > if i'm right you'd have to conditionally compile at the site.
> > 
> > #ifdef 64-bit
> > rte_clz64()
> > #else
> > rte_clz32()
> > #endif
> > 
> 
> Why can clz64 not be used in both 32 and 64 bit cases? You know the result
> will always include zeros in high bits of a 64-bit value, and the result
> will still fit inside even an 8-bit variable?

of course. doh.

sorry for the noise!

and thank you as always.

> 
> /Bruce

^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: [PATCH v8 0/3] eal: provide abstracted bit counting functions
  2023-04-04  0:11 ` [PATCH v8 0/3] " Tyler Retzlaff
                     ` (3 preceding siblings ...)
  2023-04-04  8:27   ` [PATCH v8 0/3] eal: provide abstracted bit counting functions Bruce Richardson
@ 2023-08-25  8:41   ` David Marchand
  4 siblings, 0 replies; 81+ messages in thread
From: David Marchand @ 2023-08-25  8:41 UTC (permalink / raw)
  To: Tyler Retzlaff; +Cc: dev, thomas, stephen, mb, bruce.richardson, ferruh.yigit

On Tue, Apr 4, 2023 at 2:12 AM Tyler Retzlaff
<roretzla@linux.microsoft.com> wrote:
>
> As discussed technical board meeting 2023-02-22
> http://mails.dpdk.org/archives/dev/2023-February/263516.html
>
> We will bring support in pieces for the MSVC compiler, there will be
> some abstractions and functions introduced before the compiler is
> capable of compiling DPDK in order to make parallel progress
> while waiting for standard atomics in 23.07.
>
> A higher level plan / order of work is available in the Microsoft
> roadmap for 23.07 and 23.11.

I rebased this series following Bruce rework on app/test/ and applied it.
Thanks.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 81+ messages in thread

end of thread, other threads:[~2023-08-25  8:41 UTC | newest]

Thread overview: 81+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-23 22:14 [PATCH 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
2022-11-23 22:14 ` [PATCH 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
2023-04-03 21:46   ` Mattias Rönnblom
2022-11-23 22:14 ` [PATCH 2/2] test/bitcount: add bitcount tests Tyler Retzlaff
2022-11-23 23:43 ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
2022-11-23 23:43   ` [PATCH v2 1/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
2022-11-24 10:17     ` Morten Brørup
2022-11-28 17:13       ` Tyler Retzlaff
2022-11-28 17:22         ` Morten Brørup
2022-11-28 17:27           ` Tyler Retzlaff
2023-01-05  9:04             ` Thomas Monjalon
2023-01-05 17:23               ` Tyler Retzlaff
2023-01-05 17:27                 ` Tyler Retzlaff
2023-01-05 20:57                   ` Tyler Retzlaff
2023-01-05 21:34                     ` Morten Brørup
2023-01-05 22:06                       ` Tyler Retzlaff
2023-01-05 23:10                         ` Morten Brørup
2023-01-06  1:04                           ` Tyler Retzlaff
2023-01-06 10:09                             ` Thomas Monjalon
2023-01-06 10:00                   ` Thomas Monjalon
2023-01-05  7:09     ` Morten Brørup
2023-01-05  9:01       ` Thomas Monjalon
2023-01-05 17:21         ` Tyler Retzlaff
2023-01-06  0:32           ` Stephen Hemminger
2023-01-06 11:48             ` Bruce Richardson
2023-01-06 12:41               ` Morten Brørup
2023-01-06 13:40                 ` Thomas Monjalon
2023-01-06 18:58                   ` Tyler Retzlaff
2023-01-06 20:51                     ` Thomas Monjalon
2023-01-10  9:18                       ` Ferruh Yigit
2023-01-06 18:47               ` Tyler Retzlaff
2023-01-09  8:50                 ` Bruce Richardson
2023-04-04 21:23       ` Tyler Retzlaff
2023-04-05  8:44         ` Bruce Richardson
2023-04-05 15:22           ` Tyler Retzlaff
2023-04-05 15:51             ` Bruce Richardson
2023-04-05 17:25               ` Tyler Retzlaff
2022-11-23 23:43   ` [PATCH v2 2/2] test/bitcount: add bitcount tests Tyler Retzlaff
2023-01-04 23:46   ` [PATCH v2 0/2] eal: provide leading and trailing zero bit count Tyler Retzlaff
2023-01-09 17:36   ` [PATCH v4 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
2023-01-09 17:36     ` [PATCH v4 1/2] eal: move bit operation functions from common to bitops header Tyler Retzlaff
2023-01-10 13:56       ` Ferruh Yigit
2023-01-09 17:36     ` [PATCH v4 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
2023-01-10 13:55       ` Ferruh Yigit
2023-01-10 17:34         ` Tyler Retzlaff
2023-01-10 18:37         ` Tyler Retzlaff
2023-01-10 13:56     ` [PATCH v4 0/2] " Ferruh Yigit
2023-01-06 22:01 ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Tyler Retzlaff
2023-01-06 22:01   ` [PATCH v3 1/3] eal: move bit functions from common to bitops header Tyler Retzlaff
2023-01-06 22:01   ` [PATCH v3 2/3] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
2023-01-06 22:01   ` [PATCH v3 3/3] test/bitcount: add bitcount tests Tyler Retzlaff
2023-01-07  8:15     ` Thomas Monjalon
2023-01-09 16:57       ` Tyler Retzlaff
2023-01-09 17:26         ` Tyler Retzlaff
2023-01-07 13:40     ` Morten Brørup
2023-01-09  8:51   ` [PATCH v3 0/3] eal: provide leading and trailing zero bit count Bruce Richardson
2023-01-10 19:38 ` [PATCH v5 0/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
2023-01-10 19:38   ` [PATCH v5 1/2] eal: move bit operation common to bitops header Tyler Retzlaff
2023-01-10 19:38   ` [PATCH v5 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
2023-01-10 19:46 ` [PATCH v6 0/2] " Tyler Retzlaff
2023-01-10 19:46   ` [PATCH v6 1/2] eal: move bit operation common to bitops header Tyler Retzlaff
2023-01-10 19:46   ` [PATCH v6 2/2] eal: provide leading and trailing zero bit count abstraction Tyler Retzlaff
2023-01-20 22:14   ` [PATCH v6 0/2] " Tyler Retzlaff
2023-02-02  9:14     ` David Marchand
2023-02-02 10:56       ` David Marchand
2023-02-02 15:57         ` Tyler Retzlaff
2023-02-03  9:14           ` David Marchand
2023-02-02 15:56       ` Tyler Retzlaff
2023-02-03  9:21         ` David Marchand
2023-04-01  0:45 ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Tyler Retzlaff
2023-04-01  0:45   ` [PATCH v7 1/4] eal: move bit count functions to bitops header Tyler Retzlaff
2023-04-01  0:45   ` [PATCH v7 2/4] eal: provide abstracted bit count functions Tyler Retzlaff
2023-04-01  0:45   ` [PATCH v7 3/4] pipeline: add include of bitops Tyler Retzlaff
2023-04-01  0:45   ` [PATCH v7 4/4] maintainers: add bitcount test under EAL API and common code Tyler Retzlaff
2023-04-01  7:08   ` [PATCH v7 0/4] eal: provide abstracted bit counting functions Morten Brørup
2023-04-04  0:11 ` [PATCH v8 0/3] " Tyler Retzlaff
2023-04-04  0:11   ` [PATCH v8 1/3] eal: move bit count functions to bitops header Tyler Retzlaff
2023-04-04  0:11   ` [PATCH v8 2/3] eal: provide abstracted bit count functions Tyler Retzlaff
2023-04-04  0:11   ` [PATCH v8 3/3] maintainers: add bitcount test under EAL API and common code Tyler Retzlaff
2023-04-04  8:27   ` [PATCH v8 0/3] eal: provide abstracted bit counting functions Bruce Richardson
2023-08-25  8:41   ` David Marchand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).