[PATCH 1/2] c++, libstdc++: implement __is_signed built-in trait

2023-07-09 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_signed.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_signed.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_SIGNED.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_signed.
* g++.dg/ext/is_signed.C: New test.
* g++.dg/tm/pr46567.C (__is_signed): Rename to ...
(is_signed): ... this.

libstdc++-v3/ChangeLog:

* include/ext/numeric_traits.h (__is_signed): Rename to ...
(is_signed): ... this.
* include/bits/charconv.h: Use is_signed instead.
* include/bits/locale_facets.tcc: Likewise.
* include/bits/uniform_int_dist.h: Likewise.

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc |  3 ++
 gcc/cp/cp-trait.def  |  1 +
 gcc/cp/semantics.cc  |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_signed.C | 47 
 gcc/testsuite/g++.dg/tm/pr46567.C| 12 ++---
 libstdc++-v3/include/bits/charconv.h |  2 +-
 libstdc++-v3/include/bits/locale_facets.tcc  |  6 +--
 libstdc++-v3/include/bits/uniform_int_dist.h |  4 +-
 libstdc++-v3/include/ext/numeric_traits.h| 18 
 10 files changed, 79 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_signed.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..73fcbfe39e8 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_SIGNED:
+  inform (loc, "  %qT is not a signed type", t1);
+  break;
 case CPTK_IS_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..576d5528d05 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
"__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_SIGNED, "__is_signed", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
"__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..17aad992f96 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_SIGNED:
+  return ARITHMETIC_TYPE_P (type1) && TYPE_SIGN (type1) == SIGNED;
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
 case CPTK_IS_ENUM:
 case CPTK_IS_UNION:
 case CPTK_IS_SAME:
+case CPTK_IS_SIGNED:
   break;
 
 case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..a43202d0d59 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_signed)
+# error "__has_builtin (__is_signed) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_signed.C 
b/gcc/testsuite/g++.dg/ext/is_signed.C
new file mode 100644
index 000..a04b548105d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_signed.C
@@ -0,0 +1,47 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, X, expect) \
+  SA(TRAIT(X) == expect);  \
+  SA(TRAIT(const X) == expect);\
+  SA(TRAIT(volatile X) == expect); \
+  SA(TRAIT(const volatile X) == expect)
+
+SA_TEST_CATEGORY(__is_signed, void, false);
+
+SA_TEST_CATEGORY(__is_signed, bool, bool(-1) < bool(0));
+SA_TEST_CATEGORY(__is_signed, char, char(-1) < char(0));
+SA_TEST_CATEGORY(__is_signed, signed char, true);
+SA_TEST_CATEGORY(__is_signed, unsigned char, false);
+SA_TEST_CATEGORY(__is_signed, wchar_t, wchar_t(-1) < wchar_t(0));
+SA_TEST_CATEGORY(__is_signed, short, true);
+SA_TEST_CATEGORY(__is_signed, unsigned short, false);
+SA_TEST_CATEGORY(__is_signed, int, true);
+SA_TEST_CATEGORY(__is_signed, unsigned int, false);
+SA

[PATCH 2/2] libstdc++: use new built-in trait __is_signed

2023-07-09 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_signed.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_signed): Use __is_signed built-in trait.
(is_signed_v): Likewise.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..23ab5a4b1e5 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -865,6 +865,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public __bool_constant<__is_abstract(_Tp)>
 { };
 
+  /// is_signed
+#if __has_builtin(__is_signed)
+  template
+struct is_signed
+: public __bool_constant<__is_signed(_Tp)>
+{ };
+#else
   /// @cond undocumented
   template::value>
@@ -877,11 +884,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
   /// @endcond
 
-  /// is_signed
   template
 struct is_signed
 : public __is_signed_helper<_Tp>::type
 { };
+#endif
 
   /// is_unsigned
   template
@@ -3240,8 +3247,14 @@ template 
 template 
   inline constexpr bool is_final_v = __is_final(_Tp);
 
+#if __has_builtin(__is_signed)
+template 
+  inline constexpr bool is_signed_v = __is_signed(_Tp);
+#else
 template 
   inline constexpr bool is_signed_v = is_signed<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value;
 
-- 
2.41.0



[PATCH] simplify-rtx: Fix invalid simplification with paradoxical subregs [PR110206]

2023-07-09 Thread Uros Bizjak via Gcc-patches
As shown in the PR, simplify_gen_subreg call in simplify_replace_fn_rtx:

(gdb) list
469   if (code == SUBREG)
470 {
471   op0 = simplify_replace_fn_rtx (SUBREG_REG (x),
old_rtx, fn, data);
472   if (op0 == SUBREG_REG (x))
473 return x;
474   op0 = simplify_gen_subreg (GET_MODE (x), op0,
475  GET_MODE (SUBREG_REG (x)),
476  SUBREG_BYTE (x));
477   return op0 ? op0 : x;
478 }

simplifies with following arguments:

(gdb) p debug_rtx (op0)
(const_vector:V4QI [
(const_int -52 [0xffcc]) repeated x4
])
(gdb) p debug_rtx (x)
(subreg:V16QI (reg:V4QI 98) 0)

to:

(gdb) p debug_rtx (op0)
(const_vector:V16QI [
(const_int -52 [0xffcc]) repeated x16
])

This simplification is invalid, it is not possible to get V16QImode vector
from V4QImode vector, even when all elements are duplicates.

The simplification happens in simplify_context::simplify_subreg:

(gdb) list
7558  if (VECTOR_MODE_P (outermode)
7559  && GET_MODE_INNER (outermode) == GET_MODE_INNER (innermode)
7560  && vec_duplicate_p (op, &elt))
7561return gen_vec_duplicate (outermode, elt);

but the above simplification is valid only for non-paradoxical registers,
where outermode <= innermode.  We should not assume that elements outside
the original register are valid, let alone all duplicates.

PR target/110206

gcc/ChangeLog:

* simplify-rtx.cc (simplify_context::simplify_subreg):
Avoid returning a vector with duplicated value
outside the original register.

gcc/testsuite/ChangeLog:

* gcc.dg/torture/pr110206.c: New test.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

OK for master and release branches?

Uros.
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index d7315d82aa3..87ca25086dc 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -7557,6 +7557,7 @@ simplify_context::simplify_subreg (machine_mode 
outermode, rtx op,
 
   if (VECTOR_MODE_P (outermode)
  && GET_MODE_INNER (outermode) == GET_MODE_INNER (innermode)
+ && !paradoxical_subreg_p (outermode, innermode)
  && vec_duplicate_p (op, &elt))
return gen_vec_duplicate (outermode, elt);
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr110206.c 
b/gcc/testsuite/gcc.dg/torture/pr110206.c
new file mode 100644
index 000..3a4f221ef47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr110206.c
@@ -0,0 +1,30 @@
+/* PR target/110206 */
+/* { dg-do run { target x86_64-*-* i?86-*-* } } */
+
+typedef unsigned char __attribute__((__vector_size__ (4))) U;
+typedef unsigned char __attribute__((__vector_size__ (8))) V;
+typedef unsigned short u16;
+
+V g;
+
+void
+__attribute__((noinline))
+foo (U u, u16 c, V *r)
+{
+  if (!c)
+__builtin_abort ();
+  V x = __builtin_shufflevector (u, (204 >> u), 7, 0, 5, 1, 3, 5, 0, 2);
+  V y = __builtin_shufflevector (g, (V) { }, 7, 6, 6, 7, 2, 6, 3, 5);
+  V z = __builtin_shufflevector (y, 204 * x, 3, 9, 8, 1, 4, 6, 14, 5);
+  *r = z;
+}
+
+int
+main (void)
+{
+  V r;
+  foo ((U){4}, 5, &r);
+  if (r[6] != 0x30)
+__builtin_abort();
+  return 0;
+}


Re: [PATCH 1/2] c++, libstdc++: implement __is_signed built-in trait

2023-07-09 Thread Ken Matsui via Gcc-patches
Hi,

Here is the benchmark result for is_signed:

https://github.com/ken-matsui/gcc-benches/blob/main/is_signed.md#sun-jul--9-014707-am-pdt-2023

Time: -59.439%
Peak Memory Usage: -38.5157%
Total Memory Usage: -41.687%

Sincerely,
Ken Matsui

On Sun, Jul 9, 2023 at 1:47 AM Ken Matsui  wrote:
>
> This patch implements built-in trait for std::is_signed.
>
> gcc/cp/ChangeLog:
>
> * cp-trait.def: Define __is_signed.
> * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_SIGNED.
> * semantics.cc (trait_expr_value): Likewise.
> (finish_trait_expr): Likewise.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/ext/has-builtin-1.C: Test existence of __is_signed.
> * g++.dg/ext/is_signed.C: New test.
> * g++.dg/tm/pr46567.C (__is_signed): Rename to ...
> (is_signed): ... this.
>
> libstdc++-v3/ChangeLog:
>
> * include/ext/numeric_traits.h (__is_signed): Rename to ...
> (is_signed): ... this.
> * include/bits/charconv.h: Use is_signed instead.
> * include/bits/locale_facets.tcc: Likewise.
> * include/bits/uniform_int_dist.h: Likewise.
>
> Signed-off-by: Ken Matsui 
> ---
>  gcc/cp/constraint.cc |  3 ++
>  gcc/cp/cp-trait.def  |  1 +
>  gcc/cp/semantics.cc  |  4 ++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
>  gcc/testsuite/g++.dg/ext/is_signed.C | 47 
>  gcc/testsuite/g++.dg/tm/pr46567.C| 12 ++---
>  libstdc++-v3/include/bits/charconv.h |  2 +-
>  libstdc++-v3/include/bits/locale_facets.tcc  |  6 +--
>  libstdc++-v3/include/bits/uniform_int_dist.h |  4 +-
>  libstdc++-v3/include/ext/numeric_traits.h| 18 
>  10 files changed, 79 insertions(+), 21 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_signed.C
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 8cf0f2d0974..73fcbfe39e8 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
>  case CPTK_IS_UNION:
>inform (loc, "  %qT is not a union", t1);
>break;
> +case CPTK_IS_SIGNED:
> +  inform (loc, "  %qT is not a signed type", t1);
> +  break;
>  case CPTK_IS_AGGREGATE:
>inform (loc, "  %qT is not an aggregate", t1);
>break;
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 8b7fece0cc8..576d5528d05 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -82,6 +82,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
> "__is_trivially_assignable", 2)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", 
> -1)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
>  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
> +DEFTRAIT_EXPR (IS_SIGNED, "__is_signed", 1)
>  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
> "__reference_constructs_from_temporary", 2)
>  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
> "__reference_converts_from_temporary", 2)
>  /* FIXME Added space to avoid direct usage in GCC 13.  */
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 8fb47fd179e..17aad992f96 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, 
> tree type2)
>  case CPTK_IS_UNION:
>return type_code1 == UNION_TYPE;
>
> +case CPTK_IS_SIGNED:
> +  return ARITHMETIC_TYPE_P (type1) && TYPE_SIGN (type1) == SIGNED;
> +
>  case CPTK_IS_ASSIGNABLE:
>return is_xible (MODIFY_EXPR, type1, type2);
>
> @@ -12296,6 +12299,7 @@ finish_trait_expr (location_t loc, cp_trait_kind 
> kind, tree type1, tree type2)
>  case CPTK_IS_ENUM:
>  case CPTK_IS_UNION:
>  case CPTK_IS_SAME:
> +case CPTK_IS_SIGNED:
>break;
>
>  case CPTK_IS_LAYOUT_COMPATIBLE:
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
> b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index f343e153e56..a43202d0d59 100644
> --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> @@ -146,3 +146,6 @@
>  #if !__has_builtin (__remove_cvref)
>  # error "__has_builtin (__remove_cvref) failed"
>  #endif
> +#if !__has_builtin (__is_signed)
> +# error "__has_builtin (__is_signed) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_signed.C 
> b/gcc/testsuite/g++.dg/ext/is_signed.C
> new file mode 100644
> index 000..a04b548105d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_signed.C
> @@ -0,0 +1,47 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include 
> +
> +using namespace __gnu_test;
> +
> +#define SA(X) static_assert((X),#X)
> +#define SA_TEST_CATEGORY(TRAIT, X, expect) \
> +  SA(TRAIT(X) == expect);  \
> +  SA(TRAIT(const X) == expect);\
> +  SA(TRAIT(volatile X) == expect); \
> +  SA(TRAIT(const volatile X) == expect)
> +
> 

[PATCH 1/2] c++, libstdc++: implement __is_arithmetic built-in trait

2023-07-09 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_arithmetic.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_arithmetic.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_ARITHMETIC.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_arithmetic.
* g++.dg/ext/is_arithmetic.C: New test.
* g++.dg/tm/pr46567.C (__is_arithmetic): Rename to ...
(is_arithmetic): ... this.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_arithmetic): Rename to ...
(is_arithmetic): ... this.
* include/c_global/cmath: Use is_arithmetic instead.
* include/c_std/cmath: Likewise.
* include/tr1/cmath: Likewise.

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc|  3 ++
 gcc/cp/cp-trait.def |  1 +
 gcc/cp/semantics.cc |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 ++
 gcc/testsuite/g++.dg/ext/is_arithmetic.C| 33 ++
 gcc/testsuite/g++.dg/tm/pr46567.C   |  6 +--
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  4 +-
 libstdc++-v3/include/c_global/cmath | 48 ++---
 libstdc++-v3/include/c_std/cmath| 24 +--
 libstdc++-v3/include/tr1/cmath  | 24 +--
 11 files changed, 99 insertions(+), 55 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_arithmetic.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..bd517d08843 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
+case CPTK_IS_ARITHMETIC:
+  inform (loc, "  %qT is not an arithmetic type", t1);
+  break;
 case CPTK_IS_TRIVIALLY_COPYABLE:
   inform (loc, "  %qT is not trivially copyable", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..a95aeeaf778 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
"__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_ARITHMETIC, "__is_arithmetic", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
"__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..4531f047d73 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_ARITHMETIC:
+  return ARITHMETIC_TYPE_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
 case CPTK_IS_ENUM:
 case CPTK_IS_UNION:
 case CPTK_IS_SAME:
+case CPTK_IS_ARITHMETIC:
   break;
 
 case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..3d63b0101d1 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_arithmetic)
+# error "__has_builtin (__is_arithmetic) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_arithmetic.C 
b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
new file mode 100644
index 000..fd35831f646
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)  \
+  SA(TRAIT(TYPE) == EXPECT);   \
+  SA(TRAIT(const TYPE) == EXPECT); \
+  SA(TRAIT(volatile TYPE) == EXPECT);  \
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_arithmetic, void, false);
+
+SA_TEST_CATEGORY(__is_arithmetic, char, true);
+SA_TEST_CATEGORY(__is_arithmetic, signed char, true);
+SA_TEST_CATEGORY(__is_arithmetic, unsigned char, true);
+SA_TEST_CATEGORY(__is_arithmetic, wchar_t, true);
+SA_TEST_CATEGORY(__is_arithmetic, short, tr

[PATCH 2/2] libstdc++: use new built-in trait __is_arithmetic

2023-07-09 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_arithmetic.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_arithmetic): Use __is_arithmetic
built-in trait.
(is_arithmetic_v): Likewise.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..7ebbe04c77b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -655,10 +655,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_arithmetic
+#if __has_builtin(__is_arithmetic)
+  template
+struct is_arithmetic
+: public __bool_constant<__is_arithmetic(_Tp)>
+{ };
+#else
   template
 struct is_arithmetic
 : public __or_, is_floating_point<_Tp>>::type
 { };
+#endif
 
   /// is_fundamental
   template
@@ -3198,8 +3205,15 @@ template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+
+#if __has_builtin(__is_arithmetic)
+template 
+  inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+#else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
 template 
-- 
2.41.0



Re: [PATCH 1/2] c++, libstdc++: implement __is_arithmetic built-in trait

2023-07-09 Thread Ken Matsui via Gcc-patches
Hi,

Here is the benchmark result for is_arithmetic:

https://github.com/ken-matsui/gcc-benches/blob/main/is_arithmetic.md#sun-jul--9-055758-am-pdt-2023

Time: -55.2631%
Peak Memory Usage: -38.7701%
Total Memory Usage: -40.5237%

Sincerely,
Ken Matsui

On Sun, Jul 9, 2023 at 5:57 AM Ken Matsui  wrote:
>
> This patch implements built-in trait for std::is_arithmetic.
>
> gcc/cp/ChangeLog:
>
> * cp-trait.def: Define __is_arithmetic.
> * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_ARITHMETIC.
> * semantics.cc (trait_expr_value): Likewise.
> (finish_trait_expr): Likewise.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/ext/has-builtin-1.C: Test existence of __is_arithmetic.
> * g++.dg/ext/is_arithmetic.C: New test.
> * g++.dg/tm/pr46567.C (__is_arithmetic): Rename to ...
> (is_arithmetic): ... this.
> * g++.dg/torture/pr57107.C: Likewise.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/cpp_type_traits.h (__is_arithmetic): Rename to ...
> (is_arithmetic): ... this.
> * include/c_global/cmath: Use is_arithmetic instead.
> * include/c_std/cmath: Likewise.
> * include/tr1/cmath: Likewise.
>
> Signed-off-by: Ken Matsui 
> ---
>  gcc/cp/constraint.cc|  3 ++
>  gcc/cp/cp-trait.def |  1 +
>  gcc/cp/semantics.cc |  4 ++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 ++
>  gcc/testsuite/g++.dg/ext/is_arithmetic.C| 33 ++
>  gcc/testsuite/g++.dg/tm/pr46567.C   |  6 +--
>  gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
>  libstdc++-v3/include/bits/cpp_type_traits.h |  4 +-
>  libstdc++-v3/include/c_global/cmath | 48 ++---
>  libstdc++-v3/include/c_std/cmath| 24 +--
>  libstdc++-v3/include/tr1/cmath  | 24 +--
>  11 files changed, 99 insertions(+), 55 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_arithmetic.C
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 8cf0f2d0974..bd517d08843 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
>  case CPTK_IS_AGGREGATE:
>inform (loc, "  %qT is not an aggregate", t1);
>break;
> +case CPTK_IS_ARITHMETIC:
> +  inform (loc, "  %qT is not an arithmetic type", t1);
> +  break;
>  case CPTK_IS_TRIVIALLY_COPYABLE:
>inform (loc, "  %qT is not trivially copyable", t1);
>break;
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 8b7fece0cc8..a95aeeaf778 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -82,6 +82,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
> "__is_trivially_assignable", 2)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", 
> -1)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
>  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
> +DEFTRAIT_EXPR (IS_ARITHMETIC, "__is_arithmetic", 1)
>  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
> "__reference_constructs_from_temporary", 2)
>  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
> "__reference_converts_from_temporary", 2)
>  /* FIXME Added space to avoid direct usage in GCC 13.  */
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 8fb47fd179e..4531f047d73 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, 
> tree type2)
>  case CPTK_IS_UNION:
>return type_code1 == UNION_TYPE;
>
> +case CPTK_IS_ARITHMETIC:
> +  return ARITHMETIC_TYPE_P (type1);
> +
>  case CPTK_IS_ASSIGNABLE:
>return is_xible (MODIFY_EXPR, type1, type2);
>
> @@ -12296,6 +12299,7 @@ finish_trait_expr (location_t loc, cp_trait_kind 
> kind, tree type1, tree type2)
>  case CPTK_IS_ENUM:
>  case CPTK_IS_UNION:
>  case CPTK_IS_SAME:
> +case CPTK_IS_ARITHMETIC:
>break;
>
>  case CPTK_IS_LAYOUT_COMPATIBLE:
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
> b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index f343e153e56..3d63b0101d1 100644
> --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> @@ -146,3 +146,6 @@
>  #if !__has_builtin (__remove_cvref)
>  # error "__has_builtin (__remove_cvref) failed"
>  #endif
> +#if !__has_builtin (__is_arithmetic)
> +# error "__has_builtin (__is_arithmetic) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_arithmetic.C 
> b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
> new file mode 100644
> index 000..fd35831f646
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
> @@ -0,0 +1,33 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include 
> +
> +using namespace __gnu_test;
> +
> +#define SA(X) static_assert((X),#X)
> +#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)  \
> +  S

Improve dumping of profile_count

2023-07-09 Thread Jan Hubicka via Gcc-patches
Hi,
dumps of profile_counts are quite hard to interpret since they are 64bit fixed 
point
values.  In many cases one looks at a single function and it is better to think 
of
basic block frequency, that is how many times it is executed each invocatoin. 
This
patch makes CFG dumps to also print this info.

For example:
main()
{
for (int i = 0; i < 10; i++)
t();
}

the -fdump-tree-optimized-blocks-details now prints:
int main ()
{
  unsigned int ivtmp_1;
  unsigned int ivtmp_2;

;;   basic block 2, loop depth 0, count 97603128 (estimated locally, freq 
1.), maybe hot
;;prev block 0, next block 3, flags: (NEW, VISITED)
;;pred:   ENTRY [always]  count:97603128 (estimated locally, freq 
1.) (FALLTHRU,EXECUTABLE)
;;succ:   3 [always]  count:97603128 (estimated locally, freq 1.) 
(FALLTHRU,EXECUTABLE)

;;   basic block 3, loop depth 1, count 976138697 (estimated locally, freq 
10.0011), maybe hot
;;prev block 2, next block 4, flags: (NEW, VISITED)
;;pred:   3 [90.0% (guessed)]  count:878535568 (estimated locally, freq 
9.0011) (TRUE_VALUE,EXECUTABLE)
;;2 [always]  count:97603128 (estimated locally, freq 1.) 
(FALLTHRU,EXECUTABLE)
  # ivtmp_2 = PHI 
  t ();
  ivtmp_1 = ivtmp_2 + 4294967295;
  if (ivtmp_1 != 0)
goto ; [90.00%]
  else
goto ; [10.00%]
;;succ:   3 [90.0% (guessed)]  count:878535568 (estimated locally, freq 
9.0011) (TRUE_VALUE,EXECUTABLE)
;;4 [10.0% (guessed)]  count:97603129 (estimated locally, freq 
1.) (FALSE_VALUE,EXECUTABLE)

;;   basic block 4, loop depth 0, count 97603128 (estimated locally, freq 
1.), maybe hot
;;prev block 3, next block 1, flags: (NEW, VISITED)
;;pred:   3 [10.0% (guessed)]  count:97603129 (estimated locally, freq 
1.) (FALSE_VALUE,EXECUTABLE)
  return 0;
;;succ:   EXIT [always]  count:97603128 (estimated locally, freq 
1.) (EXECUTABLE)

}

Which makes it easier to see that the inner bb is executed 10 times per 
invocation


gcc/ChangeLog:

* cfg.cc (check_bb_profile): Dump counts with relative frequency.
(dump_edge_info): Likewise.
(dump_bb_info): Likewise.
* profile-count.cc (profile_count::dump): Add comma between quality and
freq.

gcc/testsuite/ChangeLog:

* gcc.dg/predict-22.c: Update template.

diff --git a/gcc/cfg.cc b/gcc/cfg.cc
index 740d4f3581d..0de6d6b9e71 100644
--- a/gcc/cfg.cc
+++ b/gcc/cfg.cc
@@ -475,9 +475,9 @@ check_bb_profile (basic_block bb, FILE * file, int indent)
{
  fprintf (file, ";; %sInvalid sum of incoming counts ",
   s_indent);
- sum.dump (file);
+ sum.dump (file, fun);
  fprintf (file, ", should be ");
- bb->count.dump (file);
+ bb->count.dump (file, fun);
  fprintf (file, "\n");
}
 }
@@ -525,7 +525,7 @@ dump_edge_info (FILE *file, edge e, dump_flags_t flags, int 
do_succ)
   if (e->count ().initialized_p () && do_details)
 {
   fputs (" count:", file);
-  e->count ().dump (file);
+  e->count ().dump (file, cfun);
 }
 
   if (e->flags && do_details)
@@ -808,7 +808,7 @@ dump_bb_info (FILE *outf, basic_block bb, int indent, 
dump_flags_t flags,
  if (bb->count.initialized_p ())
{
  fputs (", count ", outf);
- bb->count.dump (outf);
+ bb->count.dump (outf, cfun);
}
  if (maybe_hot_bb_p (fun, bb))
fputs (", maybe hot", outf);
diff --git a/gcc/profile-count.cc b/gcc/profile-count.cc
index 6bf9700d8db..2c07ebc5942 100644
--- a/gcc/profile-count.cc
+++ b/gcc/profile-count.cc
@@ -94,7 +94,7 @@ profile_count::dump (char *buffer, struct function *fun) const
   else if (fun && initialized_p ()
   && fun->cfg
   && ENTRY_BLOCK_PTR_FOR_FN (fun)->count.initialized_p ())
-sprintf (buffer, "%" PRId64 " (%s freq %.4f)", m_val,
+sprintf (buffer, "%" PRId64 " (%s, freq %.4f)", m_val,
 profile_quality_display_names[m_quality],
 to_sreal_scale (ENTRY_BLOCK_PTR_FOR_FN (fun)->count).to_double ());
   else
diff --git a/gcc/testsuite/gcc.dg/predict-22.c 
b/gcc/testsuite/gcc.dg/predict-22.c
index f14c2b68861..1aed03fae79 100644
--- a/gcc/testsuite/gcc.dg/predict-22.c
+++ b/gcc/testsuite/gcc.dg/predict-22.c
@@ -55,5 +55,5 @@ foo (int x, int y, int z)
   baz (&f);
 }
 /* { dg-final { scan-tree-dump-times "Invalid sum" 0 "optimized"} } */
-/* { dg-final { scan-tree-dump-times "count 0 .precise.," 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "count 0 .precise" 1 "optimized"} } */
 /* { dg-final { scan-rtl-dump-times "COLD_PARTITION" 1 "bbpart"} } */


[PATCH] ci: Add a linux CI

2023-07-09 Thread Tal Regev via Gcc-patches
Description: adding a ci in a github repo. Everytime a user will do a PR to
master branch or releases branches, it will activate the ci on their repo.
for example: https://github.com/talregev/gcc/pull/1. Can help users to
verify their own changes before submitting a patch.

ChangeLog: Add a linux CI

Bootstrapping and testing: I tested it on linux with
host: x86_64-linux-gnu
target: x86_64-linux-gnu
some tests are failing. You can see the results in my CI yourself.

Patch: attach to this email.


linux_ci.patch
Description: Binary data


[x86 PATCH] Add AVX512 support for STV of SI/DImode rotation by constant.

2023-07-09 Thread Roger Sayle

Following Uros' suggestion, this patch adds support for AVX512VL's
vpro[lr][dq] instructions to the recently added scalar-to-vector (STV)
enhancements to handle DImode and SImode rotations by a constant.

For the test cases:

unsigned long long rot1(unsigned long long x) {
  return (x>>1) | (x<<63);
}

void mem1(unsigned long long *p) {
  *p = rot1(*p);
}

with -m32 -O2 -mavx512vl, we currently generate:

rot1:   movl4(%esp), %eax
movl8(%esp), %edx
movl%eax, %ecx
shrdl   $1, %edx, %eax
shrdl   $1, %ecx, %edx
ret

mem1:   movl4(%esp), %eax
vmovq   (%eax), %xmm0
vpshufd $20, %xmm0, %xmm0
vpsrlq  $1, %xmm0, %xmm0
vpshufd $136, %xmm0, %xmm0
vmovq   %xmm0, (%eax)
ret

with this patch, we now generate:

rot1:   vmovq   4(%esp), %xmm0
vprorq  $1, %xmm0, %xmm0
vmovd   %xmm0, %eax
vpextrd $1, %xmm0, %edx
ret

mem1:   movl4(%esp), %eax
vmovq   (%eax), %xmm0
vprorq  $1, %xmm0, %xmm0
vmovq   %xmm0, (%eax)
ret


This patch has been tested on x86_64-pc-linux-gnu (cascadelake which has
avx512) with make bootstrap and make -k check, both with and without
--target_board=unix{-m32} with no new failures.  Ok for mainline?


2023-07-09  Roger Sayle  

gcc/ChangeLog
* config/i386/i386-features.cc (compute_convert_gain): Tweak
gains/costs for ROTATE/ROTATERT by integer constant on AVX512VL.
(general_scalar_chain::convert_rotate): On TARGET_AVX512F generate
avx512vl_rolv2di or avx412vl_rolv4si when appropriate.

gcc/testsuite/ChangeLog
* gcc.target/i386/avx512vl-stv-rotatedi-1.c: New test case.


Cheers,
Roger
--

diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index 2e751d1..4d69251 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -585,7 +585,9 @@ general_scalar_chain::compute_convert_gain ()
  case ROTATE:
  case ROTATERT:
igain += m * ix86_cost->shift_const;
-   if (smode == DImode)
+   if (TARGET_AVX512F)
+ igain -= ix86_cost->sse_op;
+   else if (smode == DImode)
  {
int bits = INTVAL (XEXP (src, 1));
if ((bits & 0x0f) == 0)
@@ -1225,6 +1227,8 @@ general_scalar_chain::convert_rotate (enum rtx_code code, 
rtx op0, rtx op1,
  emit_insn_before (pat, insn);
  result = gen_lowpart (V2DImode, tmp1);
}
+  else if (TARGET_AVX512F)
+   result = simplify_gen_binary (code, V2DImode, op0, op1);
   else if (bits == 16 || bits == 48)
{
  rtx tmp1 = gen_reg_rtx (V8HImode);
@@ -1269,6 +1273,8 @@ general_scalar_chain::convert_rotate (enum rtx_code code, 
rtx op0, rtx op1,
   emit_insn_before (pat, insn);
   result = gen_lowpart (V4SImode, tmp1);
 }
+  else if (TARGET_AVX512F)
+result = simplify_gen_binary (code, V4SImode, op0, op1);
   else
 {
   if (code == ROTATE)
diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-stv-rotatedi-1.c 
b/gcc/testsuite/gcc.target/i386/avx512vl-stv-rotatedi-1.c
new file mode 100644
index 000..2f0ead8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vl-stv-rotatedi-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mavx512vl" } */
+
+unsigned long long rot1(unsigned long long x) { return (x>>1) | (x<<63); }
+unsigned long long rot2(unsigned long long x) { return (x>>2) | (x<<62); }
+unsigned long long rot3(unsigned long long x) { return (x>>3) | (x<<61); }
+unsigned long long rot4(unsigned long long x) { return (x>>4) | (x<<60); }
+unsigned long long rot5(unsigned long long x) { return (x>>5) | (x<<59); }
+unsigned long long rot6(unsigned long long x) { return (x>>6) | (x<<58); }
+unsigned long long rot7(unsigned long long x) { return (x>>7) | (x<<57); }
+unsigned long long rot8(unsigned long long x) { return (x>>8) | (x<<56); }
+unsigned long long rot9(unsigned long long x) { return (x>>9) | (x<<55); }
+unsigned long long rot10(unsigned long long x) { return (x>>10) | (x<<54); }
+unsigned long long rot15(unsigned long long x) { return (x>>15) | (x<<49); }
+unsigned long long rot16(unsigned long long x) { return (x>>16) | (x<<48); }
+unsigned long long rot17(unsigned long long x) { return (x>>17) | (x<<47); }
+unsigned long long rot20(unsigned long long x) { return (x>>20) | (x<<44); }
+unsigned long long rot24(unsigned long long x) { return (x>>24) | (x<<40); }
+unsigned long long rot30(unsigned long long x) { return (x>>30) | (x<<34); }
+unsigned long long rot31(unsigned long long x) { return (x>>31) | (x<<33); }
+unsigned long long rot32(unsigned long long x) { return (x>>32) | (x<<32); }
+unsigned long long rot33(unsigned long long x) { return (x>>33) | (x<<31); }
+unsigned long long rot34(unsigned long long x) { return (x>>34) | (x<<30); }
+unsigned long long rot40(unsigned long long x) { return (x>>40

[X86 PATCH] Add new insvti_lowpart_1 and insvdi_lowpart_1 patterns.

2023-07-09 Thread Roger Sayle

This patch implements another of Uros' suggestions, to investigate a
insvti_lowpart_1 pattern to improve TImode parameter passing on x86_64.
In PR 88873, the RTL the middle-end expands for passing V2DF in TImode
is subtly different from what it does for V2DI in TImode, sufficiently so
that my explanations for why insvti_lowpart_1 isn't required don't apply
in this case.

This patch adds an insvti_lowpart_1 pattern, complementing the existing
insvti_highpart_1 pattern, and also a 32-bit variant, insvdi_lowpart_1.
Because the middle-end represents 128-bit constants using CONST_WIDE_INT
and 64-bit constants using CONST_INT, it's easiest to treat these as
different patterns, rather than attempt  parameterization.

This patch also includes a peephole2 (actually a pair) to transform
xchg instructions into mov instructions, when one of the destinations
is unused.  This optimization is required to produce the optimal code
sequences below.

For the 64-bit case:

__int128 foo(__int128 x, unsigned long long y)
{
  __int128 m = ~((__int128)~0ull);
  __int128 t = x & m;
  __int128 r = t | y;
  return r;
}

Before:
xchgq   %rdi, %rsi
movq%rdx, %rax
xorl%esi, %esi
xorl%edx, %edx
orq %rsi, %rax
orq %rdi, %rdx
ret

After:
movq%rdx, %rax
movq%rsi, %rdx
ret

For the 32-bit case:

long long bar(long long x, int y)
{
  long long mask = ~0ull << 32;
  long long t = x & mask;
  long long r = t | (unsigned int)y;
  return r;
}

Before:
pushl   %ebx
movl12(%esp), %edx
xorl%ebx, %ebx
xorl%eax, %eax
movl16(%esp), %ecx
orl %ebx, %edx
popl%ebx
orl %ecx, %eax
ret

After:
movl12(%esp), %eax
movl8(%esp), %edx
ret

This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check, both with and without --target_board=unix{-m32}
with no new failures.  Ok for mainline?


2023-07-09  Roger Sayle  

gcc/ChangeLog
* config/i386/i386.md (peephole2): Transform xchg insn with a
REG_UNUSED note to a (simple) move.
(*insvti_lowpart_1): New define_insn_and_split.
(*insvdi_lowpart_1): Likewise.

gcc/testsuite/ChangeLog
* gcc.target/i386/insvdi_lowpart-1.c: New test case.
* gcc.target/i386/insvti_lowpart-1.c: Likewise.


Cheers,
Roger
--

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index e47ced1..ea04d0a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -3243,6 +3243,30 @@
   [(parallel [(set (match_dup 1) (match_dup 2))
  (set (match_dup 2) (match_dup 1))])])
 
+;; Convert xchg with a REG_UNUSED note to a mov (variant #1).
+(define_peephole2
+  [(parallel [(set (match_operand:SWI 0 "general_reg_operand")
+  (match_operand:SWI 1 "general_reg_operand"))
+ (set (match_dup 1) (match_dup 0))])]
+  "((REGNO (operands[0]) != AX_REG
+ && REGNO (operands[1]) != AX_REG)
+|| optimize_size < 2
+|| !optimize_insn_for_size_p ())
+   && peep2_reg_dead_p (1, operands[0])"
+  [(set (match_dup 1) (match_dup 0))])
+
+;; Convert xchg with a REG_UNUSED note to a mov (variant #2).
+(define_peephole2
+  [(parallel [(set (match_operand:SWI 0 "general_reg_operand")
+  (match_operand:SWI 1 "general_reg_operand"))
+ (set (match_dup 1) (match_dup 0))])]
+  "((REGNO (operands[0]) != AX_REG
+ && REGNO (operands[1]) != AX_REG)
+|| optimize_size < 2
+|| !optimize_insn_for_size_p ())
+   && peep2_reg_dead_p (1, operands[1])"
+  [(set (match_dup 0) (match_dup 1))])
+
 ;; Convert moves to/from AX_REG into xchg with -Oz.
 (define_peephole2
   [(set (match_operand:SWI48 0 "general_reg_operand")
@@ -3573,6 +3597,48 @@
   split_double_concat (TImode, operands[0], operands[4], operands[2]);
   DONE;
 })
+
+(define_insn_and_split "*insvti_lowpart_1"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=ro,r,r,&r")
+   (any_or_plus:TI
+ (and:TI
+   (match_operand:TI 1 "nonimmediate_operand" "r,m,r,m")
+   (match_operand:TI 3 "const_scalar_int_operand" "n,n,n,n"))
+ (zero_extend:TI
+   (match_operand:DI 2 "nonimmediate_operand" "r,r,m,m"]
+  "TARGET_64BIT
+   && CONST_WIDE_INT_P (operands[3])
+   && CONST_WIDE_INT_NUNITS (operands[3]) == 2
+   && CONST_WIDE_INT_ELT (operands[3], 0) == 0
+   && CONST_WIDE_INT_ELT (operands[3], 1) == -1"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  operands[4] = gen_highpart (DImode, operands[1]);
+  split_double_concat (TImode, operands[0], operands[2], operands[4]);
+  DONE;
+})
+
+(define_insn_and_split "*insvdi_lowpart_1"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,r,r,&r")
+   (any_or_plus:DI
+ (and:DI
+   (match_operand:DI 1 "nonimmediate_operand" "r,m,r,m")
+   (match_operand:DI 3 "const_int_operand" "n,n,n,n"))
+

Re: [PATCH v2] Implement new RTL optimizations pass: fold-mem-offsets.

2023-07-09 Thread Hans-Peter Nilsson
On Thu, 15 Jun 2023, Manolis Tsamis wrote:

> This is a new RTL pass that tries to optimize memory offset calculations
> by moving them from add immediate instructions to the memory loads/stores.
> For example it can transform this:
> 
>   addi t4,sp,16
>   add  t2,a6,t4
>   shl  t3,t2,1
>   ld   a2,0(t3)
>   addi a2,1
>   sd   a2,8(t2)
> 
> into the following (one instruction less):
> 
>   add  t2,a6,sp
>   shl  t3,t2,1
>   ld   a2,32(t3)
>   addi a2,1
>   sd   a2,24(t2)
> 
> Although there are places where this is done already, this pass is more
> powerful and can handle the more difficult cases that are currently not
> optimized. Also, it runs late enough and can optimize away unnecessary
> stack pointer calculations.

It punts on all "use" insns that are not SET.
Why not use single_set there too?

brgds, H-P


Re: [PATCH v2] Implement new RTL optimizations pass: fold-mem-offsets.

2023-07-09 Thread Hans-Peter Nilsson
On Sun, 9 Jul 2023, Hans-Peter Nilsson wrote:

> On Thu, 15 Jun 2023, Manolis Tsamis wrote:
> 
> > This is a new RTL pass that tries to optimize memory offset calculations
> > by moving them from add immediate instructions to the memory loads/stores.

> It punts on all "use" insns that are not SET.
> Why not use single_set there too?

Also, I don't see insn costs considered?
(Also: typo "immidiate".)

brgds, H-P


[PATCH] Break false dependence for vpternlog by inserting vpxor or setting constraint of input operand to '0'

2023-07-09 Thread liuhongt via Gcc-patches
False dependency happens when destination is only updated by
pternlog. There is no false dependency when destination is also used
in source. So either a pxor should be inserted, or input operand
should be set with constraint '0'.

Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
Ready to push to trunk.

gcc/ChangeLog:

PR target/110438
PR target/110202
* config/i386/predicates.md
(int_float_vector_all_ones_operand): New predicate.
* config/i386/sse.md (*vmov_constm1_pternlog_false_dep): New
define_insn.
(*_cvtmask2_pternlog_false_dep):
Ditto.
(*_cvtmask2_pternlog_false_dep):
Ditto.
(*_cvtmask2): Adjust to
define_insn_and_split to avoid false dependence.
(*_cvtmask2): Ditto.
(one_cmpl2): Adjust constraint
of operands 1 to '0' to avoid false dependence.
(*andnot3): Ditto.
(iornot3): Ditto.
(*3): Ditto.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr110438.c: New test.
---
 gcc/config/i386/predicates.md|   8 +-
 gcc/config/i386/sse.md   | 113 ---
 gcc/testsuite/gcc.target/i386/pr110438.c |  30 ++
 3 files changed, 135 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr110438.c

diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 7ddbe01a6f9..37d20c6303a 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1192,12 +1192,18 @@ (define_predicate "float_vector_all_ones_operand"
 return false;
 })
 
-/* Return true if operand is a vector constant that is all ones. */
+/* Return true if operand is an integral vector constant that is all ones. */
 (define_predicate "vector_all_ones_operand"
   (and (match_code "const_vector")
(match_test "INTEGRAL_MODE_P (GET_MODE (op))")
(match_test "op == CONSTM1_RTX (GET_MODE (op))")))
 
+/* Return true if operand is a vector constant that is all ones. */
+(define_predicate "int_float_vector_all_ones_operand"
+  (ior (match_operand 0 "vector_all_ones_operand")
+   (match_operand 0 "float_vector_all_ones_operand")
+   (match_test "op == constm1_rtx")))
+
 /* Return true if operand is an 128/256bit all ones vector
that zero-extends to 256/512bit.  */
 (define_predicate "vector_all_ones_zero_extend_half_operand"
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 418c337a775..56920a3e1d3 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -1382,6 +1382,29 @@ (define_insn "mov_internal"
  ]
  (symbol_ref "true")))])
 
+; False dependency happens on destination register which is not really
+; used when moving all ones to vector register
+(define_split
+  [(set (match_operand:VMOVE 0 "register_operand")
+   (match_operand:VMOVE 1 "int_float_vector_all_ones_operand"))]
+  "TARGET_AVX512F && reload_completed
+  && ( == 64 || EXT_REX_SSE_REG_P (operands[0]))
+  && optimize_function_for_speed_p (cfun)"
+  [(set (match_dup 0) (match_dup 2))
+   (parallel
+ [(set (match_dup 0) (match_dup 1))
+  (unspec [(match_dup 0)] UNSPEC_INSN_FALSE_DEP)])]
+  "operands[2] = CONST0_RTX (mode);")
+
+(define_insn "*vmov_constm1_pternlog_false_dep"
+  [(set (match_operand:VMOVE 0 "register_operand" "=v")
+   (match_operand:VMOVE 1 "int_float_vector_all_ones_operand" 
""))
+   (unspec [(match_operand:VMOVE 2 "register_operand" "0")] 
UNSPEC_INSN_FALSE_DEP)]
+   "TARGET_AVX512VL ||  == 64"
+   "vpternlogd\t{$0xFF, %0, %0, %0|%0, %0, %0, 0xFF}"
+  [(set_attr "type" "sselog1")
+   (set_attr "prefix" "evex")])
+
 ;; If mem_addr points to a memory region with less than whole vector size bytes
 ;; of accessible memory and k is a mask that would prevent reading the 
inaccessible
 ;; bytes from mem_addr, add UNSPEC_MASKLOAD to prevent it to be transformed to 
vpblendd
@@ -9336,7 +9359,7 @@ (define_expand "_cvtmask2"
 operands[3] = CONST0_RTX (mode);
   }")
 
-(define_insn "*_cvtmask2"
+(define_insn_and_split "*_cvtmask2"
   [(set (match_operand:VI48_AVX512VL 0 "register_operand" "=v,v")
(vec_merge:VI48_AVX512VL
  (match_operand:VI48_AVX512VL 2 "vector_all_ones_operand")
@@ -9346,11 +9369,35 @@ (define_insn "*_cvtmask2"
   "@
vpmovm2\t{%1, %0|%0, %1}
vpternlog\t{$0x81, %0, %0, %0%{%1%}%{z%}|%0%{%1%}%{z%}, %0, 
%0, 0x81}"
+  "&& !TARGET_AVX512DQ && reload_completed
+   && optimize_function_for_speed_p (cfun)"
+  [(set (match_dup 0) (match_dup 4))
+   (parallel
+[(set (match_dup 0)
+ (vec_merge:VI48_AVX512VL
+   (match_dup 2)
+   (match_dup 3)
+   (match_dup 1)))
+ (unspec [(match_dup 0)] UNSPEC_INSN_FALSE_DEP)])]
+  "operands[4] = CONST0_RTX (mode);"
   [(set_attr "isa" "avx512dq,*")
(set_attr "length_immediate" "0,1")
(set_attr "prefix" "evex")
(set_attr "mode" "")])
 
+(define_insn "*_cvtmask2_pternlog_false_dep"
+  [(set (match_operand:VI

[PATCH 1/2] c++, libstdc++: implement __is_pointer built-in trait

2023-07-09 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_pointer.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_POINTER.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
* g++.dg/ext/is_pointer.C: New test.
* g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
(is_pointer): ... this.
* g++.dg/torture/20070621-1.C: Likewise.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
(is_pointer): ... this.
* include/bits/deque.tcc: Use is_pointer instead.
* include/bits/stl_algobase.h: Likewise.

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc|  3 ++
 gcc/cp/cp-trait.def |  1 +
 gcc/cp/semantics.cc |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 ++
 gcc/testsuite/g++.dg/ext/is_pointer.C   | 51 +
 gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
 gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
 libstdc++-v3/include/bits/deque.tcc |  6 +--
 libstdc++-v3/include/bits/stl_algobase.h|  6 +--
 11 files changed, 86 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..30266204eb5 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_POINTER:
+  inform (loc, "  %qT is not a pointer", t1);
+  break;
 case CPTK_IS_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..b7c263e9a77 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
"__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_POINTER, "__is_pointer", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
"__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..68f8a4fe85b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_POINTER:
+  return TYPE_PTR_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
 case CPTK_IS_ENUM:
 case CPTK_IS_UNION:
 case CPTK_IS_SAME:
+case CPTK_IS_POINTER:
   break;
 
 case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..9dace5cbd48 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_pointer)
+# error "__has_builtin (__is_pointer) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
b/gcc/testsuite/g++.dg/ext/is_pointer.C
new file mode 100644
index 000..d6e39565950
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_pointer.C
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(!__is_pointer(int));
+SA(__is_pointer(int*));
+SA(__is_pointer(int**));
+
+SA(__is_pointer(const int*));
+SA(__is_pointer(const int**));
+SA(__is_pointer(int* const));
+SA(__is_pointer(int** const));
+SA(__is_pointer(int* const* const));
+
+SA(__is_pointer(volatile int*));
+SA(__is_pointer(volatile int**));
+SA(__is_pointer(int* volatile));
+SA(__is_pointer(int** volatile));
+SA(__is_pointer(int* volatile* volatile));
+
+SA(__is_pointer(const volatile int*));
+SA(__is_pointer(const volatile int**));
+SA(__is_pointer(const int* volatile));
+SA(__is_pointer(volatile int* const));
+SA(__is_pointer(int* const volatile));
+SA(__is_pointer(const int** volatile));
+SA(__is_pointer(volatile int** const));
+SA(__is_pointer(int** const 

[PATCH 2/2] libstdc++: use new built-in trait __is_pointer

2023-07-09 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_pointer.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_pointer): Use __is_pointer
built-in trait.
(is_pointer_v): Likewise.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..d83db98403b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -515,6 +515,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_array<_Tp[]>
 : public true_type { };
 
+  /// is_pointer
+#if __has_builtin(__is_pointer)
+  template
+struct is_pointer
+: public __bool_constant<__is_pointer(_Tp)>
+{ };
+#else
   template
 struct __is_pointer_helper
 : public false_type { };
@@ -523,11 +530,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct __is_pointer_helper<_Tp*>
 : public true_type { };
 
-  /// is_pointer
   template
 struct is_pointer
 : public __is_pointer_helper<__remove_cv_t<_Tp>>::type
 { };
+#endif
 
   /// is_lvalue_reference
   template
-- 
2.41.0



Re: [PATCH 2/2] libstdc++: use new built-in trait __is_pointer

2023-07-09 Thread Daniel Krügler via Gcc-patches
Am Mo., 10. Juli 2023 um 07:24 Uhr schrieb Ken Matsui via Libstdc++
:
>
> This patch lets libstdc++ use new built-in trait __is_pointer.
>
> libstdc++-v3/ChangeLog:
>
> * include/std/type_traits (is_pointer): Use __is_pointer
> built-in trait.
> (is_pointer_v): Likewise.
>
> Signed-off-by: Ken Matsui 
> ---
>  libstdc++-v3/include/std/type_traits | 9 -
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/libstdc++-v3/include/std/type_traits 
> b/libstdc++-v3/include/std/type_traits
> index 0e7a9c9c7f3..d83db98403b 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -515,6 +515,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  struct is_array<_Tp[]>
>  : public true_type { };
>
> +  /// is_pointer
> +#if __has_builtin(__is_pointer)
> +  template
> +struct is_pointer
> +: public __bool_constant<__is_pointer(_Tp)>
> +{ };
> +#else
>template
>  struct __is_pointer_helper
>  : public false_type { };
> @@ -523,11 +530,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  struct __is_pointer_helper<_Tp*>
>  : public true_type { };
>
> -  /// is_pointer
>template
>  struct is_pointer
>  : public __is_pointer_helper<__remove_cv_t<_Tp>>::type
>  { };
> +#endif
>
>/// is_lvalue_reference
>template
> --
> 2.41.0

Shouldn't this adjust is_pointer_v as well?

Thanks,

- Daniel


Re: [PATCH 2/2] libstdc++: use new built-in trait __is_pointer

2023-07-09 Thread Ken Matsui via Gcc-patches
Oops! Thank you for pointing that out!

Sincerely,
Ken Matsui

On Sun, Jul 9, 2023 at 10:33 PM Daniel Krügler
 wrote:
>
> Am Mo., 10. Juli 2023 um 07:24 Uhr schrieb Ken Matsui via Libstdc++
> :
> >
> > This patch lets libstdc++ use new built-in trait __is_pointer.
> >
> > libstdc++-v3/ChangeLog:
> >
> > * include/std/type_traits (is_pointer): Use __is_pointer
> > built-in trait.
> > (is_pointer_v): Likewise.
> >
> > Signed-off-by: Ken Matsui 
> > ---
> >  libstdc++-v3/include/std/type_traits | 9 -
> >  1 file changed, 8 insertions(+), 1 deletion(-)
> >
> > diff --git a/libstdc++-v3/include/std/type_traits 
> > b/libstdc++-v3/include/std/type_traits
> > index 0e7a9c9c7f3..d83db98403b 100644
> > --- a/libstdc++-v3/include/std/type_traits
> > +++ b/libstdc++-v3/include/std/type_traits
> > @@ -515,6 +515,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >  struct is_array<_Tp[]>
> >  : public true_type { };
> >
> > +  /// is_pointer
> > +#if __has_builtin(__is_pointer)
> > +  template
> > +struct is_pointer
> > +: public __bool_constant<__is_pointer(_Tp)>
> > +{ };
> > +#else
> >template
> >  struct __is_pointer_helper
> >  : public false_type { };
> > @@ -523,11 +530,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >  struct __is_pointer_helper<_Tp*>
> >  : public true_type { };
> >
> > -  /// is_pointer
> >template
> >  struct is_pointer
> >  : public __is_pointer_helper<__remove_cv_t<_Tp>>::type
> >  { };
> > +#endif
> >
> >/// is_lvalue_reference
> >template
> > --
> > 2.41.0
>
> Shouldn't this adjust is_pointer_v as well?
>
> Thanks,
>
> - Daniel


[PATCH v2 1/2] c++, libstdc++: implement __is_pointer built-in trait

2023-07-09 Thread Ken Matsui via Gcc-patches
This patch implements built-in trait for std::is_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_pointer.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_POINTER.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
* g++.dg/ext/is_pointer.C: New test.
* g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
(is_pointer): ... this.
* g++.dg/torture/20070621-1.C: Likewise.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
(is_pointer): ... this.
* include/bits/deque.tcc: Use is_pointer instead.
* include/bits/stl_algobase.h: Likewise.

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc|  3 ++
 gcc/cp/cp-trait.def |  1 +
 gcc/cp/semantics.cc |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 ++
 gcc/testsuite/g++.dg/ext/is_pointer.C   | 51 +
 gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
 gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
 gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
 libstdc++-v3/include/bits/deque.tcc |  6 +--
 libstdc++-v3/include/bits/stl_algobase.h|  6 +--
 11 files changed, 86 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..30266204eb5 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_POINTER:
+  inform (loc, "  %qT is not a pointer", t1);
+  break;
 case CPTK_IS_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..b7c263e9a77 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
"__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_POINTER, "__is_pointer", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
"__reference_converts_from_temporary", 2)
 /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..68f8a4fe85b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
+case CPTK_IS_POINTER:
+  return TYPE_PTR_P (type1);
+
 case CPTK_IS_ASSIGNABLE:
   return is_xible (MODIFY_EXPR, type1, type2);
 
@@ -12296,6 +12299,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
 case CPTK_IS_ENUM:
 case CPTK_IS_UNION:
 case CPTK_IS_SAME:
+case CPTK_IS_POINTER:
   break;
 
 case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..9dace5cbd48 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__is_pointer)
+# error "__has_builtin (__is_pointer) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
b/gcc/testsuite/g++.dg/ext/is_pointer.C
new file mode 100644
index 000..d6e39565950
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_pointer.C
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+SA(!__is_pointer(int));
+SA(__is_pointer(int*));
+SA(__is_pointer(int**));
+
+SA(__is_pointer(const int*));
+SA(__is_pointer(const int**));
+SA(__is_pointer(int* const));
+SA(__is_pointer(int** const));
+SA(__is_pointer(int* const* const));
+
+SA(__is_pointer(volatile int*));
+SA(__is_pointer(volatile int**));
+SA(__is_pointer(int* volatile));
+SA(__is_pointer(int** volatile));
+SA(__is_pointer(int* volatile* volatile));
+
+SA(__is_pointer(const volatile int*));
+SA(__is_pointer(const volatile int**));
+SA(__is_pointer(const int* volatile));
+SA(__is_pointer(volatile int* const));
+SA(__is_pointer(int* const volatile));
+SA(__is_pointer(const int** volatile));
+SA(__is_pointer(volatile int** const));
+SA(__is_pointer(int** const 

[PATCH v2 2/2] libstdc++: use new built-in trait __is_pointer

2023-07-09 Thread Ken Matsui via Gcc-patches
This patch lets libstdc++ use new built-in trait __is_pointer.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_pointer): Use __is_pointer
built-in trait.
(is_pointer_v): Likewise.

Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/std/type_traits | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 0e7a9c9c7f3..b8291a31d3e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -515,6 +515,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_array<_Tp[]>
 : public true_type { };
 
+  /// is_pointer
+#if __has_builtin(__is_pointer)
+  template
+struct is_pointer
+: public __bool_constant<__is_pointer(_Tp)>
+{ };
+#else
   template
 struct __is_pointer_helper
 : public false_type { };
@@ -523,11 +530,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct __is_pointer_helper<_Tp*>
 : public true_type { };
 
-  /// is_pointer
   template
 struct is_pointer
 : public __is_pointer_helper<__remove_cv_t<_Tp>>::type
 { };
+#endif
 
   /// is_lvalue_reference
   template
@@ -3168,8 +3175,14 @@ template 
 template 
   inline constexpr bool is_array_v<_Tp[_Num]> = true;
 
+#if __has_builtin(__is_pointer)
+template 
+  inline constexpr bool is_pointer_v = __is_pointer(_Tp);
+#else
 template 
   inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_lvalue_reference_v = false;
 template 
-- 
2.41.0



Re: [PATCH v2 1/2] c++, libstdc++: implement __is_pointer built-in trait

2023-07-09 Thread Ken Matsui via Gcc-patches
Hi,

Here is the benchmark result for is_pointer:

https://github.com/ken-matsui/gcc-benches/blob/main/is_pointer.md#sun-jul--9-103948-pm-pdt-2023

Time: -62.1344%
Peak Memory Usage: -52.4281%
Total Memory Usage: -53.5889%

Sincerely,
Ken Matsui

On Sun, Jul 9, 2023 at 10:38 PM Ken Matsui  wrote:
>
> This patch implements built-in trait for std::is_pointer.
>
> gcc/cp/ChangeLog:
>
> * cp-trait.def: Define __is_pointer.
> * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_POINTER.
> * semantics.cc (trait_expr_value): Likewise.
> (finish_trait_expr): Likewise.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/ext/has-builtin-1.C: Test existence of __is_pointer.
> * g++.dg/ext/is_pointer.C: New test.
> * g++.dg/tm/pr46567.C (__is_pointer): Rename to ...
> (is_pointer): ... this.
> * g++.dg/torture/20070621-1.C: Likewise.
> * g++.dg/torture/pr57107.C: Likewise.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/cpp_type_traits.h (__is_pointer): Rename to ...
> (is_pointer): ... this.
> * include/bits/deque.tcc: Use is_pointer instead.
> * include/bits/stl_algobase.h: Likewise.
>
> Signed-off-by: Ken Matsui 
> ---
>  gcc/cp/constraint.cc|  3 ++
>  gcc/cp/cp-trait.def |  1 +
>  gcc/cp/semantics.cc |  4 ++
>  gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 ++
>  gcc/testsuite/g++.dg/ext/is_pointer.C   | 51 +
>  gcc/testsuite/g++.dg/tm/pr46567.C   | 22 -
>  gcc/testsuite/g++.dg/torture/20070621-1.C   |  4 +-
>  gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
>  libstdc++-v3/include/bits/cpp_type_traits.h |  6 +--
>  libstdc++-v3/include/bits/deque.tcc |  6 +--
>  libstdc++-v3/include/bits/stl_algobase.h|  6 +--
>  11 files changed, 86 insertions(+), 24 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/ext/is_pointer.C
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 8cf0f2d0974..30266204eb5 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3751,6 +3751,9 @@ diagnose_trait_expr (tree expr, tree args)
>  case CPTK_IS_UNION:
>inform (loc, "  %qT is not a union", t1);
>break;
> +case CPTK_IS_POINTER:
> +  inform (loc, "  %qT is not a pointer", t1);
> +  break;
>  case CPTK_IS_AGGREGATE:
>inform (loc, "  %qT is not an aggregate", t1);
>break;
> diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
> index 8b7fece0cc8..b7c263e9a77 100644
> --- a/gcc/cp/cp-trait.def
> +++ b/gcc/cp/cp-trait.def
> @@ -82,6 +82,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
> "__is_trivially_assignable", 2)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", 
> -1)
>  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
>  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
> +DEFTRAIT_EXPR (IS_POINTER, "__is_pointer", 1)
>  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
> "__reference_constructs_from_temporary", 2)
>  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
> "__reference_converts_from_temporary", 2)
>  /* FIXME Added space to avoid direct usage in GCC 13.  */
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 8fb47fd179e..68f8a4fe85b 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, 
> tree type2)
>  case CPTK_IS_UNION:
>return type_code1 == UNION_TYPE;
>
> +case CPTK_IS_POINTER:
> +  return TYPE_PTR_P (type1);
> +
>  case CPTK_IS_ASSIGNABLE:
>return is_xible (MODIFY_EXPR, type1, type2);
>
> @@ -12296,6 +12299,7 @@ finish_trait_expr (location_t loc, cp_trait_kind 
> kind, tree type1, tree type2)
>  case CPTK_IS_ENUM:
>  case CPTK_IS_UNION:
>  case CPTK_IS_SAME:
> +case CPTK_IS_POINTER:
>break;
>
>  case CPTK_IS_LAYOUT_COMPATIBLE:
> diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
> b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> index f343e153e56..9dace5cbd48 100644
> --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
> @@ -146,3 +146,6 @@
>  #if !__has_builtin (__remove_cvref)
>  # error "__has_builtin (__remove_cvref) failed"
>  #endif
> +#if !__has_builtin (__is_pointer)
> +# error "__has_builtin (__is_pointer) failed"
> +#endif
> diff --git a/gcc/testsuite/g++.dg/ext/is_pointer.C 
> b/gcc/testsuite/g++.dg/ext/is_pointer.C
> new file mode 100644
> index 000..d6e39565950
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ext/is_pointer.C
> @@ -0,0 +1,51 @@
> +// { dg-do compile { target c++11 } }
> +
> +#define SA(X) static_assert((X),#X)
> +
> +SA(!__is_pointer(int));
> +SA(__is_pointer(int*));
> +SA(__is_pointer(int**));
> +
> +SA(__is_pointer(const int*));
> +SA(__is_pointer(const int**));
> +SA(__is_pointer(int* const));
> +SA(__is_pointer(int** const)

Re: [x86 PATCH] Add AVX512 support for STV of SI/DImode rotation by constant.

2023-07-09 Thread Uros Bizjak via Gcc-patches
On Sun, Jul 9, 2023 at 10:35 PM Roger Sayle  wrote:
>
>
> Following Uros' suggestion, this patch adds support for AVX512VL's
> vpro[lr][dq] instructions to the recently added scalar-to-vector (STV)
> enhancements to handle DImode and SImode rotations by a constant.
>
> For the test cases:
>
> unsigned long long rot1(unsigned long long x) {
>   return (x>>1) | (x<<63);
> }
>
> void mem1(unsigned long long *p) {
>   *p = rot1(*p);
> }
>
> with -m32 -O2 -mavx512vl, we currently generate:
>
> rot1:   movl4(%esp), %eax
> movl8(%esp), %edx
> movl%eax, %ecx
> shrdl   $1, %edx, %eax
> shrdl   $1, %ecx, %edx
> ret
>
> mem1:   movl4(%esp), %eax
> vmovq   (%eax), %xmm0
> vpshufd $20, %xmm0, %xmm0
> vpsrlq  $1, %xmm0, %xmm0
> vpshufd $136, %xmm0, %xmm0
> vmovq   %xmm0, (%eax)
> ret
>
> with this patch, we now generate:
>
> rot1:   vmovq   4(%esp), %xmm0
> vprorq  $1, %xmm0, %xmm0
> vmovd   %xmm0, %eax
> vpextrd $1, %xmm0, %edx
> ret
>
> mem1:   movl4(%esp), %eax
> vmovq   (%eax), %xmm0
> vprorq  $1, %xmm0, %xmm0
> vmovq   %xmm0, (%eax)
> ret
>
>
> This patch has been tested on x86_64-pc-linux-gnu (cascadelake which has
> avx512) with make bootstrap and make -k check, both with and without
> --target_board=unix{-m32} with no new failures.  Ok for mainline?
>
>
> 2023-07-09  Roger Sayle  
>
> gcc/ChangeLog
> * config/i386/i386-features.cc (compute_convert_gain): Tweak
> gains/costs for ROTATE/ROTATERT by integer constant on AVX512VL.
> (general_scalar_chain::convert_rotate): On TARGET_AVX512F generate
> avx512vl_rolv2di or avx412vl_rolv4si when appropriate.
>
> gcc/testsuite/ChangeLog
> * gcc.target/i386/avx512vl-stv-rotatedi-1.c: New test case.

OK.

Thanks,
Uros.

>
>
> Cheers,
> Roger
> --
>


Re: [X86 PATCH] Add new insvti_lowpart_1 and insvdi_lowpart_1 patterns.

2023-07-09 Thread Uros Bizjak via Gcc-patches
On Sun, Jul 9, 2023 at 11:30 PM Roger Sayle  wrote:
>
>
> This patch implements another of Uros' suggestions, to investigate a
> insvti_lowpart_1 pattern to improve TImode parameter passing on x86_64.
> In PR 88873, the RTL the middle-end expands for passing V2DF in TImode
> is subtly different from what it does for V2DI in TImode, sufficiently so
> that my explanations for why insvti_lowpart_1 isn't required don't apply
> in this case.
>
> This patch adds an insvti_lowpart_1 pattern, complementing the existing
> insvti_highpart_1 pattern, and also a 32-bit variant, insvdi_lowpart_1.
> Because the middle-end represents 128-bit constants using CONST_WIDE_INT
> and 64-bit constants using CONST_INT, it's easiest to treat these as
> different patterns, rather than attempt  parameterization.
>
> This patch also includes a peephole2 (actually a pair) to transform
> xchg instructions into mov instructions, when one of the destinations
> is unused.  This optimization is required to produce the optimal code
> sequences below.
>
> For the 64-bit case:
>
> __int128 foo(__int128 x, unsigned long long y)
> {
>   __int128 m = ~((__int128)~0ull);
>   __int128 t = x & m;
>   __int128 r = t | y;
>   return r;
> }
>
> Before:
> xchgq   %rdi, %rsi
> movq%rdx, %rax
> xorl%esi, %esi
> xorl%edx, %edx
> orq %rsi, %rax
> orq %rdi, %rdx
> ret
>
> After:
> movq%rdx, %rax
> movq%rsi, %rdx
> ret
>
> For the 32-bit case:
>
> long long bar(long long x, int y)
> {
>   long long mask = ~0ull << 32;
>   long long t = x & mask;
>   long long r = t | (unsigned int)y;
>   return r;
> }
>
> Before:
> pushl   %ebx
> movl12(%esp), %edx
> xorl%ebx, %ebx
> xorl%eax, %eax
> movl16(%esp), %ecx
> orl %ebx, %edx
> popl%ebx
> orl %ecx, %eax
> ret
>
> After:
> movl12(%esp), %eax
> movl8(%esp), %edx
> ret
>
> This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
> and make -k check, both with and without --target_board=unix{-m32}
> with no new failures.  Ok for mainline?
>
>
> 2023-07-09  Roger Sayle  
>
> gcc/ChangeLog
> * config/i386/i386.md (peephole2): Transform xchg insn with a
> REG_UNUSED note to a (simple) move.
> (*insvti_lowpart_1): New define_insn_and_split.
> (*insvdi_lowpart_1): Likewise.
>
> gcc/testsuite/ChangeLog
> * gcc.target/i386/insvdi_lowpart-1.c: New test case.
> * gcc.target/i386/insvti_lowpart-1.c: Likewise.

OK.

Thanks,
Uros.

>
>
> Cheers,
> Roger
> --
>