In new code, I'm making intensive use of the functions ffs and ffsll, for
searching in a bitset. So, these functions should better be well optimized,
even for MSVC.

And while at it, also the integer_length* functions.


2020-08-03  Bruno Haible  <br...@clisp.org>

        integer_length_ll: Optimize for MSVC in 64-bit mode.
        * lib/integer_length_l.c (MSVC_BUILTIN): Define for MSVC in 64-bit mode.
        (FUNC): On MSVC, use MSVC_BUILTIN if defined.

2020-08-03  Bruno Haible  <br...@clisp.org>

        integer_length_ll: Optimize for MSVC in 32-bit mode.
        * lib/integer_length_l.c: Include <intrin.h>.
        (integer_length): Define as inline function, like in
        lib/integer_length.c.

2020-08-03  Bruno Haible  <br...@clisp.org>

        integer_length: Optimize for MSVC.
        * lib/integer_length.c: Include <intrin.h>.
        (integer_length): With MSVC, use the _BitScanReverse built-in.

2020-08-03  Bruno Haible  <br...@clisp.org>

        ffsll: Optimize for MSVC in 64-bit mode.
        * lib/ffsl.h (FUNC): On MSVC, use MSVC_BUILTIN if defined.
        * lib/ffsll.c (MSVC_BUILTIN): Define for MSVC in 64-bit mode.
        * lib/ffsl.c (MSVC_BUILTIN): Define for MSVC.

2020-08-03  Bruno Haible  <br...@clisp.org>

        ffsll: Optimize for MSVC in 32-bit mode.
        * lib/ffsl.h: Include <intrin.h>.
        (ffs): Define as inline function, like in lib/ffs.c.

2020-08-03  Bruno Haible  <br...@clisp.org>

        ffs: Optimize for MSVC.
        * lib/ffs.c: Include <intrin.h>.
        (ffs): With MSVC, use the _BitScanForward built-in.

>From 353cc7c6906f650fa228d295dad270637f9441c7 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 4 Aug 2020 00:05:05 +0200
Subject: [PATCH 1/6] ffs: Optimize for MSVC.

* lib/ffs.c: Include <intrin.h>.
(ffs): With MSVC, use the _BitScanForward built-in.
---
 ChangeLog |  6 ++++++
 lib/ffs.c | 12 ++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 526747e..773a9f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2020-08-03  Bruno Haible  <br...@clisp.org>
 
+	ffs: Optimize for MSVC.
+	* lib/ffs.c: Include <intrin.h>.
+	(ffs): With MSVC, use the _BitScanForward built-in.
+
+2020-08-03  Bruno Haible  <br...@clisp.org>
+
 	sigprocmask: Try to avoid breakage for people who use an Autoconf cache.
 	* m4/signalblocking.m4 (gl_SIGNALBLOCKING): Change the name of the cache
 	variable.
diff --git a/lib/ffs.c b/lib/ffs.c
index ba4915e..d8a65ca 100644
--- a/lib/ffs.c
+++ b/lib/ffs.c
@@ -23,11 +23,23 @@
 
 #include <limits.h>
 
+#if defined _MSC_VER
+# include <intrin.h>
+#endif
+
 int
 ffs (int i)
 {
 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
   return __builtin_ffs (i);
+#elif defined _MSC_VER
+  /* _BitScanForward
+     <https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64> */
+  unsigned long bit;
+  if (_BitScanForward (&bit, i))
+    return bit + 1;
+  else
+    return 0;
 #else
   /* <https://github.com/gibsjose/BitHacks>
      gives this deBruijn constant for a branch-less computation, although
-- 
2.7.4

>From c728189201864850c562862fa7fc54d925c472e0 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 4 Aug 2020 00:11:02 +0200
Subject: [PATCH 2/6] ffsll: Optimize for MSVC in 32-bit mode.

* lib/ffsl.h: Include <intrin.h>.
(ffs): Define as inline function, like in lib/ffs.c.
---
 ChangeLog  |  6 ++++++
 lib/ffsl.h | 16 ++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 773a9f5..0a336bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2020-08-03  Bruno Haible  <br...@clisp.org>
 
+	ffsll: Optimize for MSVC in 32-bit mode.
+	* lib/ffsl.h: Include <intrin.h>.
+	(ffs): Define as inline function, like in lib/ffs.c.
+
+2020-08-03  Bruno Haible  <br...@clisp.org>
+
 	ffs: Optimize for MSVC.
 	* lib/ffs.c: Include <intrin.h>.
 	(ffs): With MSVC, use the _BitScanForward built-in.
diff --git a/lib/ffsl.h b/lib/ffsl.h
index cea4386..d5c5a97 100644
--- a/lib/ffsl.h
+++ b/lib/ffsl.h
@@ -27,6 +27,22 @@
 #include <limits.h>
 #include <strings.h>
 
+#if defined _MSC_VER
+# include <intrin.h>
+/* Copied from ffs.c.  */
+static inline int
+ffs (int i)
+{
+  /* _BitScanForward
+     <https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64> */
+  unsigned long bit;
+  if (_BitScanForward (&bit, i))
+    return bit + 1;
+  else
+    return 0;
+}
+#endif
+
 #if !defined FUNC || !defined TYPE
 # error
 #endif
-- 
2.7.4

>From 1552de7c513ffbedf675de10b77a6d5c264ee3b2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 4 Aug 2020 00:13:46 +0200
Subject: [PATCH 3/6] ffsll: Optimize for MSVC in 64-bit mode.

* lib/ffsl.h (FUNC): On MSVC, use MSVC_BUILTIN if defined.
* lib/ffsll.c (MSVC_BUILTIN): Define for MSVC in 64-bit mode.
* lib/ffsl.c (MSVC_BUILTIN): Define for MSVC.
---
 ChangeLog   | 7 +++++++
 lib/ffsl.c  | 1 +
 lib/ffsl.h  | 8 ++++++++
 lib/ffsll.c | 3 +++
 4 files changed, 19 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 0a336bf..51b2be7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-08-03  Bruno Haible  <br...@clisp.org>
 
+	ffsll: Optimize for MSVC in 64-bit mode.
+	* lib/ffsl.h (FUNC): On MSVC, use MSVC_BUILTIN if defined.
+	* lib/ffsll.c (MSVC_BUILTIN): Define for MSVC in 64-bit mode.
+	* lib/ffsl.c (MSVC_BUILTIN): Define for MSVC.
+
+2020-08-03  Bruno Haible  <br...@clisp.org>
+
 	ffsll: Optimize for MSVC in 32-bit mode.
 	* lib/ffsl.h: Include <intrin.h>.
 	(ffs): Define as inline function, like in lib/ffs.c.
diff --git a/lib/ffsl.c b/lib/ffsl.c
index ee99ba7..198cacb 100644
--- a/lib/ffsl.c
+++ b/lib/ffsl.c
@@ -1,4 +1,5 @@
 #define FUNC ffsl
 #define TYPE long int
 #define GCC_BUILTIN __builtin_ffsl
+#define MSVC_BUILTIN _BitScanForward
 #include "ffsl.h"
diff --git a/lib/ffsl.h b/lib/ffsl.h
index d5c5a97..fa5c093 100644
--- a/lib/ffsl.h
+++ b/lib/ffsl.h
@@ -52,6 +52,14 @@ FUNC (TYPE i)
 {
 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined GCC_BUILTIN
   return GCC_BUILTIN (i);
+#elif defined _MSC_VER && defined MSVC_BUILTIN
+  /* _BitScanForward, _BitScanForward64
+     <https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64> */
+  unsigned long bit;
+  if (MSVC_BUILTIN (&bit, i))
+    return bit + 1;
+  else
+    return 0;
 #else
   unsigned TYPE j = i;
   /* Split j into chunks, and look at one chunk after the other.  */
diff --git a/lib/ffsll.c b/lib/ffsll.c
index f0e9425..80a273c 100644
--- a/lib/ffsll.c
+++ b/lib/ffsll.c
@@ -1,4 +1,7 @@
 #define FUNC ffsll
 #define TYPE long long int
 #define GCC_BUILTIN __builtin_ffsll
+#ifdef _WIN64
+# define MSVC_BUILTIN _BitScanForward64
+#endif
 #include "ffsl.h"
-- 
2.7.4

>From 8c7b90680b73580b5c257baa3c9c22239ab0c3d1 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 4 Aug 2020 00:40:24 +0200
Subject: [PATCH 4/6] integer_length: Optimize for MSVC.

* lib/integer_length.c: Include <intrin.h>.
(integer_length): With MSVC, use the _BitScanReverse built-in.
---
 ChangeLog            |  6 ++++++
 lib/integer_length.c | 14 ++++++++++----
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 51b2be7..b2169e3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2020-08-03  Bruno Haible  <br...@clisp.org>
 
+	integer_length: Optimize for MSVC.
+	* lib/integer_length.c: Include <intrin.h>.
+	(integer_length): With MSVC, use the _BitScanReverse built-in.
+
+2020-08-03  Bruno Haible  <br...@clisp.org>
+
 	ffsll: Optimize for MSVC in 64-bit mode.
 	* lib/ffsl.h (FUNC): On MSVC, use MSVC_BUILTIN if defined.
 	* lib/ffsll.c (MSVC_BUILTIN): Define for MSVC in 64-bit mode.
diff --git a/lib/integer_length.c b/lib/integer_length.c
index edad54b..43d8f49 100644
--- a/lib/integer_length.c
+++ b/lib/integer_length.c
@@ -25,10 +25,8 @@
 
 #include "float+.h"
 
-/* MSVC with option -fp:strict refuses to compile constant initializers that
-   contain floating-point operations.  Pacify this compiler.  */
-#ifdef _MSC_VER
-# pragma fenv_access (off)
+#if defined _MSC_VER
+# include <intrin.h>
 #endif
 
 #define NBITS (sizeof (unsigned int) * CHAR_BIT)
@@ -41,6 +39,14 @@ integer_length (unsigned int x)
     return 0;
   else
     return NBITS - __builtin_clz (x);
+#elif defined _MSC_VER
+  /* _BitScanReverse
+     <https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64> */
+  unsigned long bit;
+  if (_BitScanReverse (&bit, x))
+    return bit + 1;
+  else
+    return 0;
 #else
 # if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
   if (NBITS <= DBL_MANT_BIT)
-- 
2.7.4

>From dc87bda7182bf9ad9034ca739f46b3dbb9dc4632 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 4 Aug 2020 01:10:23 +0200
Subject: [PATCH 5/6] integer_length_ll: Optimize for MSVC in 32-bit mode.

* lib/integer_length_l.c: Include <intrin.h>.
(integer_length): Define as inline function, like in
lib/integer_length.c.
---
 ChangeLog              |  7 +++++++
 lib/integer_length_l.c | 16 ++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index b2169e3..bfd2ade 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2020-08-03  Bruno Haible  <br...@clisp.org>
 
+	integer_length_ll: Optimize for MSVC in 32-bit mode.
+	* lib/integer_length_l.c: Include <intrin.h>.
+	(integer_length): Define as inline function, like in
+	lib/integer_length.c.
+
+2020-08-03  Bruno Haible  <br...@clisp.org>
+
 	integer_length: Optimize for MSVC.
 	* lib/integer_length.c: Include <intrin.h>.
 	(integer_length): With MSVC, use the _BitScanReverse built-in.
diff --git a/lib/integer_length_l.c b/lib/integer_length_l.c
index 7a60357..ea52ac3 100644
--- a/lib/integer_length_l.c
+++ b/lib/integer_length_l.c
@@ -37,6 +37,22 @@
 # define GCC_BUILTIN __builtin_clzl
 #endif
 
+#if defined _MSC_VER
+# include <intrin.h>
+/* Copied from integer_length.c.  */
+static inline int
+integer_length (unsigned int x)
+{
+  /* _BitScanReverse
+     <https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64> */
+  unsigned long bit;
+  if (_BitScanReverse (&bit, x))
+    return bit + 1;
+  else
+    return 0;
+}
+#endif
+
 #define NBITS (sizeof (TYPE) * CHAR_BIT)
 
 /* Modify shift count to be in bounds, even in dead code, otherwise GCC
-- 
2.7.4

>From eb7f785f5ad4fd6a9d9e8e74e42838a27d1dff86 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Tue, 4 Aug 2020 01:17:36 +0200
Subject: [PATCH 6/6] integer_length_ll: Optimize for MSVC in 64-bit mode.

* lib/integer_length_l.c (MSVC_BUILTIN): Define for MSVC in 64-bit mode.
(FUNC): On MSVC, use MSVC_BUILTIN if defined.
---
 ChangeLog              |  6 ++++++
 lib/integer_length_l.c | 12 ++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index bfd2ade..9919a40 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2020-08-03  Bruno Haible  <br...@clisp.org>
 
+	integer_length_ll: Optimize for MSVC in 64-bit mode.
+	* lib/integer_length_l.c (MSVC_BUILTIN): Define for MSVC in 64-bit mode.
+	(FUNC): On MSVC, use MSVC_BUILTIN if defined.
+
+2020-08-03  Bruno Haible  <br...@clisp.org>
+
 	integer_length_ll: Optimize for MSVC in 32-bit mode.
 	* lib/integer_length_l.c: Include <intrin.h>.
 	(integer_length): Define as inline function, like in
diff --git a/lib/integer_length_l.c b/lib/integer_length_l.c
index ea52ac3..161f1af 100644
--- a/lib/integer_length_l.c
+++ b/lib/integer_length_l.c
@@ -31,10 +31,14 @@
 # define FUNC integer_length_ll
 # define TYPE unsigned long long
 # define GCC_BUILTIN __builtin_clzll
+# ifdef _WIN64
+#  define MSVC_BUILTIN _BitScanReverse64
+# endif
 #else
 # define FUNC integer_length_l
 # define TYPE unsigned long
 # define GCC_BUILTIN __builtin_clzl
+# define MSVC_BUILTIN _BitScanReverse
 #endif
 
 #if defined _MSC_VER
@@ -67,6 +71,14 @@ FUNC (TYPE x)
     return 0;
   else
     return NBITS - GCC_BUILTIN (x);
+#elif defined _MSC_VER && defined MSVC_BUILTIN
+  /* _BitScanReverse, _BitScanReverse64
+     <https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64> */
+  unsigned long bit;
+  if (MSVC_BUILTIN (&bit, x))
+    return bit + 1;
+  else
+    return 0;
 #else
   /* Split x into chunks, and look at one chunk after the other.  */
   if (sizeof (TYPE) > 2 * sizeof (unsigned int))
-- 
2.7.4

Reply via email to