在 2024-10-22 22:18, Jacek Caban 写道:
Style-wise, I would perhaps prefer a solution that uses fewer #ifdefs. We could for example change __mingw_has_sse to always return true when it's defined. It would limit optimization opportunities for the compiler, so perhaps we could have it in a header and make it a trivial inline in case __SSE__ is defined? Anyway, the current patch matches how similar things are done in mingw-w64, so I won't insist on that.


Even with that patch, the original patch caching cpuid result would still be beneficial for cases when __SSE__ is not defined.

Here's an updated patch.


--
Best regards,
LIU Hao
From d54cc9e99b4f6130d6e6ac7ac4aaf077026fcb6d Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mo...@126.com>
Date: Tue, 22 Oct 2024 23:16:04 +0800
Subject: [PATCH] crt: Provide a common `__mingw_has_sse()`

This commit moves `__mingw_has_sse()` to a separate file, and makes its
result cacheable.

SSE is required for x86-64, and can be enabled for x86-32 by passing `-msse`
to GCC. On ARM and ARM64 it's always absent. A macro is defined if it would
be known to return a constant.

Co-authored-by: Morilli <molli.ben...@gmail.com>
Signed-off-by: LIU Hao <lh_mo...@126.com>
---
 mingw-w64-crt/Makefile.am            |  2 +-
 mingw-w64-crt/include/internal.h     |  8 ++++++
 mingw-w64-crt/misc/__mingw_has_sse.c | 37 ++++++++++++++++++++++++++++
 mingw-w64-crt/misc/feclearexcept.c   | 31 ++---------------------
 mingw-w64-crt/misc/fegetenv.c        |  6 ++---
 mingw-w64-crt/misc/fegetexceptflag.c | 10 +++-----
 mingw-w64-crt/misc/fesetenv.c        | 10 +++-----
 mingw-w64-crt/misc/fesetexceptflag.c | 10 +++-----
 mingw-w64-crt/misc/fesetround.c      |  8 +++---
 mingw-w64-crt/misc/fetestexcept.c    |  9 +++----
 10 files changed, 68 insertions(+), 63 deletions(-)
 create mode 100644 mingw-w64-crt/misc/__mingw_has_sse.c

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 7db657ed7..b5e23e084 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -1044,7 +1044,7 @@ src_libmingwex=\
   misc/feclearexcept.c   misc/fegetenv.c            misc/fegetexceptflag.c  
misc/fegetround.c            misc/feholdexcept.c    \
   misc/feraiseexcept.c   misc/fesetenv.c            misc/fesetexceptflag.c  
misc/fesetround.c            misc/fetestexcept.c    \
   misc/feupdateenv.c     misc/ftruncate.c           misc/fwide.c            
misc/getlogin.c              misc/getopt.c          \
-  misc/gettimeofday.c \
+  misc/gettimeofday.c    misc/__mingw_has_sse.c      \
   misc/mempcpy.c         misc/mingw-aligned-malloc.c \
   misc/mingw_matherr.c   misc/mingw_mbwc_convert.c  misc/mingw_usleep.c     
misc/mingw_wcstod.c          misc/mingw_wcstof.c    \
   misc/mingw_wcstold.c \
diff --git a/mingw-w64-crt/include/internal.h b/mingw-w64-crt/include/internal.h
index 3786ed7a1..752c5dc96 100644
--- a/mingw-w64-crt/include/internal.h
+++ b/mingw-w64-crt/include/internal.h
@@ -146,6 +146,14 @@ extern "C" {
   PIMAGE_SECTION_HEADER __cdecl _FindPESection (PBYTE pImageBase, DWORD_PTR 
rva);
   BOOL __cdecl _IsNonwritableInCurrentImage (PBYTE pTarget);
 
+#if defined(__SSE__)
+# define __mingw_has_sse()  1
+#elif defined(__i386__)
+  int __mingw_has_sse(void);
+#else
+# define __mingw_has_sse()  0
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/mingw-w64-crt/misc/__mingw_has_sse.c 
b/mingw-w64-crt/misc/__mingw_has_sse.c
new file mode 100644
index 000000000..e8e8a7059
--- /dev/null
+++ b/mingw-w64-crt/misc/__mingw_has_sse.c
@@ -0,0 +1,37 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#if defined(__i386__)
+int __mingw_has_sse (void);
+static int __has_sse = -1;
+
+int __mingw_has_sse(void)
+{
+  int cpuInfo[4], infoType = 1;
+  int o_flag, n_flag;
+
+  if (__has_sse != -1)
+    return __has_sse;
+
+  __asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (o_flag));
+  n_flag = o_flag ^ 0x200000;
+  __asm__ volatile ("pushl %0\n\tpopfl" : : "g" (n_flag));
+  __asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (n_flag));
+  if (n_flag == o_flag)
+    {
+      __has_sse = 0;
+      return 0;
+    }
+
+  __asm__ __volatile__ (
+    "cpuid"
+    : "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]),
+    "=d" (cpuInfo[3])
+    : "a" (infoType));
+  __has_sse = (cpuInfo[3] & 0x2000000);
+  return __has_sse;
+}
+#endif  /* __i386__ */
diff --git a/mingw-w64-crt/misc/feclearexcept.c 
b/mingw-w64-crt/misc/feclearexcept.c
index 673528b20..a5ab0f095 100644
--- a/mingw-w64-crt/misc/feclearexcept.c
+++ b/mingw-w64-crt/misc/feclearexcept.c
@@ -3,36 +3,9 @@
  * This file is part of the mingw-w64 runtime package.
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
-#include <fenv.h>
-
-#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__))
-int __mingw_has_sse (void);
 
-int __mingw_has_sse(void)
-{
-  int cpuInfo[4],infoType = 1;
-  
-#ifndef _WIN64
-  int o_flag, n_flag;
-  
-  __asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (o_flag));
-  n_flag = o_flag ^ 0x200000;
-  __asm__ volatile ("pushl %0\n\tpopfl" : : "g" (n_flag));
-  __asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (n_flag));
-  if (n_flag == o_flag)
-    return 0;
-#endif
-       
-  __asm__ __volatile__ (
-    "cpuid"
-    : "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]),
-    "=d" (cpuInfo[3])
-    : "a" (infoType));
-  if (cpuInfo[3] & 0x2000000)
-    return 1;
-  return 0;
-}
-#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)) */
+#include <fenv.h>
+#include <internal.h>
 
 /* 7.6.2.1
    The feclearexcept function clears the supported exceptions
diff --git a/mingw-w64-crt/misc/fegetenv.c b/mingw-w64-crt/misc/fegetenv.c
index 31960816e..e17fd491c 100644
--- a/mingw-w64-crt/misc/fegetenv.c
+++ b/mingw-w64-crt/misc/fegetenv.c
@@ -3,11 +3,9 @@
  * This file is part of the mingw-w64 runtime package.
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
-#include <fenv.h>
 
-#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__))
-int __mingw_has_sse (void);
-#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)) */
+#include <fenv.h>
+#include <internal.h>
 
 /* 7.6.4.1
    The fegetenv function stores the current floating-point environment
diff --git a/mingw-w64-crt/misc/fegetexceptflag.c 
b/mingw-w64-crt/misc/fegetexceptflag.c
index eaa940a2a..b50ca6fc1 100644
--- a/mingw-w64-crt/misc/fegetexceptflag.c
+++ b/mingw-w64-crt/misc/fegetexceptflag.c
@@ -3,13 +3,11 @@
  * This file is part of the mingw-w64 runtime package.
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
-#include <fenv.h>
 
-#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__))
-extern int __mingw_has_sse (void);
-#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)) */
+#include <fenv.h>
+#include <internal.h>
 
-/* 7.6.2.2  
+/* 7.6.2.2
    The fegetexceptflag function stores an implementation-defined
    representation of the exception flags indicated by the argument
    excepts in the object pointed to by the argument flagp.  */
@@ -32,7 +30,7 @@ int fegetexceptflag (fexcept_t * flagp, int excepts)
   _mxcsr = 0;
   if (__mingw_has_sse ())
     __asm__ volatile ("stmxcsr %0" : "=m" (_mxcsr));
-    
+
   *flagp = (_mxcsr | _status) & excepts & FE_ALL_EXCEPT;
 #endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__) */
   return 0;
diff --git a/mingw-w64-crt/misc/fesetenv.c b/mingw-w64-crt/misc/fesetenv.c
index a3279bddd..76325ce37 100644
--- a/mingw-w64-crt/misc/fesetenv.c
+++ b/mingw-w64-crt/misc/fesetenv.c
@@ -3,13 +3,11 @@
  * This file is part of the mingw-w64 runtime package.
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
+
 #include <_mingw.h>
 #include <fenv.h>
 #include <float.h>
-
-#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__))
-extern int __mingw_has_sse (void);
-#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)) */
+#include <internal.h>
 
 /* 7.6.4.3
    The fesetenv function establishes the floating-point environment
@@ -28,7 +26,7 @@ int fesetenv (const fenv_t * envp)
 {
 #if defined(_ARM_) || defined(__arm__)
   if (envp == FE_DFL_ENV)
-    /* Use the choice made at app startup */ 
+    /* Use the choice made at app startup */
     _fpreset();
   else
     __asm__ volatile ("fmxr FPSCR, %0" : : "r" (*envp));
@@ -59,7 +57,7 @@ int fesetenv (const fenv_t * envp)
    (* __MINGW_IMP_SYMBOL(_fpreset))();
 
   else if (envp == FE_DFL_ENV)
-    /* Use the choice made at app startup */ 
+    /* Use the choice made at app startup */
     _fpreset();
 
   else
diff --git a/mingw-w64-crt/misc/fesetexceptflag.c 
b/mingw-w64-crt/misc/fesetexceptflag.c
index 7e3361c6a..095dfea0b 100644
--- a/mingw-w64-crt/misc/fesetexceptflag.c
+++ b/mingw-w64-crt/misc/fesetexceptflag.c
@@ -3,11 +3,9 @@
  * This file is part of the mingw-w64 runtime package.
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
-#include <fenv.h>
 
-#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__))
-extern int __mingw_has_sse (void);
-#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)) */
+#include <fenv.h>
+#include <internal.h>
 
 /* 7.6.2.4
    The fesetexceptflag function sets the complete status for those
@@ -16,9 +14,9 @@ extern int __mingw_has_sse (void);
    *flagp shall have been set by a previous call to fegetexceptflag
    whose second argument represented at least those exceptions
    represented by the argument excepts. This function does not raise
-   exceptions, but only sets the state of the flags. */ 
+   exceptions, but only sets the state of the flags. */
 
-int fesetexceptflag (const fexcept_t * flagp, int excepts) 
+int fesetexceptflag (const fexcept_t * flagp, int excepts)
 {
   fenv_t _env;
 
diff --git a/mingw-w64-crt/misc/fesetround.c b/mingw-w64-crt/misc/fesetround.c
index 624a9997d..e51f46cd7 100644
--- a/mingw-w64-crt/misc/fesetround.c
+++ b/mingw-w64-crt/misc/fesetround.c
@@ -3,11 +3,9 @@
  * This file is part of the mingw-w64 runtime package.
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
-#include <fenv.h>
 
-#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__))
-int __mingw_has_sse (void);
-#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)) */
+#include <fenv.h>
+#include <internal.h>
 
  /* 7.6.3.2
     The fesetround function establishes the rounding direction
@@ -42,7 +40,7 @@ int fesetround (int mode)
   _cw &= ~0xc00;
   _cw |= mode;
   __asm__ volatile ("fldcw %0;" : : "m" (*&_cw));
-  
+
   if (__mingw_has_sse ())
     {
       int mxcsr;
diff --git a/mingw-w64-crt/misc/fetestexcept.c 
b/mingw-w64-crt/misc/fetestexcept.c
index da073e6d0..04e75970f 100644
--- a/mingw-w64-crt/misc/fetestexcept.c
+++ b/mingw-w64-crt/misc/fetestexcept.c
@@ -4,13 +4,10 @@
  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
 
-#include <fenv.h> 
+#include <fenv.h>
+#include <internal.h>
 
-#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__))
-extern int __mingw_has_sse (void);
-#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || 
defined(__aarch64__)) */
-
-/* 7.6.2.5 
+/* 7.6.2.5
    The fetestexcept function determines which of a specified subset of
    the exception flags are currently set. The excepts argument
    specifies the exception flags to be queried.
-- 
2.47.0

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to