]> Savannah Git Hosting - gnulib.git/commitdiff
Optimize three-valued comparison between integers.
authorBruno Haible <bruno@clisp.org>
Wed, 22 Jul 2020 16:35:20 +0000 (18:35 +0200)
committerBruno Haible <bruno@clisp.org>
Thu, 23 Jul 2020 22:13:55 +0000 (00:13 +0200)
(a > b ? 1 : a < b ? -1 : 0) is the same as (a > b) - (a < b).

* m4/gnulib-common.m4 (gl_COMMON): Define _GL_CMP.
* lib/c-strcasecmp.c (c_strcasecmp): Use _GL_CMP.
* lib/c-strncasecmp.c (c_strncasecmp): Likewise.
* lib/dfa.c (compare): Likewise.
* lib/fts.c (fts_compare_ino): Likewise.
* lib/mbmemcasecmp.c (mbmemcasecmp): Likewise.
* lib/mbscasecmp.c (mbscasecmp): Likewise.
* lib/mbsncasecmp.c (mbsncasecmp): Likewise.
* lib/memcasecmp.c (memcasecmp): Likewise.
* lib/memcmp2.c (memcmp2): Likewise.
* lib/savedir.c (direntry_cmp_inode): Likewise.
* lib/strcasecmp.c (strcasecmp): Likewise.
* lib/strncasecmp.c (strncasecmp): Likewise.
* lib/unistr/u-cmp2.h (FUNC): Likewise.

15 files changed:
ChangeLog
lib/c-strcasecmp.c
lib/c-strncasecmp.c
lib/dfa.c
lib/fts.c
lib/mbmemcasecmp.c
lib/mbscasecmp.c
lib/mbsncasecmp.c
lib/memcasecmp.c
lib/memcmp2.c
lib/savedir.c
lib/strcasecmp.c
lib/strncasecmp.c
lib/unistr/u-cmp2.h
m4/gnulib-common.m4

index 08804223d1bf3fa60f038d853eb2243e6328debd..3203040d0f7987fe22dbd9df45f22fd2f2e938ca 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2020-07-23  Bruno Haible  <bruno@clisp.org>
+
+       Optimize three-valued comparison between integers.
+       (a > b ? 1 : a < b ? -1 : 0) is the same as (a > b) - (a < b).
+       * m4/gnulib-common.m4 (gl_COMMON): Define _GL_CMP.
+       * lib/c-strcasecmp.c (c_strcasecmp): Use _GL_CMP.
+       * lib/c-strncasecmp.c (c_strncasecmp): Likewise.
+       * lib/dfa.c (compare): Likewise.
+       * lib/fts.c (fts_compare_ino): Likewise.
+       * lib/mbmemcasecmp.c (mbmemcasecmp): Likewise.
+       * lib/mbscasecmp.c (mbscasecmp): Likewise.
+       * lib/mbsncasecmp.c (mbsncasecmp): Likewise.
+       * lib/memcasecmp.c (memcasecmp): Likewise.
+       * lib/memcmp2.c (memcmp2): Likewise.
+       * lib/savedir.c (direntry_cmp_inode): Likewise.
+       * lib/strcasecmp.c (strcasecmp): Likewise.
+       * lib/strncasecmp.c (strncasecmp): Likewise.
+       * lib/unistr/u-cmp2.h (FUNC): Likewise.
+
 2020-07-23  Bruno Haible  <bruno@clisp.org>
 
        lchmod: Use /proc on Cygwin.
index 3ac650f87c1fb0769bb42f85f60918f59b0f190c..1de04b7066a2c54040503864ec06f7136fbc71cf 100644 (file)
@@ -52,5 +52,5 @@ c_strcasecmp (const char *s1, const char *s2)
     /* On machines where 'char' and 'int' are types of the same size, the
        difference of two 'unsigned char' values - including the sign bit -
        doesn't fit in an 'int'.  */
-    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+    return _GL_CMP (c1, c2);
 }
index a4e67d1655b9f6b93342a3cdaa274f2418680282..1782e54ad1862f680b7a68676e66242a179156bd 100644 (file)
@@ -52,5 +52,5 @@ c_strncasecmp (const char *s1, const char *s2, size_t n)
     /* On machines where 'char' and 'int' are types of the same size, the
        difference of two 'unsigned char' values - including the sign bit -
        doesn't fit in an 'int'.  */
-    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+    return _GL_CMP (c1, c2);
 }
index dee7be86172db44683e345669caef9ab4160a51a..1d2d4045740244b49f0d819373f796908251f840 100644 (file)
--- a/lib/dfa.c
+++ b/lib/dfa.c
@@ -2466,7 +2466,7 @@ static int
 compare (const void *a, const void *b)
 {
   position const *p = a, *q = b;
-  return p->index < q->index ? -1 : p->index > q->index;
+  return _GL_CMP (p->index, q->index);
 }
 
 static void
index 5e357bee590efe4816d0e19d912928cc36193f3e..a34092ca2520e7d6735a65499a6bf5e1f8e67d94 100644 (file)
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -1190,8 +1190,7 @@ fts_children (register FTS *sp, int instr)
 static int
 fts_compare_ino (struct _ftsent const **a, struct _ftsent const **b)
 {
-  return (a[0]->fts_statp->st_ino < b[0]->fts_statp->st_ino ? -1
-          : b[0]->fts_statp->st_ino < a[0]->fts_statp->st_ino ? 1 : 0);
+  return _GL_CMP (a[0]->fts_statp->st_ino, b[0]->fts_statp->st_ino);
 }
 
 /* Map the dirent.d_type value, DTYPE, to the corresponding stat.st_mode
index 57039d2950e763273af596edc6d7f907988bad99..d0eea69d4b841c10ef9906f048ba2cceaed8ac16 100644 (file)
@@ -33,7 +33,7 @@ int
 mbmemcasecmp (const char *s1, size_t n1, const char *s2, size_t n2)
 {
   if (s1 == s2)
-    return (n1 < n2 ? -1 : n1 > n2 ? 1 : 0);
+    return _GL_CMP (n1, n2);
 
   if (MB_CUR_MAX > 1)
     {
@@ -80,7 +80,7 @@ mbmemcasecmp (const char *s1, size_t n1, const char *s2, size_t n2)
                 /* On machines where 'char' and 'int' are types of the same
                    size, the difference of two 'unsigned char' values
                    - including the sign bit - doesn't fit in an 'int'.  */
-                return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+                return _GL_CMP (c1, c2);
             }
           ++p1;
           ++p2;
index 9a1ea4bb3569ea8850bfdd82afb56a4de1657aee..976e94a070a1bd7dad3d5025e9805f4b8be145a0 100644 (file)
@@ -93,6 +93,6 @@ mbscasecmp (const char *s1, const char *s2)
         /* On machines where 'char' and 'int' are types of the same size, the
            difference of two 'unsigned char' values - including the sign bit -
            doesn't fit in an 'int'.  */
-        return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+        return _GL_CMP (c1, c2);
     }
 }
index a414a6986fcea6fde1ddf633e21bf5eb0dfd1c2f..da43d5cb8ce9d8a6884f0a8382ee1cab47b07ec4 100644 (file)
@@ -94,6 +94,6 @@ mbsncasecmp (const char *s1, const char *s2, size_t n)
         /* On machines where 'char' and 'int' are types of the same size, the
            difference of two 'unsigned char' values - including the sign bit -
            doesn't fit in an 'int'.  */
-        return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+        return _GL_CMP (c1, c2);
     }
 }
index a44379373c446e30be30513fb694e6845233a68d..6720b8cdb838ca15795409cd5c635a8ff546a42e 100644 (file)
@@ -40,8 +40,7 @@ memcasecmp (const void *vs1, const void *vs2, size_t n)
       unsigned char u2 = s2[i];
       int U1 = toupper (u1);
       int U2 = toupper (u2);
-      int diff = (UCHAR_MAX <= INT_MAX ? U1 - U2
-                  : U1 < U2 ? -1 : U2 < U1);
+      int diff = (UCHAR_MAX <= INT_MAX ? U1 - U2 : _GL_CMP (U1, U2));
       if (diff)
         return diff;
     }
index c9c33168706b5eef45477f9acb2918019a5a9274..bbfbb0294dec2c2d6d6b5c02bd72f0a7ac831e0e 100644 (file)
@@ -26,11 +26,6 @@ memcmp2 (const char *s1, size_t n1, const char *s2, size_t n2)
 {
   int cmp = memcmp (s1, s2, n1 <= n2 ? n1 : n2);
   if (cmp == 0)
-    {
-      if (n1 < n2)
-        cmp = -1;
-      else if (n1 > n2)
-        cmp = 1;
-    }
+    cmp = _GL_CMP (n1, n2);
   return cmp;
 }
index 5d7151ea8176f00dbbc63da6fb06f2e1b2f2963d..c93b81a0b94fd48f8913926dad62c6721cbc35bb 100644 (file)
@@ -65,7 +65,7 @@ direntry_cmp_inode (void const *a, void const *b)
   direntry_t const *dea = a;
   direntry_t const *deb = b;
 
-  return dea->ino < deb->ino ? -1 : dea->ino > deb->ino;
+  return _GL_CMP (dea->ino, deb->ino);
 }
 #endif
 
index c0b610e5e890817b349f2b188415074fa2d7dc59..bcb9adb18586072d6fa88d37650f0769b8e4f9c3 100644 (file)
@@ -58,5 +58,5 @@ strcasecmp (const char *s1, const char *s2)
     /* On machines where 'char' and 'int' are types of the same size, the
        difference of two 'unsigned char' values - including the sign bit -
        doesn't fit in an 'int'.  */
-    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+    return _GL_CMP (c1, c2);
 }
index 4c1b5b52c962e2c7031b5f25680ef92f5c2748b2..396d1caaa270a28d511318616b8974ef11e077f4 100644 (file)
@@ -58,5 +58,5 @@ strncasecmp (const char *s1, const char *s2, size_t n)
     /* On machines where 'char' and 'int' are types of the same size, the
        difference of two 'unsigned char' values - including the sign bit -
        doesn't fit in an 'int'.  */
-    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+    return _GL_CMP (c1, c2);
 }
index 85a5db80c5243c46a21dd8d7b787ef37d9c2a2c1..1e0ea72802cd20e336785f148ef938679d445fea 100644 (file)
@@ -21,12 +21,7 @@ FUNC (const UNIT *s1, size_t n1, const UNIT *s2, size_t n2)
   int cmp = U_CMP (s1, s2, MIN (n1, n2));
 
   if (cmp == 0)
-    {
-      if (n1 < n2)
-        cmp = -1;
-      else if (n1 > n2)
-        cmp = 1;
-    }
+    cmp = _GL_CMP (n1, n2);
 
   return cmp;
 }
index f4ba5e3a00d02ce1ebcc2f68e3c73da569511e10..ba4239188db84534d584ff1ad8b886bcf5a4ef28 100644 (file)
@@ -1,4 +1,4 @@
-# gnulib-common.m4 serial 50
+# gnulib-common.m4 serial 51
 dnl Copyright (C) 2007-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -292,6 +292,20 @@ AC_DEFUN([gl_COMMON_BODY], [
        that may clobber errno, it needs to save and restore the value of
        errno.  */
 #define _GL_ASYNC_SAFE
+])
+  AH_VERBATIM([micro_optimizations],
+[/* _GL_CMP (n1, n2) performs a three-valued comparison on n1 vs. n2.
+   It returns
+     1  if n1 > n2
+     0  if n1 == n2
+     -1 if n1 < n2
+   The naïve code   (n1 > n2 ? 1 : n1 < n2 ? -1 : 0)  produces a conditional
+   jump with nearly all GCC versions up to GCC 10.
+   This variant     (n1 < n2 ? -1 : n1 > n2)  produces a conditional with many
+   GCC versions up to GCC 9.
+   The better code  (n1 > n2) - (n1 < n2)  from Hacker's Delight § 2-9
+   avoids conditional jumps in all GCC versions >= 3.4.  */
+#define _GL_CMP(n1, n2) ((n1) > (n2)) - ((n1) < (n2))
 ])
   dnl Hint which direction to take regarding cross-compilation guesses:
   dnl When a user installs a program on a platform they are not intimately