All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rostislav Krasny <rostiprodev@gmail.com>
To: git@vger.kernel.org
Cc: Rostislav Krasny <rostiprodev@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	Sebastian Andrzej Siewior <sebastian@breakpoint.cc>,
	Jeff King <peff@peff.net>
Subject: [PATCH 1/1] compat: modernize and simplify byte swapping functions
Date: Fri,  2 Jan 2026 02:27:35 +0200	[thread overview]
Message-ID: <20260102002735.31390-2-rostiprodev@gmail.com> (raw)
In-Reply-To: <20260102002735.31390-1-rostiprodev@gmail.com>

Replace manual bit operations with memcpy + network functions for better
maintainability. Add missing 16-bit network byte order conversion.

Key improvements:
- Simplify the get_be*() and put_be*() functions
- Add bswap16() macro with automatic compiler optimization:
  * GCC/Clang: __builtin_bswap16() intrinsic
  * MSVC: _byteswap_ushort() intrinsic
- Add default_bswap16() static inline function with manual fallback implementation
- Rename default_swab32() to default_bswap32() for naming consistency
- Add ntohs() and htons() macros for complete 16/32/64-bit network conversion
- Add put_be16() function for API completeness alongside existing put_be*() and
  get_be*() functions
- Performance improvements (GCC 15.2.1, Clang 21.1.7):
  * on x86-64 with -O0 4.2x faster (GCC), 3.7x faster (Clang)
  * on x86-64 with -O1 4x faster (GCC), identical (Clang)
  * on x86-64 with -O2 identical (GCC), 1.8x faster (Clang)

Signed-off-by: Rostislav Krasny <rostiprodev@gmail.com>
---
 compat/bswap.h | 74 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 44 insertions(+), 30 deletions(-)

diff --git a/compat/bswap.h b/compat/bswap.h
index 28635ebc69..f9954ef090 100644
--- a/compat/bswap.h
+++ b/compat/bswap.h
@@ -9,10 +9,15 @@
  */
 
 /*
- * Default version that the compiler ought to optimize properly with
+ * Default versions that the compiler ought to optimize properly with
  * constant values.
  */
-static inline uint32_t default_swab32(uint32_t val)
+static inline uint16_t default_bswap16(uint16_t val)
+{
+	return ((val & 0xff00) >> 8) | ((val & 0x00ff) << 8);
+}
+
+static inline uint32_t default_bswap32(uint32_t val)
 {
 	return (((val & 0xff000000) >> 24) |
 		((val & 0x00ff0000) >>  8) |
@@ -40,6 +45,7 @@ static inline uint64_t default_bswap64(uint64_t val)
 # define __has_builtin(x) 0
 #endif
 
+#undef bswap16
 #undef bswap32
 #undef bswap64
 
@@ -47,6 +53,7 @@ static inline uint64_t default_bswap64(uint64_t val)
 
 #include <stdlib.h>
 
+#define bswap16(x) _byteswap_ushort(x)
 #define bswap32(x) _byteswap_ulong(x)
 #define bswap64(x) _byteswap_uint64(x)
 
@@ -54,8 +61,9 @@ static inline uint64_t default_bswap64(uint64_t val)
 #define GIT_BIG_ENDIAN 4321
 #define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN
 
-#elif __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)
+#elif __has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)
 
+#define bswap16(x) __builtin_bswap16((x))
 #define bswap32(x) __builtin_bswap32((x))
 #define bswap64(x) __builtin_bswap64((x))
 
@@ -98,24 +106,36 @@ static inline uint64_t default_bswap64(uint64_t val)
 
 #endif
 
+#undef ntohs
+#undef htons
 #undef ntohl
 #undef htonl
 #undef ntohll
 #undef htonll
 
 #if GIT_BYTE_ORDER == GIT_BIG_ENDIAN
+# define ntohs(x) (x)
+# define htons(x) (x)
 # define ntohl(x) (x)
 # define htonl(x) (x)
 # define ntohll(x) (x)
 # define htonll(x) (x)
 #else
 
+# if defined(bswap16)
+#  define ntohs(x) bswap16(x)
+#  define htons(x) bswap16(x)
+# else
+#  define ntohs(x) default_bswap16(x)
+#  define htons(x) default_bswap16(x)
+# endif
+
 # if defined(bswap32)
 #  define ntohl(x) bswap32(x)
 #  define htonl(x) bswap32(x)
 # else
-#  define ntohl(x) default_swab32(x)
-#  define htonl(x) default_swab32(x)
+#  define ntohl(x) default_bswap32(x)
+#  define htonl(x) default_bswap32(x)
 # endif
 
 # if defined(bswap64)
@@ -129,47 +149,41 @@ static inline uint64_t default_bswap64(uint64_t val)
 
 static inline uint16_t get_be16(const void *ptr)
 {
-	const unsigned char *p = ptr;
-	return	(uint16_t)p[0] << 8 |
-		(uint16_t)p[1] << 0;
+	uint16_t n;
+	memcpy(&n, ptr, sizeof n);
+	return ntohs(n);
 }
 
 static inline uint32_t get_be32(const void *ptr)
 {
-	const unsigned char *p = ptr;
-	return	(uint32_t)p[0] << 24 |
-		(uint32_t)p[1] << 16 |
-		(uint32_t)p[2] <<  8 |
-		(uint32_t)p[3] <<  0;
+	uint32_t n;
+	memcpy(&n, ptr, sizeof n);
+	return ntohl(n);
 }
 
 static inline uint64_t get_be64(const void *ptr)
 {
-	const unsigned char *p = ptr;
-	return	(uint64_t)get_be32(&p[0]) << 32 |
-		(uint64_t)get_be32(&p[4]) <<  0;
+	uint64_t n;
+	memcpy(&n, ptr, sizeof n);
+	return ntohll(n);
+}
+
+static inline void put_be16(void *ptr, uint16_t value)
+{
+	uint16_t n = htons(value);
+	memcpy(ptr, &n, sizeof n);
 }
 
 static inline void put_be32(void *ptr, uint32_t value)
 {
-	unsigned char *p = ptr;
-	p[0] = (value >> 24) & 0xff;
-	p[1] = (value >> 16) & 0xff;
-	p[2] = (value >>  8) & 0xff;
-	p[3] = (value >>  0) & 0xff;
+	uint32_t n = htonl(value);
+	memcpy(ptr, &n, sizeof n);
 }
 
 static inline void put_be64(void *ptr, uint64_t value)
 {
-	unsigned char *p = ptr;
-	p[0] = (value >> 56) & 0xff;
-	p[1] = (value >> 48) & 0xff;
-	p[2] = (value >> 40) & 0xff;
-	p[3] = (value >> 32) & 0xff;
-	p[4] = (value >> 24) & 0xff;
-	p[5] = (value >> 16) & 0xff;
-	p[6] = (value >>  8) & 0xff;
-	p[7] = (value >>  0) & 0xff;
+	uint64_t n = htonll(value);
+	memcpy(ptr, &n, sizeof n);
 }
 
 #endif /* COMPAT_BSWAP_H */
-- 
2.52.0


  reply	other threads:[~2026-01-02  0:27 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-02  0:27 [PATCH 0/1] compat: modernize and simplify byte swapping functions Rostislav Krasny
2026-01-02  0:27 ` Rostislav Krasny [this message]
2026-01-02  6:16   ` [PATCH 1/1] " Jeff King
2026-01-02 17:37     ` Rostislav Krasny
2026-01-11 22:05       ` Rostislav Krasny
2026-01-14 21:14         ` Jeff King
2026-01-02  7:29 ` [PATCH 0/1] " Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260102002735.31390-2-rostiprodev@gmail.com \
    --to=rostiprodev@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    --cc=sebastian@breakpoint.cc \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.