[gcc r15-377] c++: Implement __is_nothrow_invocable built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:3dab8f8a542aeabfab1a244a7a601b220680c80b

commit r15-377-g3dab8f8a542aeabfab1a244a7a601b220680c80b
Author: Ken Matsui 
Date:   Wed Feb 21 00:46:56 2024 -0800

c++: Implement __is_nothrow_invocable built-in trait

This patch implements built-in trait for std::is_nothrow_invocable.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of
__is_nothrow_invocable.
* g++.dg/ext/is_nothrow_invocable.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/constraint.cc|  6 +++
 gcc/cp/cp-trait.def |  1 +
 gcc/cp/semantics.cc |  5 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 ++
 gcc/testsuite/g++.dg/ext/is_nothrow_invocable.C | 62 +
 5 files changed, 77 insertions(+)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 6d14ef7dcc75..8679d3ce658d 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3825,6 +3825,12 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_NOTHROW_CONVERTIBLE:
  inform (loc, "  %qT is not nothrow convertible from %qE", t2, t1);
   break;
+case CPTK_IS_NOTHROW_INVOCABLE:
+   if (!t2)
+ inform (loc, "  %qT is not nothrow invocable", t1);
+   else
+ inform (loc, "  %qT is not nothrow invocable by %qE", t1, t2);
+   break;
 case CPTK_IS_OBJECT:
   inform (loc, "  %qT is not an object type", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 4e420d5390a6..0721ecdf3f05 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -84,6 +84,7 @@ DEFTRAIT_EXPR (IS_MEMBER_POINTER, "__is_member_pointer", 1)
 DEFTRAIT_EXPR (IS_NOTHROW_ASSIGNABLE, "__is_nothrow_assignable", 2)
 DEFTRAIT_EXPR (IS_NOTHROW_CONSTRUCTIBLE, "__is_nothrow_constructible", -1)
 DEFTRAIT_EXPR (IS_NOTHROW_CONVERTIBLE, "__is_nothrow_convertible", 2)
+DEFTRAIT_EXPR (IS_NOTHROW_INVOCABLE, "__is_nothrow_invocable", -1)
 DEFTRAIT_EXPR (IS_OBJECT, "__is_object", 1)
 DEFTRAIT_EXPR (IS_POINTER_INTERCONVERTIBLE_BASE_OF, 
"__is_pointer_interconvertible_base_of", 2)
 DEFTRAIT_EXPR (IS_POD, "__is_pod", 1)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 311e4f472d83..43b175f92fdc 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12592,6 +12592,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_NOTHROW_CONVERTIBLE:
   return is_nothrow_convertible (type1, type2);
 
+case CPTK_IS_NOTHROW_INVOCABLE:
+  return expr_noexcept_p (build_invoke (type1, type2, tf_none), tf_none);
+
 case CPTK_IS_OBJECT:
   return object_type_p (type1);
 
@@ -12727,6 +12730,7 @@ same_type_ref_bind_p (cp_trait_kind kind, tree type1, 
tree type2)
 case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
 case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
 case CPTK_IS_INVOCABLE:
+case CPTK_IS_NOTHROW_INVOCABLE:
 case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
 case CPTK_REF_CONVERTS_FROM_TEMPORARY:
   to = type1;
@@ -12832,6 +12836,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
 case CPTK_IS_INVOCABLE:
 case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
 case CPTK_IS_NOTHROW_CONVERTIBLE:
+case CPTK_IS_NOTHROW_INVOCABLE:
 case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
 case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
 case CPTK_REF_CONVERTS_FROM_TEMPORARY:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index d1c662678556..65740a118001 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -134,6 +134,9 @@
 #if !__has_builtin (__is_nothrow_convertible)
 # error "__has_builtin (__is_nothrow_convertible) failed"
 #endif
+#if !__has_builtin (__is_nothrow_invocable)
+# error "__has_builtin (__is_nothrow_invocable) failed"
+#endif
 #if !__has_builtin (__is_object)
 # error "__has_builtin (__is_object) failed"
 #endif
diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_invocable.C 
b/gcc/testsuite/g++.dg/ext/is_nothrow_invocable.C
new file mode 100644
index ..2f9b40e5538d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_nothrow_invocable.C
@@ -0,0 +1,62 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+using func_type = void(*)();
+SA( ! __is_nothrow_invocable(func_type) );
+
+#if __cpp_noexcept_function_type
+using func_type_nt = void(*)() noexcept;
+SA(   __is_nothrow_invocable(func_type_nt) );
+#endif
+
+struct X { };
+using mem_type = int X::*;
+
+SA( ! 

[gcc r15-376] c++: Implement __is_invocable built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:7bd33955970202095738e85c4ddf161432ece099

commit r15-376-g7bd33955970202095738e85c4ddf161432ece099
Author: Ken Matsui 
Date:   Mon Feb 19 18:10:16 2024 -0800

c++: Implement __is_invocable built-in trait

This patch implements built-in trait for std::is_invocable.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_invocable.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_INVOCABLE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.
* cp-tree.h (build_invoke): New function.
* method.cc (build_invoke): New function.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_invocable.
* g++.dg/ext/is_invocable1.C: New test.
* g++.dg/ext/is_invocable2.C: New test.
* g++.dg/ext/is_invocable3.C: New test.
* g++.dg/ext/is_invocable4.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Patrick Palka 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/constraint.cc |   6 +
 gcc/cp/cp-trait.def  |   1 +
 gcc/cp/cp-tree.h |   2 +
 gcc/cp/method.cc | 135 
 gcc/cp/semantics.cc  |   5 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
 gcc/testsuite/g++.dg/ext/is_invocable1.C | 349 +++
 gcc/testsuite/g++.dg/ext/is_invocable2.C | 139 
 gcc/testsuite/g++.dg/ext/is_invocable3.C |  51 +
 gcc/testsuite/g++.dg/ext/is_invocable4.C |  33 +++
 10 files changed, 724 insertions(+)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c28d7bf428ee..6d14ef7dcc75 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3792,6 +3792,12 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_FUNCTION:
   inform (loc, "  %qT is not a function", t1);
   break;
+case CPTK_IS_INVOCABLE:
+  if (!t2)
+inform (loc, "  %qT is not invocable", t1);
+  else
+inform (loc, "  %qT is not invocable by %qE", t1, t2);
+  break;
 case CPTK_IS_LAYOUT_COMPATIBLE:
   inform (loc, "  %qT is not layout compatible with %qT", t1, t2);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b1c875a6e7d4..4e420d5390a6 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -75,6 +75,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
 DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
 DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
 DEFTRAIT_EXPR (IS_MEMBER_FUNCTION_POINTER, "__is_member_function_pointer", 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 07e9632942bb..e68ca1dd5e7b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7341,6 +7341,8 @@ extern tree get_copy_assign   (tree);
 extern tree get_default_ctor   (tree);
 extern tree get_dtor   (tree, tsubst_flags_t);
 extern tree build_stub_object  (tree);
+extern tree build_invoke   (tree, const_tree,
+tsubst_flags_t);
 extern tree strip_inheriting_ctors (tree);
 extern tree inherited_ctor_binfo   (tree);
 extern bool base_ctor_omit_inherited_parms (tree);
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 08a3d34fb016..0b21656ed612 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1928,6 +1928,141 @@ build_trait_object (tree type)
   return build_stub_object (type);
 }
 
+/* [func.require] Build an expression of INVOKE(FN_TYPE, ARG_TYPES...).  If the
+   given is not invocable, returns error_mark_node.  */
+
+tree
+build_invoke (tree fn_type, const_tree arg_types, tsubst_flags_t complain)
+{
+  if (error_operand_p (fn_type) || error_operand_p (arg_types))
+return error_mark_node;
+
+  gcc_assert (TYPE_P (fn_type));
+  gcc_assert (TREE_CODE (arg_types) == TREE_VEC);
+
+  /* Access check is required to determine if the given is invocable.  */
+  deferring_access_check_sentinel acs (dk_no_deferred);
+
+  /* INVOKE is an unevaluated context.  */
+  cp_unevaluated cp_uneval_guard;
+
+  bool is_ptrdatamem;
+  bool is_ptrmemfunc;
+  if (TREE_CODE (fn_type) == REFERENCE_TYPE)
+{
+  tree non_ref_fn_type = TREE_TYPE (fn_type);
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (non_ref_fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P (non_ref_fn_type);
+
+  /* Dereference fn_type if it is a pointer to member.  */
+  if (is_ptrdatamem || is_ptrmemfunc)
+   fn_type = non_ref_fn_type;
+}
+  else
+{
+  is_ptrdatamem = TYPE_PTRDATAMEM_P (fn_type);
+  is_ptrmemfunc = TYPE_PTRMEMFUNC_P 

[gcc r15-375] c++: Implement __array_rank built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:37fad797adea340307fb33c3d7a0a17652063a33

commit r15-375-g37fad797adea340307fb33c3d7a0a17652063a33
Author: Ken Matsui 
Date:   Thu Feb 15 07:17:31 2024 -0800

c++: Implement __array_rank built-in trait

This patch implements built-in trait for std::rank.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __array_rank.
* g++.dg/ext/rank.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/constraint.cc |  3 +++
 gcc/cp/cp-trait.def  |  1 +
 gcc/cp/semantics.cc  | 24 +---
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/rank.C  | 24 
 5 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index d4cc88504863..c28d7bf428ee 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3871,6 +3871,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_VOLATILE:
   inform (loc, "  %qT is not a volatile type", t1);
   break;
+case CPTK_RANK:
+  inform (loc, "  %qT cannot yield a rank", t1);
+  break;
 case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
   inform (loc, "  %qT is not a reference that binds to a temporary "
  "object of type %qT (direct-initialization)", t1, t2);
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 2d1cb7c227c0..b1c875a6e7d4 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -99,6 +99,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, 
"__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNBOUNDED_ARRAY, "__is_unbounded_array", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_VOLATILE, "__is_volatile", 1)
+DEFTRAIT_EXPR (RANK, "__array_rank", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
"__reference_converts_from_temporary", 2)
 DEFTRAIT_TYPE (REMOVE_ALL_EXTENTS, "__remove_all_extents", 1)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index d499b858057c..bde26e4f2bb4 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12646,6 +12646,10 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_DEDUCIBLE:
   return type_targs_deducible_from (type1, type2);
 
+/* __array_rank is handled in finish_trait_expr. */
+case CPTK_RANK:
+  gcc_unreachable ();
+
 #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \
 case CPTK_##CODE:
 #include "cp-trait.def"
@@ -12769,7 +12773,10 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
   if (processing_template_decl)
 {
   tree trait_expr = make_node (TRAIT_EXPR);
-  TREE_TYPE (trait_expr) = boolean_type_node;
+  if (kind == CPTK_RANK)
+   TREE_TYPE (trait_expr) = size_type_node;
+  else
+   TREE_TYPE (trait_expr) = boolean_type_node;
   TRAIT_EXPR_TYPE1 (trait_expr) = type1;
   TRAIT_EXPR_TYPE2 (trait_expr) = type2;
   TRAIT_EXPR_KIND (trait_expr) = kind;
@@ -12862,6 +12869,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
 case CPTK_IS_UNBOUNDED_ARRAY:
 case CPTK_IS_UNION:
 case CPTK_IS_VOLATILE:
+case CPTK_RANK:
   break;
 
 case CPTK_IS_LAYOUT_COMPATIBLE:
@@ -12893,8 +12901,18 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
   gcc_unreachable ();
 }
 
-  tree val = (trait_expr_value (kind, type1, type2)
- ? boolean_true_node : boolean_false_node);
+  tree val;
+  if (kind == CPTK_RANK)
+{
+  size_t __array_rank = 0;
+  for (; TREE_CODE (type1) == ARRAY_TYPE; type1 = TREE_TYPE (type1))
+   ++__array_rank;
+  val = build_int_cst (size_type_node, __array_rank);
+}
+  else
+val = (trait_expr_value (kind, type1, type2)
+  ? boolean_true_node : boolean_false_node);
+
   return maybe_wrap_with_location (val, loc);
 }
 
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index d2e6a5b4dcb3..bcaa56a7bc5c 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -11,6 +11,9 @@
 #if !__has_builtin (__add_rvalue_reference)
 # error "__has_builtin (__add_rvalue_reference) failed"
 #endif
+#if !__has_builtin (__array_rank)
+# error "__has_builtin (__array_rank) failed"
+#endif
 #if !__has_builtin (__builtin_addressof)
 # error "__has_builtin (__builtin_addressof) failed"
 #endif
diff --git a/gcc/testsuite/g++.dg/ext/rank.C b/gcc/testsuite/g++.dg/ext/rank.C
new file 

[gcc r15-374] c++: Implement __decay built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:142d1d8e057c0e6da7f4e6eba4cc265c556d2dd8

commit r15-374-g142d1d8e057c0e6da7f4e6eba4cc265c556d2dd8
Author: Ken Matsui 
Date:   Thu Feb 15 04:43:41 2024 -0800

c++: Implement __decay built-in trait

This patch implements built-in trait for std::decay.

gcc/cp/ChangeLog:

* cp-trait.def: Define __decay.
* semantics.cc (finish_trait_type): Handle CPTK_DECAY.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __decay.
* g++.dg/ext/decay.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-trait.def  |  1 +
 gcc/cp/semantics.cc  | 12 
 gcc/testsuite/g++.dg/ext/decay.C | 22 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 4 files changed, 38 insertions(+)

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 173818adf792..2d1cb7c227c0 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -51,6 +51,7 @@
 DEFTRAIT_TYPE (ADD_LVALUE_REFERENCE, "__add_lvalue_reference", 1)
 DEFTRAIT_TYPE (ADD_POINTER, "__add_pointer", 1)
 DEFTRAIT_TYPE (ADD_RVALUE_REFERENCE, "__add_rvalue_reference", 1)
+DEFTRAIT_TYPE (DECAY, "__decay", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_ASSIGN, "__has_nothrow_assign", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_CONSTRUCTOR, "__has_nothrow_constructor", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_COPY, "__has_nothrow_copy", 1)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index f6338f77d239..d499b858057c 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12946,6 +12946,18 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
tree type2,
return cp_build_reference_type (type1, /*rval=*/true);
   return type1;
 
+case CPTK_DECAY:
+  if (TYPE_REF_P (type1))
+   type1 = TREE_TYPE (type1);
+
+  if (TREE_CODE (type1) == ARRAY_TYPE)
+   return finish_trait_type (CPTK_ADD_POINTER, TREE_TYPE (type1), type2,
+ complain);
+  else if (TREE_CODE (type1) == FUNCTION_TYPE)
+   return finish_trait_type (CPTK_ADD_POINTER, type1, type2, complain);
+  else
+   return cv_unqualified (type1);
+
 case CPTK_REMOVE_ALL_EXTENTS:
   return strip_array_types (type1);
 
diff --git a/gcc/testsuite/g++.dg/ext/decay.C b/gcc/testsuite/g++.dg/ext/decay.C
new file mode 100644
index ..8adedfeefe6c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/decay.C
@@ -0,0 +1,22 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+// Positive tests.
+using test1_type = __decay(bool);
+SA(__is_same(test1_type, bool));
+
+// NB: DR 705.
+using test2_type = __decay(const int);
+SA(__is_same(test2_type, int));
+
+using test3_type = __decay(int[4]);
+SA(__is_same(test3_type, __remove_extent(int[4])*));
+
+using fn_type = void ();
+using test4_type = __decay(fn_type);
+SA(__is_same(test4_type, __add_pointer(fn_type)));
+
+using cfn_type = void () const;
+using test5_type = __decay(cfn_type);
+SA(__is_same(test5_type, cfn_type));
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 266cb35a3684..d2e6a5b4dcb3 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -32,6 +32,9 @@
 #if !__has_builtin (__builtin_source_location)
 # error "__has_builtin (__builtin_source_location) failed"
 #endif
+#if !__has_builtin (__decay)
+# error "__has_builtin (__decay) failed"
+#endif
 #if !__has_builtin (__has_nothrow_assign)
 # error "__has_builtin (__has_nothrow_assign) failed"
 #endif


[gcc r15-373] c++: Implement __add_rvalue_reference built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:85c2ba4244196dcccdf0647ff49f376c52513f65

commit r15-373-g85c2ba4244196dcccdf0647ff49f376c52513f65
Author: Ken Matsui 
Date:   Thu Feb 15 00:48:14 2024 -0800

c++: Implement __add_rvalue_reference built-in trait

This patch implements built-in trait for std::add_rvalue_reference.

gcc/cp/ChangeLog:

* cp-trait.def: Define __add_rvalue_reference.
* semantics.cc (finish_trait_type): Handle
CPTK_ADD_RVALUE_REFERENCE.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of
__add_rvalue_reference.
* g++.dg/ext/add_rvalue_reference.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-trait.def |  1 +
 gcc/cp/semantics.cc |  6 ++
 gcc/testsuite/g++.dg/ext/add_rvalue_reference.C | 20 
 gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 +++
 4 files changed, 30 insertions(+)

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 9a27dca4ea35..173818adf792 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -50,6 +50,7 @@
 
 DEFTRAIT_TYPE (ADD_LVALUE_REFERENCE, "__add_lvalue_reference", 1)
 DEFTRAIT_TYPE (ADD_POINTER, "__add_pointer", 1)
+DEFTRAIT_TYPE (ADD_RVALUE_REFERENCE, "__add_rvalue_reference", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_ASSIGN, "__has_nothrow_assign", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_CONSTRUCTOR, "__has_nothrow_constructor", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_COPY, "__has_nothrow_copy", 1)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index a6f795d6336b..f6338f77d239 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12940,6 +12940,12 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
tree type2,
}
   return type1;
 
+case CPTK_ADD_RVALUE_REFERENCE:
+  /* [meta.trans.ref].  */
+  if (referenceable_type_p (type1))
+   return cp_build_reference_type (type1, /*rval=*/true);
+  return type1;
+
 case CPTK_REMOVE_ALL_EXTENTS:
   return strip_array_types (type1);
 
diff --git a/gcc/testsuite/g++.dg/ext/add_rvalue_reference.C 
b/gcc/testsuite/g++.dg/ext/add_rvalue_reference.C
new file mode 100644
index ..c92fe6bfa17b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/add_rvalue_reference.C
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+class ClassType { };
+
+SA(__is_same(__add_rvalue_reference(int), int&&));
+SA(__is_same(__add_rvalue_reference(int&&), int&&));
+SA(__is_same(__add_rvalue_reference(int&), int&));
+SA(__is_same(__add_rvalue_reference(const int), const int&&));
+SA(__is_same(__add_rvalue_reference(int*), int*&&));
+SA(__is_same(__add_rvalue_reference(ClassType&&), ClassType&&));
+SA(__is_same(__add_rvalue_reference(ClassType), ClassType&&));
+SA(__is_same(__add_rvalue_reference(int(int)), int(&&)(int)));
+SA(__is_same(__add_rvalue_reference(void), void));
+SA(__is_same(__add_rvalue_reference(const void), const void));
+SA(__is_same(__add_rvalue_reference(bool(int) const), bool(int) const));
+SA(__is_same(__add_rvalue_reference(bool(int) &), bool(int) &));
+SA(__is_same(__add_rvalue_reference(bool(int) const &&), bool(int) const &&));
+SA(__is_same(__add_rvalue_reference(bool(int)), bool(&&)(int)));
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index a8b2f0fcfd28..266cb35a3684 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -8,6 +8,9 @@
 #if !__has_builtin (__add_pointer)
 # error "__has_builtin (__add_pointer) failed"
 #endif
+#if !__has_builtin (__add_rvalue_reference)
+# error "__has_builtin (__add_rvalue_reference) failed"
+#endif
 #if !__has_builtin (__builtin_addressof)
 # error "__has_builtin (__builtin_addressof) failed"
 #endif


[gcc r15-372] c++: Implement __add_lvalue_reference built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:c08d1afbf539a672f28100640d964565ac575ff5

commit r15-372-gc08d1afbf539a672f28100640d964565ac575ff5
Author: Ken Matsui 
Date:   Wed Feb 14 23:21:35 2024 -0800

c++: Implement __add_lvalue_reference built-in trait

This patch implements built-in trait for std::add_lvalue_reference.

gcc/cp/ChangeLog:

* cp-trait.def: Define __add_lvalue_reference.
* semantics.cc (finish_trait_type): Handle
CPTK_ADD_LVALUE_REFERENCE.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of
__add_lvalue_reference.
* g++.dg/ext/add_lvalue_reference.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-trait.def |  1 +
 gcc/cp/semantics.cc |  6 ++
 gcc/testsuite/g++.dg/ext/add_lvalue_reference.C | 21 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 +++
 4 files changed, 31 insertions(+)

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 933c8bcbe68e..9a27dca4ea35 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -48,6 +48,7 @@
 #define DEFTRAIT_TYPE_DEFAULTED
 #endif
 
+DEFTRAIT_TYPE (ADD_LVALUE_REFERENCE, "__add_lvalue_reference", 1)
 DEFTRAIT_TYPE (ADD_POINTER, "__add_pointer", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_ASSIGN, "__has_nothrow_assign", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_CONSTRUCTOR, "__has_nothrow_constructor", 1)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index c2ab08c56052..a6f795d6336b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12924,6 +12924,12 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
tree type2,
 
   switch (kind)
 {
+case CPTK_ADD_LVALUE_REFERENCE:
+  /* [meta.trans.ref].  */
+  if (referenceable_type_p (type1))
+   return cp_build_reference_type (type1, /*rval=*/false);
+  return type1;
+
 case CPTK_ADD_POINTER:
   /* [meta.trans.ptr].  */
   if (VOID_TYPE_P (type1) || referenceable_type_p (type1))
diff --git a/gcc/testsuite/g++.dg/ext/add_lvalue_reference.C 
b/gcc/testsuite/g++.dg/ext/add_lvalue_reference.C
new file mode 100644
index ..8fe1e0300e5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/add_lvalue_reference.C
@@ -0,0 +1,21 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+class ClassType { };
+
+SA(__is_same(__add_lvalue_reference(int), int&));
+SA(__is_same(__add_lvalue_reference(int&), int&));
+SA(__is_same(__add_lvalue_reference(const int), const int&));
+SA(__is_same(__add_lvalue_reference(int*), int*&));
+SA(__is_same(__add_lvalue_reference(ClassType&), ClassType&));
+SA(__is_same(__add_lvalue_reference(ClassType), ClassType&));
+SA(__is_same(__add_lvalue_reference(int(int)), int(&)(int)));
+SA(__is_same(__add_lvalue_reference(int&&), int&));
+SA(__is_same(__add_lvalue_reference(ClassType&&), ClassType&));
+SA(__is_same(__add_lvalue_reference(void), void));
+SA(__is_same(__add_lvalue_reference(const void), const void));
+SA(__is_same(__add_lvalue_reference(bool(int) const), bool(int) const));
+SA(__is_same(__add_lvalue_reference(bool(int) &), bool(int) &));
+SA(__is_same(__add_lvalue_reference(bool(int) const &&), bool(int) const &&));
+SA(__is_same(__add_lvalue_reference(bool(int)), bool(&)(int)));
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f0b165e28916..a8b2f0fcfd28 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -2,6 +2,9 @@
 // { dg-do compile }
 // Verify that __has_builtin gives the correct answer for C++ built-ins.
 
+#if !__has_builtin (__add_lvalue_reference)
+# error "__has_builtin (__add_lvalue_reference) failed"
+#endif
 #if !__has_builtin (__add_pointer)
 # error "__has_builtin (__add_pointer) failed"
 #endif


[gcc r15-371] c++: Implement __remove_all_extents built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:86812be98a129ac9923df5dfb6b457bfe28e9e8c

commit r15-371-g86812be98a129ac9923df5dfb6b457bfe28e9e8c
Author: Ken Matsui 
Date:   Wed Feb 14 22:45:31 2024 -0800

c++: Implement __remove_all_extents built-in trait

This patch implements built-in trait for std::remove_all_extents.

gcc/cp/ChangeLog:

* cp-trait.def: Define __remove_all_extents.
* semantics.cc (finish_trait_type): Handle
CPTK_REMOVE_ALL_EXTENTS.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of
__remove_all_extents.
* g++.dg/ext/remove_all_extents.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-trait.def   |  1 +
 gcc/cp/semantics.cc   |  3 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C  |  3 +++
 gcc/testsuite/g++.dg/ext/remove_all_extents.C | 16 
 4 files changed, 23 insertions(+)

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 577c96d579bf..933c8bcbe68e 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -98,6 +98,7 @@ DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_VOLATILE, "__is_volatile", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
"__reference_converts_from_temporary", 2)
+DEFTRAIT_TYPE (REMOVE_ALL_EXTENTS, "__remove_all_extents", 1)
 DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
 DEFTRAIT_TYPE (REMOVE_CVREF, "__remove_cvref", 1)
 DEFTRAIT_TYPE (REMOVE_EXTENT, "__remove_extent", 1)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index b2122cedff5e..c2ab08c56052 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12934,6 +12934,9 @@ finish_trait_type (cp_trait_kind kind, tree type1, tree 
type2,
}
   return type1;
 
+case CPTK_REMOVE_ALL_EXTENTS:
+  return strip_array_types (type1);
+
 case CPTK_REMOVE_CV:
   return cv_unqualified (type1);
 
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index d58e41867049..f0b165e28916 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -176,6 +176,9 @@
 #if !__has_builtin (__reference_converts_from_temporary)
 # error "__has_builtin (__reference_converts_from_temporary) failed"
 #endif
+#if !__has_builtin (__remove_all_extents)
+# error "__has_builtin (__remove_all_extents) failed"
+#endif
 #if !__has_builtin (__remove_cv)
 # error "__has_builtin (__remove_cv) failed"
 #endif
diff --git a/gcc/testsuite/g++.dg/ext/remove_all_extents.C 
b/gcc/testsuite/g++.dg/ext/remove_all_extents.C
new file mode 100644
index ..60ade2ade7fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/remove_all_extents.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+class ClassType { };
+
+SA(__is_same(__remove_all_extents(int), int));
+SA(__is_same(__remove_all_extents(int[2]), int));
+SA(__is_same(__remove_all_extents(int[2][3]), int));
+SA(__is_same(__remove_all_extents(int[][3]), int));
+SA(__is_same(__remove_all_extents(const int[2][3]), const int));
+SA(__is_same(__remove_all_extents(ClassType), ClassType));
+SA(__is_same(__remove_all_extents(ClassType[2]), ClassType));
+SA(__is_same(__remove_all_extents(ClassType[2][3]), ClassType));
+SA(__is_same(__remove_all_extents(ClassType[][3]), ClassType));
+SA(__is_same(__remove_all_extents(const ClassType[2][3]), const ClassType));


[gcc r15-370] c++: Implement __remove_extent built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:e1ca1fa1c7a347088551aa7de521d2a87c1a7863

commit r15-370-ge1ca1fa1c7a347088551aa7de521d2a87c1a7863
Author: Ken Matsui 
Date:   Wed Feb 14 05:49:35 2024 -0800

c++: Implement __remove_extent built-in trait

This patch implements built-in trait for std::remove_extent.

gcc/cp/ChangeLog:

* cp-trait.def: Define __remove_extent.
* semantics.cc (finish_trait_type): Handle CPTK_REMOVE_EXTENT.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __remove_extent.
* g++.dg/ext/remove_extent.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-trait.def  |  1 +
 gcc/cp/semantics.cc  |  5 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 gcc/testsuite/g++.dg/ext/remove_extent.C | 16 
 4 files changed, 25 insertions(+)

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 63f879287ce1..577c96d579bf 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -100,6 +100,7 @@ DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_tempo
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
"__reference_converts_from_temporary", 2)
 DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
 DEFTRAIT_TYPE (REMOVE_CVREF, "__remove_cvref", 1)
+DEFTRAIT_TYPE (REMOVE_EXTENT, "__remove_extent", 1)
 DEFTRAIT_TYPE (REMOVE_POINTER, "__remove_pointer", 1)
 DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1)
 DEFTRAIT_TYPE (TYPE_PACK_ELEMENT, "__type_pack_element", -1)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 4920b5627849..b2122cedff5e 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12942,6 +12942,11 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
tree type2,
type1 = TREE_TYPE (type1);
   return cv_unqualified (type1);
 
+case CPTK_REMOVE_EXTENT:
+  if (TREE_CODE (type1) == ARRAY_TYPE)
+   type1 = TREE_TYPE (type1);
+  return type1;
+
 case CPTK_REMOVE_POINTER:
   if (TYPE_PTR_P (type1))
type1 = TREE_TYPE (type1);
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index bd9e064ce3aa..d58e41867049 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -182,6 +182,9 @@
 #if !__has_builtin (__remove_cvref)
 # error "__has_builtin (__remove_cvref) failed"
 #endif
+#if !__has_builtin (__remove_extent)
+# error "__has_builtin (__remove_extent) failed"
+#endif
 #if !__has_builtin (__remove_pointer)
 # error "__has_builtin (__remove_pointer) failed"
 #endif
diff --git a/gcc/testsuite/g++.dg/ext/remove_extent.C 
b/gcc/testsuite/g++.dg/ext/remove_extent.C
new file mode 100644
index ..6183aca5a487
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/remove_extent.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+class ClassType { };
+
+SA(__is_same(__remove_extent(int), int));
+SA(__is_same(__remove_extent(int[2]), int));
+SA(__is_same(__remove_extent(int[2][3]), int[3]));
+SA(__is_same(__remove_extent(int[][3]), int[3]));
+SA(__is_same(__remove_extent(const int[2]), const int));
+SA(__is_same(__remove_extent(ClassType), ClassType));
+SA(__is_same(__remove_extent(ClassType[2]), ClassType));
+SA(__is_same(__remove_extent(ClassType[2][3]), ClassType[3]));
+SA(__is_same(__remove_extent(ClassType[][3]), ClassType[3]));
+SA(__is_same(__remove_extent(const ClassType[2]), const ClassType));


[gcc r15-369] c++: Implement __add_pointer built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:2763f81e0b93700bc879690ce2a7d258c3989924

commit r15-369-g2763f81e0b93700bc879690ce2a7d258c3989924
Author: Ken Matsui 
Date:   Wed Feb 14 03:40:00 2024 -0800

c++: Implement __add_pointer built-in trait

This patch implements built-in trait for std::add_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __add_pointer.
* semantics.cc (finish_trait_type): Handle CPTK_ADD_POINTER.
(object_type_p): New function.
(referenceable_type_p): Likewise.
(trait_expr_value): Use object_type_p.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __add_pointer.
* g++.dg/ext/add_pointer.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/cp-trait.def  |  1 +
 gcc/cp/semantics.cc  | 36 ++---
 gcc/testsuite/g++.dg/ext/add_pointer.C   | 39 
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 +++
 4 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 05514a51c21f..63f879287ce1 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -48,6 +48,7 @@
 #define DEFTRAIT_TYPE_DEFAULTED
 #endif
 
+DEFTRAIT_TYPE (ADD_POINTER, "__add_pointer", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_ASSIGN, "__has_nothrow_assign", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_CONSTRUCTOR, "__has_nothrow_constructor", 1)
 DEFTRAIT_EXPR (HAS_NOTHROW_COPY, "__has_nothrow_copy", 1)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index e49d3e35e8b5..4920b5627849 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12438,6 +12438,16 @@ fold_builtin_is_corresponding_member (location_t loc, 
int nargs,
   fold_convert (TREE_TYPE (arg1), arg2)));
 }
 
+/* [basic.types] 8.  True iff TYPE is an object type.  */
+
+static bool
+object_type_p (const_tree type)
+{
+  return (TREE_CODE (type) != FUNCTION_TYPE
+  && !TYPE_REF_P (type)
+  && !VOID_TYPE_P (type));
+}
+
 /* Actually evaluates the trait.  */
 
 static bool
@@ -12580,9 +12590,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
   return is_nothrow_convertible (type1, type2);
 
 case CPTK_IS_OBJECT:
-  return (type_code1 != FUNCTION_TYPE
- && type_code1 != REFERENCE_TYPE
- && type_code1 != VOID_TYPE);
+  return object_type_p (type1);
 
 case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF:
   return pointer_interconvertible_base_of_p (type1, type2);
@@ -12737,6 +12745,18 @@ same_type_ref_bind_p (cp_trait_kind kind, tree type1, 
tree type2)
  (non_reference (to), non_reference (from;
 }
 
+/* [defns.referenceable] True iff TYPE is a referenceable type.  */
+
+static bool
+referenceable_type_p (const_tree type)
+{
+  return (TYPE_REF_P (type)
+ || object_type_p (type)
+ || (FUNC_OR_METHOD_TYPE_P (type)
+ && (type_memfn_quals (type) == TYPE_UNQUALIFIED
+ && type_memfn_rqual (type) == REF_QUAL_NONE)));
+}
+
 /* Process a trait expression.  */
 
 tree
@@ -12904,6 +12924,16 @@ finish_trait_type (cp_trait_kind kind, tree type1, 
tree type2,
 
   switch (kind)
 {
+case CPTK_ADD_POINTER:
+  /* [meta.trans.ptr].  */
+  if (VOID_TYPE_P (type1) || referenceable_type_p (type1))
+   {
+ if (TYPE_REF_P (type1))
+   type1 = TREE_TYPE (type1);
+ return build_pointer_type (type1);
+   }
+  return type1;
+
 case CPTK_REMOVE_CV:
   return cv_unqualified (type1);
 
diff --git a/gcc/testsuite/g++.dg/ext/add_pointer.C 
b/gcc/testsuite/g++.dg/ext/add_pointer.C
new file mode 100644
index ..c405cdd0feb5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/add_pointer.C
@@ -0,0 +1,39 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+class ClassType { };
+
+SA(__is_same(__add_pointer(int), int*));
+SA(__is_same(__add_pointer(int*), int**));
+SA(__is_same(__add_pointer(const int), const int*));
+SA(__is_same(__add_pointer(int&), int*));
+SA(__is_same(__add_pointer(ClassType*), ClassType**));
+SA(__is_same(__add_pointer(ClassType), ClassType*));
+SA(__is_same(__add_pointer(void), void*));
+SA(__is_same(__add_pointer(const void), const void*));
+SA(__is_same(__add_pointer(volatile void), volatile void*));
+SA(__is_same(__add_pointer(const volatile void), const volatile void*));
+
+void f1();
+using f1_type = decltype(f1);
+using pf1_type = decltype();
+SA(__is_same(__add_pointer(f1_type), pf1_type));
+
+void f2() noexcept; // PR libstdc++/78361
+using f2_type = decltype(f2);
+using pf2_type = decltype();
+SA(__is_same(__add_pointer(f2_type), pf2_type));
+
+using fn_type = void();
+using pfn_type = void(*)();
+SA(__is_same(__add_pointer(fn_type), pfn_type));
+
+SA(__is_same(__add_pointer(void() &), void() &));

[gcc r15-368] c++: Implement __is_unbounded_array built-in trait

2024-05-10 Thread Ken Matsui via Gcc-cvs
https://gcc.gnu.org/g:06d64eb96cd9faf7e725bd4fbe5b859d23c5ecb5

commit r15-368-g06d64eb96cd9faf7e725bd4fbe5b859d23c5ecb5
Author: Ken Matsui 
Date:   Mon Sep 11 13:54:39 2023 -0700

c++: Implement __is_unbounded_array built-in trait

This patch implements built-in trait for std::is_unbounded_array.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of
__is_unbounded_array.
* g++.dg/ext/is_unbounded_array.C: New test.

Signed-off-by: Ken Matsui 
Reviewed-by: Jason Merrill 

Diff:
---
 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_unbounded_array.C | 37 +++
 5 files changed, 48 insertions(+)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 5a8aaa70fa60..d4cc88504863 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3862,6 +3862,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_TRIVIALLY_COPYABLE:
   inform (loc, "  %qT is not trivially copyable", t1);
   break;
+case CPTK_IS_UNBOUNDED_ARRAY:
+  inform (loc, "  %qT is not an unbounded array", t1);
+  break;
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 18e2d0f3480c..05514a51c21f 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -92,6 +92,7 @@ DEFTRAIT_EXPR (IS_TRIVIAL, "__is_trivial", 1)
 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_UNBOUNDED_ARRAY, "__is_unbounded_array", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
 DEFTRAIT_EXPR (IS_VOLATILE, "__is_volatile", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_temporary", 2)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 71520dcd4fa9..e49d3e35e8b5 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12620,6 +12620,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
 case CPTK_IS_TRIVIALLY_COPYABLE:
   return trivially_copyable_p (type1);
 
+case CPTK_IS_UNBOUNDED_ARRAY:
+  return array_of_unknown_bound_p (type1);
+
 case CPTK_IS_UNION:
   return type_code1 == UNION_TYPE;
 
@@ -12836,6 +12839,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, 
tree type1, tree type2)
 case CPTK_IS_REFERENCE:
 case CPTK_IS_SAME:
 case CPTK_IS_SCOPED_ENUM:
+case CPTK_IS_UNBOUNDED_ARRAY:
 case CPTK_IS_UNION:
 case CPTK_IS_VOLATILE:
   break;
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index 4cbe6fe8cea4..1e10c87754a3 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -158,6 +158,9 @@
 #if !__has_builtin (__is_trivially_copyable)
 # error "__has_builtin (__is_trivially_copyable) failed"
 #endif
+#if !__has_builtin (__is_unbounded_array)
+# error "__has_builtin (__is_unbounded_array) failed"
+#endif
 #if !__has_builtin (__is_union)
 # error "__has_builtin (__is_union) failed"
 #endif
diff --git a/gcc/testsuite/g++.dg/ext/is_unbounded_array.C 
b/gcc/testsuite/g++.dg/ext/is_unbounded_array.C
new file mode 100644
index ..283a74e1a0a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_unbounded_array.C
@@ -0,0 +1,37 @@
+// { dg-do compile { target c++11 } }
+
+#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)
+
+class ClassType { };
+class IncompleteClass;
+union IncompleteUnion;
+
+SA_TEST_CATEGORY(__is_unbounded_array, int[2], false);
+SA_TEST_CATEGORY(__is_unbounded_array, int[], true);
+SA_TEST_CATEGORY(__is_unbounded_array, int[2][3], false);
+SA_TEST_CATEGORY(__is_unbounded_array, int[][3], true);
+SA_TEST_CATEGORY(__is_unbounded_array, float*[2], false);
+SA_TEST_CATEGORY(__is_unbounded_array, float*[], true);
+SA_TEST_CATEGORY(__is_unbounded_array, float*[2][3], false);
+SA_TEST_CATEGORY(__is_unbounded_array, float*[][3], true);
+SA_TEST_CATEGORY(__is_unbounded_array, ClassType[2], false);
+SA_TEST_CATEGORY(__is_unbounded_array, ClassType[], true);

[gcc r15-367] [RISC-V] Use shNadd for constant synthesis

2024-05-10 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:dbbd059b49edc936769737204f5c270d8d6ff553

commit r15-367-gdbbd059b49edc936769737204f5c270d8d6ff553
Author: Jeff Law 
Date:   Fri May 10 13:49:44 2024 -0600

[RISC-V] Use shNadd for constant synthesis

So here's the next idiom to improve constant synthesis.

The basic idea here is to try and use shNadd to generate the constant when 
profitable.

Let's take 0x30801.  Right now that generates:

li  a0,3145728
addia0,a0,1
sllia0,a0,12
addia0,a0,-2047

But we can do better.  The constant is evenly divisible by 9 resulting in
0x5639 which doesn't look terribly interesting.  But that constant can 
be
generated with two instructions, then we can use a sh3add to multiply it by 
9.
So the updated sequence looks like:

li  a0,1431654400
addia0,a0,1593
sh3add  a0,a0,a0

This doesn't trigger a whole lot, but I haven't really set up a test to 
explore
the most likely space where this might be useful.  The tests were found
exploring a different class of constant synthesis problems.

If you were to dive into the before/after you'd see that the shNadd 
interacts
quite nicely with the recent bseti work.   The joys of recursion.

Probably the most controversial thing in here is using the "FMA" opcode to
stand in for when we want to use shNadd.  Essentially when we synthesize a
constant we generate a series of RTL opcodes and constants for emission by
another routine.   We don't really have a way to say we want a shift-add.  
But
you can think of shift-add as a limited form of multiply-accumulate.  It's a
bit of a stretch, but not crazy bad IMHO.

Other approaches would be to store our own enum rather than an RTL opcode.  
Or
store an actual generator function rather than any kind of opcode.

It wouldn't take much pushback over (ab)using FMA in this manner to get me 
to
use our own enums rather than RTL opcodes for this stuff.

gcc/

* config/riscv/riscv.cc (riscv_build_integer_1): Recognize cases 
where
we can use shNadd to improve constant synthesis.
(riscv_move_integer): Handle code generation for shNadd.

gcc/testsuite
* gcc.target/riscv/synthesis-1.c: Also count shNadd instructions.
* gcc.target/riscv/synthesis-3.c: New test.

Diff:
---
 gcc/config/riscv/riscv.cc| 42 +++
 gcc/testsuite/gcc.target/riscv/synthesis-1.c |  2 +-
 gcc/testsuite/gcc.target/riscv/synthesis-3.c | 81 
 3 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 2860137af718..9c98b1da0357 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -880,6 +880,40 @@ riscv_build_integer_1 (struct riscv_integer_op 
codes[RISCV_MAX_INTEGER_OPS],
}
 }
 
+  if (cost > 2 && TARGET_64BIT && TARGET_ZBA)
+{
+  if ((value % 9) == 0
+ && (alt_cost
+ = riscv_build_integer_1 (alt_codes, value / 9, mode) + 1) < cost)
+   {
+  alt_codes[alt_cost - 1].code = FMA;
+  alt_codes[alt_cost - 1].value = 9;
+  alt_codes[alt_cost - 1].use_uw = false;
+  memcpy (codes, alt_codes, sizeof (alt_codes));
+  cost = alt_cost;
+   }
+  if ((value % 5) == 0
+ && (alt_cost
+ = riscv_build_integer_1 (alt_codes, value / 5, mode) + 1) < cost)
+   {
+  alt_codes[alt_cost - 1].code = FMA;
+  alt_codes[alt_cost - 1].value = 5;
+  alt_codes[alt_cost - 1].use_uw = false;
+  memcpy (codes, alt_codes, sizeof (alt_codes));
+  cost = alt_cost;
+   }
+  if ((value % 3) == 0
+ && (alt_cost
+ = riscv_build_integer_1 (alt_codes, value / 3, mode) + 1) < cost)
+   {
+  alt_codes[alt_cost - 1].code = FMA;
+  alt_codes[alt_cost - 1].value = 3;
+  alt_codes[alt_cost - 1].use_uw = false;
+  memcpy (codes, alt_codes, sizeof (alt_codes));
+  cost = alt_cost;
+   }
+}
+
   /* Final cases, particularly focused on bseti.  */
   if (cost > 2 && TARGET_ZBS)
 {
@@ -2542,6 +2576,14 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT 
value,
  x = gen_rtx_fmt_ee (AND, mode, x, GEN_INT (value));
  x = riscv_emit_set (t, x);
}
+ else if (codes[i].code == FMA)
+   {
+ HOST_WIDE_INT value = exact_log2 (codes[i].value - 1);
+ rtx ashift = gen_rtx_fmt_ee (ASHIFT, mode, x, GEN_INT (value));
+ x = gen_rtx_fmt_ee (PLUS, mode, ashift, x);
+ rtx t = can_create_pseudo_p () ? gen_reg_rtx (mode) : temp;
+ x = riscv_emit_set (t, x);
+   }
  else
x = gen_rtx_fmt_ee 

[gcc r15-366] i386: Improve V[48]QI shifts on AVX512/SSE4.1

2024-05-10 Thread Roger Sayle via Gcc-cvs
https://gcc.gnu.org/g:f5a8cdc1ef5d6aa2de60849c23658ac5298df7bb

commit r15-366-gf5a8cdc1ef5d6aa2de60849c23658ac5298df7bb
Author: Roger Sayle 
Date:   Fri May 10 20:26:40 2024 +0100

i386: Improve V[48]QI shifts on AVX512/SSE4.1

The following one line patch improves the code generated for V8QI and V4QI
shifts when AV512BW and AVX512VL functionality is available.

For the testcase (from gcc.target/i386/vect-shiftv8qi.c):

typedef signed char v8qi __attribute__ ((__vector_size__ (8)));
v8qi foo (v8qi x) { return x >> 5; }

GCC with -O2 -march=cascadelake currently generates:

foo:movl$67372036, %eax
vpsraw  $5, %xmm0, %xmm2
vpbroadcastd%eax, %xmm1
movl$117901063, %eax
vpbroadcastd%eax, %xmm3
vmovdqa %xmm1, %xmm0
vmovdqa %xmm3, -24(%rsp)
vpternlogd  $120, -24(%rsp), %xmm2, %xmm0
vpsubb  %xmm1, %xmm0, %xmm0
ret

with this patch we now generate the much improved:

foo:vpmovsxbw   %xmm0, %xmm0
vpsraw  $5, %xmm0, %xmm0
vpmovwb %xmm0, %xmm0
ret

This patch also fixes the FAILs of gcc.target/i386/vect-shiftv[48]qi.c
when run with the additional -march=cascadelake flag, by splitting these
tests into two; one form testing code generation with -msse2 (and
-mno-avx512vl) as originally intended, and the other testing AVX512
code generation with an explicit -march=cascadelake.

2024-05-10  Roger Sayle  
Hongtao Liu  

gcc/ChangeLog
* config/i386/i386-expand.cc (ix86_expand_vecop_qihi_partial):
Don't attempt ix86_expand_vec_shift_qihi_constant on SSE4.1.

gcc/testsuite/ChangeLog
* gcc.target/i386/vect-shiftv4qi.c: Specify -mno-avx512vl.
* gcc.target/i386/vect-shiftv8qi.c: Likewise.
* gcc.target/i386/vect-shiftv4qi-2.c: New test case.
* gcc.target/i386/vect-shiftv8qi-2.c: Likewise.

Diff:
---
 gcc/config/i386/i386-expand.cc   |  3 ++
 gcc/testsuite/gcc.target/i386/vect-shiftv4qi-2.c | 43 
 gcc/testsuite/gcc.target/i386/vect-shiftv4qi.c   |  2 +-
 gcc/testsuite/gcc.target/i386/vect-shiftv8qi-2.c | 43 
 gcc/testsuite/gcc.target/i386/vect-shiftv8qi.c   |  2 +-
 5 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 2f27bfb484c2..1ab22fe79736 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -24283,6 +24283,9 @@ ix86_expand_vecop_qihi_partial (enum rtx_code code, rtx 
dest, rtx op1, rtx op2)
 
   if (CONST_INT_P (op2)
   && (code == ASHIFT || code == LSHIFTRT || code == ASHIFTRT)
+  /* With AVX512 it's cheaper to do vpmovsxbw/op/vpmovwb.
+ Even with SSE4.1 the alternative is better.  */
+  && !TARGET_SSE4_1
   && ix86_expand_vec_shift_qihi_constant (code, qdest, qop1, qop2))
 {
   emit_move_insn (dest, gen_lowpart (qimode, qdest));
diff --git a/gcc/testsuite/gcc.target/i386/vect-shiftv4qi-2.c 
b/gcc/testsuite/gcc.target/i386/vect-shiftv4qi-2.c
new file mode 100644
index ..abc1a276b043
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-shiftv4qi-2.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=cascadelake" } */
+
+#define N 4
+
+typedef unsigned char __vu __attribute__ ((__vector_size__ (N)));
+typedef signed char __vi __attribute__ ((__vector_size__ (N)));
+
+__vu sll (__vu a, int n)
+{
+  return a << n;
+}
+
+__vu sll_c (__vu a)
+{
+  return a << 5;
+}
+
+/* { dg-final { scan-assembler-times "vpsllw" 2 } } */
+
+__vu srl (__vu a, int n)
+{
+  return a >> n;
+}
+
+__vu srl_c (__vu a)
+{
+  return a >> 5;
+}
+
+/* { dg-final { scan-assembler-times "vpsrlw" 2 } } */
+
+__vi sra (__vi a, int n)
+{
+  return a >> n;
+}
+
+__vi sra_c (__vi a)
+{
+  return a >> 5;
+}
+
+/* { dg-final { scan-assembler-times "vpsraw" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-shiftv4qi.c 
b/gcc/testsuite/gcc.target/i386/vect-shiftv4qi.c
index b7e45c2e8799..9b52582d01f8 100644
--- a/gcc/testsuite/gcc.target/i386/vect-shiftv4qi.c
+++ b/gcc/testsuite/gcc.target/i386/vect-shiftv4qi.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -msse2" } */
+/* { dg-options "-O2 -msse2 -mno-avx2 -mno-avx512vl" } */
 
 #define N 4
 
diff --git a/gcc/testsuite/gcc.target/i386/vect-shiftv8qi-2.c 
b/gcc/testsuite/gcc.target/i386/vect-shiftv8qi-2.c
new file mode 100644
index ..52760f5a0607
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-shiftv8qi-2.c
@@ -0,0 +1,43 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -march=cascadelake" } */
+
+#define N 8
+
+typedef unsigned char __vu __attribute__ ((__vector_size__ (N)));
+typedef signed char __vi __attribute__ ((__vector_size__ (N)));
+

[gcc r15-365] pru: Fix register class checks in predicates

2024-05-10 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:d4d30461c02b50c07f92c8cccb87da528a806d3e

commit r15-365-gd4d30461c02b50c07f92c8cccb87da528a806d3e
Author: Dimitar Dimitrov 
Date:   Thu May 9 22:19:24 2024 +0300

pru: Fix register class checks in predicates

The register class checks in the multiply-source predicates was
incorrectly using the register number instead of the register
class for comparison.

gcc/ChangeLog:

* config/pru/predicates.md (pru_mulsrc0_operand): Use register
class instead of register number for the check.
(pru_mulsrc1_operand): Ditto.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/predicates.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/config/pru/predicates.md b/gcc/config/pru/predicates.md
index 77b3316b98ee..55635599609b 100644
--- a/gcc/config/pru/predicates.md
+++ b/gcc/config/pru/predicates.md
@@ -103,7 +103,7 @@
   else
return 0;
 
-  return REGNO_REG_CLASS (regno) == MULSRC0_REGNUM
+  return REGNO_REG_CLASS (regno) == MULSRC0_REGS
 || regno >= FIRST_PSEUDO_REGISTER;
 }
   return 0;
@@ -123,7 +123,7 @@
   else
return 0;
 
-  return REGNO_REG_CLASS (regno) == MULSRC1_REGNUM
+  return REGNO_REG_CLASS (regno) == MULSRC1_REGS
 || regno >= FIRST_PSEUDO_REGISTER;
 }
   return 0;


[gcc r15-364] [PR114942][LRA]: Don't reuse input reload reg of inout early clobber operand

2024-05-10 Thread Vladimir Makarov via Gcc-cvs
https://gcc.gnu.org/g:9585317f0715699197b1313bbf939c6ea3c1ace6

commit r15-364-g9585317f0715699197b1313bbf939c6ea3c1ace6
Author: Vladimir N. Makarov 
Date:   Fri May 10 09:15:50 2024 -0400

[PR114942][LRA]: Don't reuse input reload reg of inout early clobber operand

  The insn in question has the same reg in inout operand and input
operand.  The inout operand is early clobber.  LRA reused input reload
reg of the inout operand for the input operand which is wrong.  It
were a good decision if the inout operand was not early clobber one.
The patch rejects the reuse for the PR test case.

gcc/ChangeLog:

PR target/114942
* lra-constraints.cc (struct input_reload): Add new member 
early_clobber_p.
(get_reload_reg): Add new arg early_clobber_p, don't reuse input
reload with true early_clobber_p member value, use the arg for new
element of curr_insn_input_reloads.
(match_reload): Assign false to early_clobber_p member.
(process_addr_reg, simplify_operand_subreg, curr_insn_transform):
Adjust get_reload_reg calls.

gcc/testsuite/ChangeLog:

PR target/114942
* gcc.target/i386/pr114942.c: New.

Diff:
---
 gcc/lra-constraints.cc   | 27 +++
 gcc/testsuite/gcc.target/i386/pr114942.c | 24 
 2 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 5b78fd0b7e5c..e945a4da4519 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -599,6 +599,8 @@ struct input_reload
 {
   /* True for input reload of matched operands.  */
   bool match_p;
+  /* True for input reload of inout earlyclobber operand.  */
+  bool early_clobber_p;
   /* Reloaded value.  */
   rtx input;
   /* Reload pseudo used.  */
@@ -649,13 +651,15 @@ canonicalize_reload_addr (rtx addr)
 /* Create a new pseudo using MODE, RCLASS, EXCLUDE_START_HARD_REGS, ORIGINAL or
reuse an existing reload pseudo.  Don't reuse an existing reload pseudo if
IN_SUBREG_P is true and the reused pseudo should be wrapped up in a SUBREG.
+   EARLY_CLOBBER_P is true for input reload of inout early clobber operand.
The result pseudo is returned through RESULT_REG.  Return TRUE if we created
a new pseudo, FALSE if we reused an existing reload pseudo.  Use TITLE to
describe new registers for debug purposes.  */
 static bool
 get_reload_reg (enum op_type type, machine_mode mode, rtx original,
enum reg_class rclass, HARD_REG_SET *exclude_start_hard_regs,
-   bool in_subreg_p, const char *title, rtx *result_reg)
+   bool in_subreg_p, bool early_clobber_p,
+   const char *title, rtx *result_reg)
 {
   int i, regno;
   enum reg_class new_class;
@@ -703,6 +707,7 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx 
original,
 for (i = 0; i < curr_insn_input_reloads_num; i++)
   {
if (! curr_insn_input_reloads[i].match_p
+   && ! curr_insn_input_reloads[i].early_clobber_p
&& rtx_equal_p (curr_insn_input_reloads[i].input, original)
&& in_class_p (curr_insn_input_reloads[i].reg, rclass, _class))
  {
@@ -750,6 +755,8 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx 
original,
   lra_assert (curr_insn_input_reloads_num < LRA_MAX_INSN_RELOADS);
   curr_insn_input_reloads[curr_insn_input_reloads_num].input = original;
   curr_insn_input_reloads[curr_insn_input_reloads_num].match_p = false;
+  curr_insn_input_reloads[curr_insn_input_reloads_num].early_clobber_p
+= early_clobber_p;
   curr_insn_input_reloads[curr_insn_input_reloads_num++].reg = *result_reg;
   return true;
 }
@@ -1189,6 +1196,7 @@ match_reload (signed char out, signed char *ins, signed 
char *outs,
   lra_assert (curr_insn_input_reloads_num < LRA_MAX_INSN_RELOADS);
   curr_insn_input_reloads[curr_insn_input_reloads_num].input = in_rtx;
   curr_insn_input_reloads[curr_insn_input_reloads_num].match_p = true;
+  curr_insn_input_reloads[curr_insn_input_reloads_num].early_clobber_p = false;
   curr_insn_input_reloads[curr_insn_input_reloads_num++].reg = new_in_reg;
   for (i = 0; (in = ins[i]) >= 0; i++)
 if (GET_MODE (*curr_id->operand_loc[in]) == VOIDmode
@@ -1577,7 +1585,7 @@ process_addr_reg (rtx *loc, bool check_only_p, rtx_insn 
**before, rtx_insn **aft
  reg = *loc;
  if (get_reload_reg (after == NULL ? OP_IN : OP_INOUT,
  mode, reg, cl, NULL,
- subreg_p, "address", _reg))
+ subreg_p, false, "address", _reg))
before_p = true;
}
   else if (new_class != NO_REGS && rclass != new_class)
@@ -1733,7 +1741,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
= (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS);
  if 

[gcc r15-363] [prange] Fix thinko in prange::update_bitmask() [PR115026]

2024-05-10 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:cbd420a1c3e2bb549dc83b53cc9a31aa6b23952c

commit r15-363-gcbd420a1c3e2bb549dc83b53cc9a31aa6b23952c
Author: Aldy Hernandez 
Date:   Fri May 10 12:26:49 2024 +0200

[prange] Fix thinko in prange::update_bitmask() [PR115026]

gcc/ChangeLog:

PR tree-optimization/115026
* value-range.cc (prange::update_bitmask): Use operand bitmask.

Diff:
---
 gcc/value-range.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 3e1ecf69517c..5bcb2c3f650b 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -686,7 +686,7 @@ prange::update_bitmask (const irange_bitmask )
   // If all the bits are known, this is a singleton.
   if (bm.mask () == 0)
 {
-  set (type (), m_bitmask.value (), m_bitmask.value ());
+  set (type (), bm.value (), bm.value ());
   return;
 }


[gcc r11-11433] libstdc++: Silence irrelevant warnings in

2024-05-10 Thread Matthias Kretz via Gcc-cvs
https://gcc.gnu.org/g:6679ea120ee06355ba309c53604b23909d325b98

commit r11-11433-g6679ea120ee06355ba309c53604b23909d325b98
Author: Matthias Kretz 
Date:   Wed Apr 17 10:35:47 2024 +0200

libstdc++: Silence irrelevant warnings in 

Avoid
-Wnarrowing in C code;
-Wtautological-compare in unconditional static_assert (necessary for
faking a dependency on a template parameter)

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

* include/experimental/bits/simd.h: Ignore -Wnarrowing for
arm_neon.h.
(__int_for_sizeof): Replace tautological compare with checking
for invalid template parameter value.
* include/experimental/bits/simd_builtin.h (__extract_part):
Remove tautological compare by combining two static_assert.

(cherry picked from commit e7a3ad29c9c832b6ae999cbfb0af89e121959030)

Diff:
---
 libstdc++-v3/include/experimental/bits/simd.h | 8 +++-
 libstdc++-v3/include/experimental/bits/simd_builtin.h | 3 +--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd.h 
b/libstdc++-v3/include/experimental/bits/simd.h
index 248237731268..56ec9dd4a84d 100644
--- a/libstdc++-v3/include/experimental/bits/simd.h
+++ b/libstdc++-v3/include/experimental/bits/simd.h
@@ -42,7 +42,12 @@
 #if _GLIBCXX_SIMD_X86INTRIN
 #include 
 #elif _GLIBCXX_SIMD_HAVE_NEON
+#pragma GCC diagnostic push
+// narrowing conversion of '__a' from 'uint64_t' {aka 'long long unsigned 
int'} to
+//   'int64x1_t' {aka 'long long int'} [-Wnarrowing]
+#pragma GCC diagnostic ignored "-Wnarrowing"
 #include 
+#pragma GCC diagnostic pop
 #endif
 
 /** @ingroup ts_simd
@@ -385,6 +390,7 @@ template 
   constexpr auto
   __int_for_sizeof()
   {
+static_assert(_Bytes > 0);
 if constexpr (_Bytes == sizeof(int))
   return int();
   #ifdef __clang__
@@ -450,7 +456,7 @@ template 
return _Ip{};
   }
 else
-  static_assert(_Bytes != _Bytes, "this should be unreachable");
+  static_assert(_Bytes == 0, "this should be unreachable");
   }
 #pragma GCC diagnostic pop
 
diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h 
b/libstdc++-v3/include/experimental/bits/simd_builtin.h
index 9703012a6d95..42e894ac3b0b 100644
--- a/libstdc++-v3/include/experimental/bits/simd_builtin.h
+++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h
@@ -276,8 +276,7 @@ template 
   __extract_part(const _SimdWrapper __x)
   {
 static_assert(_Combine == 1, "_Combine != 1 not implemented");
-static_assert(__have_avx512f && _Np == _Np);
-static_assert(_Total >= 2 && _Index + _Combine <= _Total && _Index >= 0);
+static_assert(__have_avx512f && _Total >= 2 && _Index + _Combine <= _Total 
&& _Index >= 0);
 return __x._M_data >> (_Index * _Np / _Total);
   }


[gcc r11-11431] libstdc++: Avoid ill-formed types on ARM

2024-05-10 Thread Matthias Kretz via Libstdc++-cvs
https://gcc.gnu.org/g:fb2f4a191cc74b6ab2899798db8a59a9b2a3f23f

commit r11-11431-gfb2f4a191cc74b6ab2899798db8a59a9b2a3f23f
Author: Matthias Kretz 
Date:   Wed Apr 17 09:11:25 2024 +0200

libstdc++: Avoid ill-formed types on ARM

This resolves failing tests in check-simd.

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

PR libstdc++/114750
* include/experimental/bits/simd_builtin.h
(_SimdImplBuiltin::_S_load, _S_store): Fall back to copying
scalars if the memory type cannot be vectorized for the target.

(cherry picked from commit 0fc7f3c6adc8543f55ec35b309016d9d9c4ddd35)

Diff:
---
 libstdc++-v3/include/experimental/bits/simd_builtin.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h 
b/libstdc++-v3/include/experimental/bits/simd_builtin.h
index 9c8094d70167..9703012a6d95 100644
--- a/libstdc++-v3/include/experimental/bits/simd_builtin.h
+++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h
@@ -1460,7 +1460,7 @@ template 
   [&](auto __i) constexpr {
 return static_cast<_Tp>(__i < _Np ? __mem[__i] : 0);
   });
-   else if constexpr (sizeof(_Up) > 8)
+   else if constexpr (sizeof(_Up) > 8 or __vectorized_sizeof<_Up>() <= 
sizeof(_Up))
  return __generate_vector<_Tp, _SimdMember<_Tp>::_S_full_size>(
   [&](auto __i) constexpr _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
 return static_cast<_Tp>(__i < _Np ? __mem[__i] : 0);
@@ -1532,7 +1532,7 @@ template 
for (size_t __i = 0; __i < _Np; ++__i)
  __mem[__i] = __v[__i];
  }
-   else if constexpr (sizeof(_Up) > 8)
+   else if constexpr (sizeof(_Up) > 8 or __vectorized_sizeof<_Up>() <= 
sizeof(_Up))
  __execute_n_times<_Np>([&](auto __i) constexpr 
_GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
__mem[__i] = __v[__i];
  });


[gcc r11-11430] libstdc++: Add masked ++/-- implementation for sizeof < 16

2024-05-10 Thread Matthias Kretz via Gcc-cvs
https://gcc.gnu.org/g:dcd598817c1b3c62d782f568ce63e37566228a58

commit r11-11430-gdcd598817c1b3c62d782f568ce63e37566228a58
Author: Matthias Kretz 
Date:   Wed Mar 27 13:41:25 2024 +0100

libstdc++: Add masked ++/-- implementation for sizeof < 16

This resolves further failures (-Wreturn-type warnings) and test
failures for where-* tests targeting AVX-512.

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

* include/experimental/bits/simd_x86.h (_S_masked_unary):
Cast inputs < 16 bytes to 16 byte vectors before calling the
right subtraction builtin. Before returning, truncate to the
return vector type.

(cherry picked from commit a6c630c314b099f64d79055964d88b257459cf13)

Diff:
---
 libstdc++-v3/include/experimental/bits/simd_x86.h | 24 +--
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd_x86.h 
b/libstdc++-v3/include/experimental/bits/simd_x86.h
index fb0d6977832a..6883ab83f962 100644
--- a/libstdc++-v3/include/experimental/bits/simd_x86.h
+++ b/libstdc++-v3/include/experimental/bits/simd_x86.h
@@ -3507,6 +3507,9 @@ template 
 #ifdef __clang__
return __movm<_Np, _Tp>(__k._M_data) ? __v._M_data - __pm_one : 
__v._M_data;
 #else // __clang__
+   using _TV = __vector_type_t<_Tp, _Np>;
+   constexpr size_t __bytes = sizeof(__v) < 16 ? 16 : sizeof(__v);
+   constexpr size_t __width = __bytes / sizeof(_Tp);
if constexpr (is_integral_v<_Tp>)
  {
constexpr bool __lp64 = sizeof(long) == sizeof(long long);
@@ -3516,11 +3519,11 @@ template 
  std::conditional_t<__lp64, long long, int>,
  std::conditional_t<
std::is_same_v<_Ip, signed char>, char, _Ip>>;
-   const auto __value = __vector_bitcast<_Up>(__v._M_data);
+   const auto __value = __intrin_bitcast<__vector_type_t<_Up, 
__width>>(__v._M_data);
 #define _GLIBCXX_SIMD_MASK_SUB(_Sizeof, _Width, _Instr)
\
-  if constexpr (sizeof(_Tp) == _Sizeof && sizeof(__v) == _Width)   
\
-return __vector_bitcast<_Tp>(__builtin_ia32_##_Instr##_mask(__value,   
\
-__vector_broadcast<_Np>(_Up(__pm_one)), __value, __k._M_data))
+  if constexpr (sizeof(_Tp) == _Sizeof && sizeof(__value) == _Width)   
\
+return __intrin_bitcast<_TV>(__builtin_ia32_##_Instr##_mask(__value,   
\
+__vector_broadcast<__width>(_Up(__pm_one)), __value, __k._M_data))
_GLIBCXX_SIMD_MASK_SUB(1, 64, psubb512);
_GLIBCXX_SIMD_MASK_SUB(1, 32, psubb256);
_GLIBCXX_SIMD_MASK_SUB(1, 16, psubb128);
@@ -3537,16 +3540,17 @@ template 
  }
else
  {
+   const auto __value = __intrin_bitcast<__vector_type_t<_Tp, 
__width>>(__v._M_data);
 #define _GLIBCXX_SIMD_MASK_SUB_512(_Sizeof, _Width, _Instr)
\
-  if constexpr (sizeof(_Tp) == _Sizeof && sizeof(__v) == _Width)   
\
+  if constexpr (sizeof(_Tp) == _Sizeof && sizeof(__value) == _Width)   
\
 return __builtin_ia32_##_Instr##_mask( 
\
-__v._M_data, __vector_broadcast<_Np>(_Tp(__pm_one)), __v._M_data, \
+__value, __vector_broadcast<__width>(_Tp(__pm_one)), __value, \
 __k._M_data, _MM_FROUND_CUR_DIRECTION)
 #define _GLIBCXX_SIMD_MASK_SUB(_Sizeof, _Width, _Instr)
\
-  if constexpr (sizeof(_Tp) == _Sizeof && sizeof(__v) == _Width)   
\
-return __builtin_ia32_##_Instr##_mask( 
\
-__v._M_data, __vector_broadcast<_Np>(_Tp(__pm_one)), __v._M_data, \
-__k._M_data)
+  if constexpr (sizeof(_Tp) == _Sizeof && sizeof(__value) == _Width)   
\
+return __intrin_bitcast<_TV>(__builtin_ia32_##_Instr##_mask(   
\
+__value, __vector_broadcast<__width>(_Tp(__pm_one)), __value, \
+__k._M_data))
_GLIBCXX_SIMD_MASK_SUB_512(4, 64, subps512);
_GLIBCXX_SIMD_MASK_SUB(4, 32, subps256);
_GLIBCXX_SIMD_MASK_SUB(4, 16, subps128);


[gcc r11-11434] libstdc++: Fix conversion of simd to vector builtin

2024-05-10 Thread Matthias Kretz via Libstdc++-cvs
https://gcc.gnu.org/g:9e3663ba96df1315f53b4b488f4c2e63633c7b2f

commit r11-11434-g9e3663ba96df1315f53b4b488f4c2e63633c7b2f
Author: Matthias Kretz 
Date:   Mon Apr 22 16:12:34 2024 +0200

libstdc++: Fix conversion of simd to vector builtin

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

PR libstdc++/114803
* include/experimental/bits/simd_builtin.h
(_SimdBase2::operator __vector_type_t): There is no __builtin()
function in _SimdWrapper, instead use its conversion operator.
* testsuite/experimental/simd/pr114803_vecbuiltin_cvt.cc: New
test.

(cherry picked from commit 7ef139146a8923a8719873ca3fdae175668e8d63)

Diff:
---
 .../include/experimental/bits/simd_builtin.h   |   2 +-
 .../experimental/simd/pr114803_vecbuiltin_cvt.cc   | 105 +
 2 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h 
b/libstdc++-v3/include/experimental/bits/simd_builtin.h
index 42e894ac3b0b..65a8a8886618 100644
--- a/libstdc++-v3/include/experimental/bits/simd_builtin.h
+++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h
@@ -839,7 +839,7 @@ template 
 
   explicit
   operator __vector_type_t<_Tp, _Np>() const
-  { return static_cast*>(this)->_M_data.__builtin(); 
}
+  { return __data(*static_cast*>(this)); }
 };
 
 struct _SimdBase1
diff --git 
a/libstdc++-v3/testsuite/experimental/simd/pr114803_vecbuiltin_cvt.cc 
b/libstdc++-v3/testsuite/experimental/simd/pr114803_vecbuiltin_cvt.cc
new file mode 100644
index ..103dd19394c1
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/pr114803_vecbuiltin_cvt.cc
@@ -0,0 +1,105 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include 
+
+template 
+  void
+  maybe_test()
+  {
+using V = std::experimental::simd>;
+if constexpr (std::is_destructible_v)
+  {
+   using V2 [[gnu::vector_size(16)]] = T;
+   V x = {};
+   V2 x2 = static_cast(x);
+   x = static_cast(x2);
+   for (unsigned i = 0; i < V::size(); ++i)
+ {
+   if (x2[i] != 0)
+ __builtin_abort();
+ }
+#ifdef __SSE__
+   if constexpr (std::is_same_v)
+ x = static_cast(static_cast<__m128>(x));
+   else if constexpr (std::is_same_v)
+ x = static_cast(static_cast<__m128d>(x));
+   else if constexpr (std::is_integral_v)
+ x = static_cast(static_cast<__m128i>(x));
+#elif __ALTIVEC__
+   if constexpr (std::is_same_v)
+ x = static_cast(static_cast<__vector float>(x));
+#ifdef __VSX__
+   else if constexpr (std::is_same_v)
+ x = static_cast(static_cast<__vector double>(x));
+#endif
+   else if constexpr (std::is_integral_v && sizeof(T) == sizeof(signed 
char)
+&& std::is_signed_v)
+ x = static_cast(static_cast<__vector signed char>(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == sizeof(signed 
char))
+ x = static_cast(static_cast<__vector unsigned char>(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == sizeof(short)
+&& std::is_signed_v)
+ x = static_cast(static_cast<__vector signed short>(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == sizeof(short))
+ x = static_cast(static_cast<__vector unsigned short>(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == sizeof(int)
+&& std::is_signed_v)
+ x = static_cast(static_cast<__vector signed int>(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == sizeof(int))
+ x = static_cast(static_cast<__vector unsigned int>(x));
+#ifdef __VSX__
+   else if constexpr (std::is_integral_v && sizeof(T) == sizeof(long 
long)
+&& std::is_signed_v)
+ x = static_cast(static_cast<__vector signed long long>(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == sizeof(long 
long))
+ x = static_cast(static_cast<__vector unsigned long long>(x));
+#endif
+#elif __ARM_NEON
+   if constexpr (std::is_same_v)
+ x = static_cast(static_cast(x));
+#ifdef __aarch64__
+   else if constexpr (std::is_same_v)
+ x = static_cast(static_cast(x));
+#endif
+   else if constexpr (std::is_integral_v && sizeof(T) == 1 && 
std::is_signed_v)
+ x = static_cast(static_cast(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == 1)
+ x = static_cast(static_cast(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == 2 && 
std::is_signed_v)
+ x = static_cast(static_cast(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == 2)
+ x = static_cast(static_cast(x));
+   else if constexpr (std::is_integral_v && sizeof(T) == 4 && 
std::is_signed_v)
+ x = 

[gcc r11-11432] libstdc++: Add include guard to simd-internal header

2024-05-10 Thread Matthias Kretz via Libstdc++-cvs
https://gcc.gnu.org/g:ef919c8c6d5fe65c56279261c08f9033c4b449cd

commit r11-11432-gef919c8c6d5fe65c56279261c08f9033c4b449cd
Author: Matthias Kretz 
Date:   Wed Apr 17 10:12:42 2024 +0200

libstdc++: Add include guard to simd-internal header

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

* include/experimental/bits/numeric_traits.h: Add include guard.

(cherry picked from commit 3cfe94ad28102618c14a91c0a83d9e5cc7df69d7)

Diff:
---
 libstdc++-v3/include/experimental/bits/numeric_traits.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/libstdc++-v3/include/experimental/bits/numeric_traits.h 
b/libstdc++-v3/include/experimental/bits/numeric_traits.h
index 0a1c711a559b..fd6ad761fb3d 100644
--- a/libstdc++-v3/include/experimental/bits/numeric_traits.h
+++ b/libstdc++-v3/include/experimental/bits/numeric_traits.h
@@ -22,6 +22,9 @@
 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 // .
 
+#ifndef _GLIBCXX_EXPERIMENTAL_BITS_NUMERIC_TRAITS_H
+#define _GLIBCXX_EXPERIMENTAL_BITS_NUMERIC_TRAITS_H
+
 #include 
 
 namespace std {
@@ -565,3 +568,4 @@ template <>
 #endif // __FINITE_MATH_ONLY__
 
 } // namespace std
+#endif  // _GLIBCXX_EXPERIMENTAL_BITS_NUMERIC_TRAITS_H


[gcc r11-11429] libstdc++: Fix call signature of builtins from masked ++/--

2024-05-10 Thread Matthias Kretz via Gcc-cvs
https://gcc.gnu.org/g:f0b7583dab56c78824344e00eb6230eaaeb09a44

commit r11-11429-gf0b7583dab56c78824344e00eb6230eaaeb09a44
Author: Matthias Kretz 
Date:   Wed Mar 27 08:49:43 2024 +0100

libstdc++: Fix call signature of builtins from masked ++/--

This resolves failures in the "expensive" where-* test of check-simd
when targeting AVX-512.

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

* include/experimental/bits/simd_x86.h (_S_masked_unary): Call
the 4- and 8-byte variants of __builtin_ia32_subp[ds] without
rounding direction argument.

(cherry picked from commit 0ac2c0f0687b321ab54de271d788b4e0a287b4e2)

Diff:
---
 libstdc++-v3/include/experimental/bits/simd_x86.h | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd_x86.h 
b/libstdc++-v3/include/experimental/bits/simd_x86.h
index 2e7ea238811c..fb0d6977832a 100644
--- a/libstdc++-v3/include/experimental/bits/simd_x86.h
+++ b/libstdc++-v3/include/experimental/bits/simd_x86.h
@@ -3537,17 +3537,23 @@ template 
  }
else
  {
-#define _GLIBCXX_SIMD_MASK_SUB(_Sizeof, _Width, _Instr)
\
+#define _GLIBCXX_SIMD_MASK_SUB_512(_Sizeof, _Width, _Instr)
\
   if constexpr (sizeof(_Tp) == _Sizeof && sizeof(__v) == _Width)   
\
 return __builtin_ia32_##_Instr##_mask( 
\
 __v._M_data, __vector_broadcast<_Np>(_Tp(__pm_one)), __v._M_data, \
 __k._M_data, _MM_FROUND_CUR_DIRECTION)
-   _GLIBCXX_SIMD_MASK_SUB(4, 64, subps512);
+#define _GLIBCXX_SIMD_MASK_SUB(_Sizeof, _Width, _Instr)
\
+  if constexpr (sizeof(_Tp) == _Sizeof && sizeof(__v) == _Width)   
\
+return __builtin_ia32_##_Instr##_mask( 
\
+__v._M_data, __vector_broadcast<_Np>(_Tp(__pm_one)), __v._M_data, \
+__k._M_data)
+   _GLIBCXX_SIMD_MASK_SUB_512(4, 64, subps512);
_GLIBCXX_SIMD_MASK_SUB(4, 32, subps256);
_GLIBCXX_SIMD_MASK_SUB(4, 16, subps128);
-   _GLIBCXX_SIMD_MASK_SUB(8, 64, subpd512);
+   _GLIBCXX_SIMD_MASK_SUB_512(8, 64, subpd512);
_GLIBCXX_SIMD_MASK_SUB(8, 32, subpd256);
_GLIBCXX_SIMD_MASK_SUB(8, 16, subpd128);
+#undef _GLIBCXX_SIMD_MASK_SUB_512
 #undef _GLIBCXX_SIMD_MASK_SUB
  }
 #endif // __clang__


[gcc r11-11428] libstdc++: Avoid vector casts while still avoiding PR90424

2024-05-10 Thread Matthias Kretz via Libstdc++-cvs
https://gcc.gnu.org/g:4190a95cb837c5d221d9c5677f49f3c7d4d5576f

commit r11-11428-g4190a95cb837c5d221d9c5677f49f3c7d4d5576f
Author: Matthias Kretz 
Date:   Fri Jun 2 21:33:04 2023 +0200

libstdc++: Avoid vector casts while still avoiding PR90424

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

PR libstdc++/109822
* include/experimental/bits/simd_builtin.h (_S_store): Rewrite
to avoid casts to other vector types. Implement store as
succession of power-of-2 sized memcpy to avoid PR90424.

(cherry picked from commit 9165ede56ababd6471e7a2ce4eab30f3d5129e14)

Diff:
---
 .../include/experimental/bits/simd_builtin.h   | 40 --
 1 file changed, 15 insertions(+), 25 deletions(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h 
b/libstdc++-v3/include/experimental/bits/simd_builtin.h
index 9cdef60b85b2..9c8094d70167 100644
--- a/libstdc++-v3/include/experimental/bits/simd_builtin.h
+++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h
@@ -1291,6 +1291,18 @@ struct _CommonImplBuiltin
 
   // }}}
   // _S_store {{{
+  template 
+_GLIBCXX_SIMD_INTRINSIC static void
+_S_memcpy(char* __dst, const char* __src)
+{
+  if constexpr (_Bytes > 0)
+   {
+ constexpr size_t _Ns = std::__bit_floor(_Bytes);
+ __builtin_memcpy(__dst, __src, _Ns);
+ _S_memcpy<_Bytes - _Ns>(__dst + _Ns, __src + _Ns);
+   }
+}
+
   template 
 _GLIBCXX_SIMD_INTRINSIC static void
 _S_store(_TV __x, void* __addr)
@@ -1298,33 +1310,11 @@ struct _CommonImplBuiltin
   constexpr size_t _Bytes = _ReqBytes == 0 ? sizeof(__x) : _ReqBytes;
   static_assert(sizeof(__x) >= _Bytes);
 
+#if !defined __clang__ && _GLIBCXX_SIMD_WORKAROUND_PR90424
   if constexpr (__is_vector_type_v<_TV>)
-   {
- using _Tp = typename _VectorTraits<_TV>::value_type;
- constexpr size_t _Np = _Bytes / sizeof(_Tp);
- static_assert(_Np * sizeof(_Tp) == _Bytes);
-
-#ifdef _GLIBCXX_SIMD_WORKAROUND_PR90424
- using _Up = conditional_t<
-   (is_integral_v<_Tp> || _Bytes < 4),
-   conditional_t<(sizeof(__x) > sizeof(long long)), long long, _Tp>,
-   float>;
- const auto __v = __vector_bitcast<_Up>(__x);
-#else // _GLIBCXX_SIMD_WORKAROUND_PR90424
- const __vector_type_t<_Tp, _Np> __v = __x;
-#endif // _GLIBCXX_SIMD_WORKAROUND_PR90424
-
- if constexpr ((_Bytes & (_Bytes - 1)) != 0)
-   {
- constexpr size_t _MoreBytes = std::__bit_ceil(_Bytes);
- alignas(decltype(__v)) char __tmp[_MoreBytes];
- __builtin_memcpy(__tmp, &__v, _MoreBytes);
- __builtin_memcpy(__addr, __tmp, _Bytes);
-   }
- else
-   __builtin_memcpy(__addr, &__v, _Bytes);
-   }
+   _S_memcpy<_Bytes>(reinterpret_cast(__addr), 
reinterpret_cast(&__x));
   else
+#endif // _GLIBCXX_SIMD_WORKAROUND_PR90424
__builtin_memcpy(__addr, &__x, _Bytes);
 }


[gcc r11-11427] libstdc++: Replace use of incorrect non-temporal store

2024-05-10 Thread Matthias Kretz via Libstdc++-cvs
https://gcc.gnu.org/g:db0c654ae689e92d8ba0421815a820278b777b06

commit r11-11427-gdb0c654ae689e92d8ba0421815a820278b777b06
Author: Matthias Kretz 
Date:   Fri Jun 2 13:44:22 2023 +0200

libstdc++: Replace use of incorrect non-temporal store

The call to the base implementation sometimes didn't find a matching
signature because the _Abi parameter of _SimdImpl* was "wrong" after
conversion. It has to call into ::_SimdImpl instead of the
current ABI tag's _SimdImpl. This also reduces the number of possible
template instantiations.

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

PR libstdc++/110054
* include/experimental/bits/simd_builtin.h (_S_masked_store):
Call into deduced ABI's SimdImpl after conversion.
* include/experimental/bits/simd_x86.h (_S_masked_store_nocvt):
Don't use _mm_maskmoveu_si128. Use the generic fall-back
implementation. Also fix masked stores without SSE2, which
were not doing anything before.

(cherry picked from commit 27e45b7597d6fb1a71927d658a0294797b720c0a)

Diff:
---
 .../include/experimental/bits/simd_builtin.h   |  6 ++--
 libstdc++-v3/include/experimental/bits/simd_x86.h  | 38 +++---
 2 files changed, 7 insertions(+), 37 deletions(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h 
b/libstdc++-v3/include/experimental/bits/simd_builtin.h
index 7c272c178e55..9cdef60b85b2 100644
--- a/libstdc++-v3/include/experimental/bits/simd_builtin.h
+++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h
@@ -1624,7 +1624,7 @@ template 
if constexpr (_UW_size == _TV_size) // one convert+store
  {
const _UW __converted = __convert<_UW>(__v);
-   _SuperImpl::_S_masked_store_nocvt(
+   _UAbi::_SimdImpl::_S_masked_store_nocvt(
  __converted, __mem,
  _UAbi::_MaskImpl::template _S_convert<
__int_for_sizeof_t<_Up>>(__k));
@@ -1639,7 +1639,7 @@ template 
const array<_UV, _NAllStores> __converted
  = __convert_all<_UV, _NAllStores>(__v);
__execute_n_times<_NFullStores>([&](auto __i) 
_GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
- _SuperImpl::_S_masked_store_nocvt(
+ _UAbi::_SimdImpl::_S_masked_store_nocvt(
_UW(__converted[__i]), __mem + __i * _UW_size,
_UAbi::_MaskImpl::template _S_convert<
  __int_for_sizeof_t<_Up>>(
@@ -1647,7 +1647,7 @@ template 
});
if constexpr (_NAllStores
  > _NFullStores) // one partial at the end
- _SuperImpl::_S_masked_store_nocvt(
+ _UAbi::_SimdImpl::_S_masked_store_nocvt(
_UW(__converted[_NFullStores]),
__mem + _NFullStores * _UW_size,
_UAbi::_MaskImpl::template _S_convert<
diff --git a/libstdc++-v3/include/experimental/bits/simd_x86.h 
b/libstdc++-v3/include/experimental/bits/simd_x86.h
index 0b86927ab6e4..2e7ea238811c 100644
--- a/libstdc++-v3/include/experimental/bits/simd_x86.h
+++ b/libstdc++-v3/include/experimental/bits/simd_x86.h
@@ -1106,31 +1106,6 @@ template 
else
  _mm512_mask_storeu_pd(__mem, __k, __vi);
  }
-#if 0 // with KNL either sizeof(_Tp) >= 4 or sizeof(_vi) <= 32
-  // with Skylake-AVX512, __have_avx512bw is true
- else if constexpr (__have_sse2)
-   {
- using _M   = __vector_type_t<_Tp, _Np>;
- using _MVT = _VectorTraits<_M>;
- _mm_maskmoveu_si128(__auto_bitcast(__extract<0, 4>(__v._M_data)),
- __auto_bitcast(_MaskImpl::template 
_S_convert<_Tp, _Np>(__k._M_data)),
- reinterpret_cast(__mem));
- _mm_maskmoveu_si128(__auto_bitcast(__extract<1, 4>(__v._M_data)),
- __auto_bitcast(_MaskImpl::template 
_S_convert<_Tp, _Np>(
-   __k._M_data >> 1 * _MVT::_S_full_size)),
- reinterpret_cast(__mem) + 1 * 16);
- _mm_maskmoveu_si128(__auto_bitcast(__extract<2, 4>(__v._M_data)),
- __auto_bitcast(_MaskImpl::template 
_S_convert<_Tp, _Np>(
-   __k._M_data >> 2 * _MVT::_S_full_size)),
- reinterpret_cast(__mem) + 2 * 16);
- if constexpr (_Np > 48 / sizeof(_Tp))
-   _mm_maskmoveu_si128(
- __auto_bitcast(__extract<3, 4>(__v._M_data)),
- __auto_bitcast(_MaskImpl::template _S_convert<_Tp, _Np>(
-   __k._M_data >> 3 * _MVT::_S_full_size)),
- reinterpret_cast(__mem) + 3 * 16);
-   }
-#endif
else
  

[gcc r11-11426] libstdc++: Protect against macros

2024-05-10 Thread Matthias Kretz via Gcc-cvs
https://gcc.gnu.org/g:fdd2a21a53facecc8e2b240673f909dae4034e88

commit r11-11426-gfdd2a21a53facecc8e2b240673f909dae4034e88
Author: Matthias Kretz 
Date:   Fri Jun 2 21:21:36 2023 +0200

libstdc++: Protect against macros

Signed-off-by: Matthias Kretz 

libstdc++-v3/ChangeLog:

* include/experimental/bits/simd.h (__bit_cast): Use
__gnu__::__vector_size__ instead of gnu::vector_size.

(cherry picked from commit ce2188e4320cbb46d6246bd3f478ba20440c62f3)

Diff:
---
 libstdc++-v3/include/experimental/bits/simd.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd.h 
b/libstdc++-v3/include/experimental/bits/simd.h
index d5683bfcacb3..248237731268 100644
--- a/libstdc++-v3/include/experimental/bits/simd.h
+++ b/libstdc++-v3/include/experimental/bits/simd.h
@@ -1615,18 +1615,18 @@ template 
   return reinterpret_cast<_To>(__x);
 else if constexpr (__is_vector_type_v<_To> && __from_is_vectorizable)
   {
-   using _FV [[gnu::vector_size(sizeof(_From))]] = _From;
+   using _FV [[__gnu__::__vector_size__(sizeof(_From))]] = _From;
return reinterpret_cast<_To>(_FV{__x});
   }
 else if constexpr (__to_is_vectorizable && __from_is_vectorizable)
   {
-   using _TV [[gnu::vector_size(sizeof(_To))]] = _To;
-   using _FV [[gnu::vector_size(sizeof(_From))]] = _From;
+   using _TV [[__gnu__::__vector_size__(sizeof(_To))]] = _To;
+   using _FV [[__gnu__::__vector_size__(sizeof(_From))]] = _From;
return reinterpret_cast<_TV>(_FV{__x})[0];
   }
 else if constexpr (__to_is_vectorizable && __is_vector_type_v<_From>)
   {
-   using _TV [[gnu::vector_size(sizeof(_To))]] = _To;
+   using _TV [[__gnu__::__vector_size__(sizeof(_To))]] = _To;
return reinterpret_cast<_TV>(__x)[0];
   }
 else


[gcc r15-362] tree-optimization/114998 - use-after-free with loop distribution

2024-05-10 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:34d15a4d630a0d54eddb99bdab086c506e10dac5

commit r15-362-g34d15a4d630a0d54eddb99bdab086c506e10dac5
Author: Richard Biener 
Date:   Fri May 10 14:19:49 2024 +0200

tree-optimization/114998 - use-after-free with loop distribution

When loop distribution releases a PHI node of the original IL it
can end up clobbering memory that's re-used when it upon releasing
its RDG resets all stmt UIDs back to -1, even those that got released.

The fix is to avoid resetting UIDs based on stmts in the RDG but
instead reset only those still present in the loop.

PR tree-optimization/114998
* tree-loop-distribution.cc (free_rdg): Take loop argument.
Reset UIDs of stmts still in the IL rather than all stmts
referenced from the RDG.
(loop_distribution::build_rdg): Pass loop to free_rdg.
(loop_distribution::distribute_loop): Likewise.
(loop_distribution::transform_reduction_loop): Likewise.

* gcc.dg/torture/pr114998.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr114998.c | 35 +
 gcc/tree-loop-distribution.cc   | 24 --
 2 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/pr114998.c 
b/gcc/testsuite/gcc.dg/torture/pr114998.c
new file mode 100644
index ..81fc1e077cb9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr114998.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-dce -ftree-loop-distribution" } */
+
+short a, d;
+int b, c, f, g, h, i, j[2], o;
+__attribute__((const)) int s(char r);
+int main() {
+  int l, m, k, n;
+  if (b) {
+char p;
+for (; p >= 0; p--) {
+  int e[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
+ 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1,
+ 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0};
+  if (j[p]) {
+int q[1];
+i = o;
+o = q[h];
+if (g)
+  n = d;
+m = 4;
+for (; m; m--) {
+  if (l)
+k |= c;
+  if (a)
+break;
+}
+  }
+  s(n);
+  f |= b;
+}
+  }
+  return 0;
+}
diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc
index 95203fefa188..45932bae5e7f 100644
--- a/gcc/tree-loop-distribution.cc
+++ b/gcc/tree-loop-distribution.cc
@@ -778,7 +778,7 @@ loop_distribution::stmts_from_loop (class loop *loop, 
vec *stmts)
 /* Free the reduced dependence graph RDG.  */
 
 static void
-free_rdg (struct graph *rdg)
+free_rdg (struct graph *rdg, loop_p loop)
 {
   int i;
 
@@ -792,13 +792,25 @@ free_rdg (struct graph *rdg)
 
   if (v->data)
{
- gimple_set_uid (RDGV_STMT (v), -1);
  (RDGV_DATAREFS (v)).release ();
  free (v->data);
}
 }
 
   free_graph (rdg);
+
+  /* Reset UIDs of stmts still in the loop.  */
+  basic_block *bbs = get_loop_body (loop);
+  for (unsigned i = 0; i < loop->num_nodes; ++i)
+{
+  basic_block bb = bbs[i];
+  gimple_stmt_iterator gsi;
+  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next ())
+   gimple_set_uid (gsi_stmt (gsi), -1);
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next ())
+   gimple_set_uid (gsi_stmt (gsi), -1);
+}
+  free (bbs);
 }
 
 struct graph *
@@ -812,7 +824,7 @@ loop_distribution::build_rdg (class loop *loop, 
control_dependences *cd)
   rdg = new_graph (stmts.length ());
   if (!create_rdg_vertices (rdg, stmts, loop))
 {
-  free_rdg (rdg);
+  free_rdg (rdg, loop);
   return NULL;
 }
   stmts.release ();
@@ -3062,7 +3074,7 @@ loop_distribution::distribute_loop (class loop *loop,
 "Loop %d not distributed: too many memory references.\n",
 loop->num);
 
-  free_rdg (rdg);
+  free_rdg (rdg, loop);
   loop_nest.release ();
   free_data_refs (datarefs_vec);
   delete ddrs_table;
@@ -3259,7 +3271,7 @@ loop_distribution::distribute_loop (class loop *loop,
   FOR_EACH_VEC_ELT (partitions, i, partition)
 partition_free (partition);
 
-  free_rdg (rdg);
+  free_rdg (rdg, loop);
   return nbp - *nb_calls;
 }
 
@@ -3665,7 +3677,7 @@ loop_distribution::transform_reduction_loop (loop_p loop)
   auto_bitmap partition_stmts;
   bitmap_set_range (partition_stmts, 0, rdg->n_vertices);
   find_single_drs (loop, rdg, partition_stmts, _dr, _dr);
-  free_rdg (rdg);
+  free_rdg (rdg, loop);
 
   /* Bail out if there is no single load.  */
   if (load_dr == NULL)


[gcc r15-361] Allow patterns in SLP reductions

2024-05-10 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:52d4691294c84793b301ad3cc24e277b8c7efe0b

commit r15-361-g52d4691294c84793b301ad3cc24e277b8c7efe0b
Author: Richard Biener 
Date:   Fri Mar 1 09:29:32 2024 +0100

Allow patterns in SLP reductions

The following removes the over-broad rejection of patterns for SLP
reductions which is done by removing them from LOOP_VINFO_REDUCTIONS
during pattern detection.  That's also insufficient in case the
pattern only appears on the reduction path.  Instead this implements
the proper correctness check in vectorizable_reduction and guides
SLP discovery to heuristically avoid forming later invalid groups.

I also couldn't find any testcase that FAILs when allowing the SLP
reductions to form so I've added one.

I came across this for single-lane SLP reductions with the all-SLP
work where we rely on patterns to properly vectorize COND_EXPR
reductions.

* tree-vect-patterns.cc (vect_pattern_recog_1): Do not
remove reductions involving patterns.
* tree-vect-loop.cc (vectorizable_reduction): Reject SLP
reduction groups with multiple lane-reducing reductions.
* tree-vect-slp.cc (vect_analyze_slp_instance): When discovering
SLP reduction groups avoid including lane-reducing ones.

* gcc.dg/vect/vect-reduc-sad-9.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/vect/vect-reduc-sad-9.c | 68 
 gcc/tree-vect-loop.cc| 15 ++
 gcc/tree-vect-patterns.cc| 13 --
 gcc/tree-vect-slp.cc | 26 +++
 4 files changed, 101 insertions(+), 21 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-sad-9.c 
b/gcc/testsuite/gcc.dg/vect/vect-reduc-sad-9.c
new file mode 100644
index ..3c6af4510f45
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-sad-9.c
@@ -0,0 +1,68 @@
+/* Disabling epilogues until we find a better way to deal with scans.  */
+/* { dg-additional-options "--param vect-epilogues-nomask=0" } */
+/* { dg-additional-options "-msse4.2" { target { x86_64-*-* i?86-*-* } } } */
+/* { dg-require-effective-target vect_usad_char } */
+
+#include 
+#include "tree-vect.h"
+
+#define N 64
+
+unsigned char X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+unsigned char Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+int abs (int);
+
+/* Sum of absolute differences between arrays of unsigned char types.
+   Detected as a sad pattern.
+   Vectorized on targets that support sad for unsigned chars.  */
+
+__attribute__ ((noinline)) int
+foo (int len, int *res2)
+{
+  int i;
+  int result = 0;
+  int result2 = 0;
+
+  for (i = 0; i < len; i++)
+{
+  /* Make sure we are not using an SLP reduction for this.  */
+  result += abs (X[2*i] - Y[2*i]);
+  result2 += abs (X[2*i + 1] - Y[2*i + 1]);
+}
+
+  *res2 = result2;
+  return result;
+}
+
+
+int
+main (void)
+{
+  int i;
+  int sad;
+
+  check_vect ();
+
+  for (i = 0; i < N/2; i++)
+{
+  X[2*i] = i;
+  Y[2*i] = N/2 - i;
+  X[2*i+1] = i;
+  Y[2*i+1] = 0;
+  __asm__ volatile ("");
+}
+
+
+  int sad2;
+  sad = foo (N/2, );
+  if (sad != (N/2)*(N/4))
+abort ();
+  if (sad2 != (N/2-1)*(N/2)/2)
+abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "vect_recog_sad_pattern: detected" "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 704df7bdcc73..361aec064884 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -7667,6 +7667,21 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
   return false;
 }
 
+  /* Lane-reducing ops also never can be used in a SLP reduction group
+ since we'll mix lanes belonging to different reductions.  But it's
+ OK to use them in a reduction chain or when the reduction group
+ has just one element.  */
+  if (lane_reduc_code_p
+  && slp_node
+  && !REDUC_GROUP_FIRST_ELEMENT (stmt_info)
+  && SLP_TREE_LANES (slp_node) > 1)
+{
+  if (dump_enabled_p ())
+   dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+"lane-reducing reduction in reduction group.\n");
+  return false;
+}
+
   /* All uses but the last are expected to be defined in the loop.
  The last use is the reduction variable.  In case of nested cycle this
  assumption is not true: we use reduc_index to record the index of the
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index 8e8de5ea3a55..dfb7d8005262 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -7160,7 +7160,6 @@ vect_pattern_recog_1 (vec_info *vinfo,
  vect_recog_func *recog_func, stmt_vec_info stmt_info)
 {
   gimple *pattern_stmt;
-  loop_vec_info loop_vinfo;
   tree pattern_vectype;
 
   /* If this 

[gcc r14-10194] AVR: target/114981 - Tweak __builtin_powif / __powisf2

2024-05-10 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:fcdd723779f9ad9af9638e11ffe56786de2d02ce

commit r14-10194-gfcdd723779f9ad9af9638e11ffe56786de2d02ce
Author: Georg-Johann Lay 
Date:   Wed May 8 17:52:56 2024 +0200

AVR: target/114981 - Tweak __builtin_powif / __powisf2

Implement __powisf2 in assembly.

PR target/114981
libgcc/
* config/avr/t-avr (LIB2FUNCS_EXCLUDE): Add _powisf2.
(LIB1ASMFUNCS) [!avrtiny]: Add _powif.
* config/avr/lib1funcs.S (mov4): New .macro.
(L_powif, __powisf2) [!avrtiny]: New module and function.

gcc/testsuite/
* gcc.target/avr/pr114981-powif.c: New test.

(cherry picked from commit af64af69c3cc85dbe00c520651a54850bf5cadc1)

Diff:
---
 gcc/testsuite/gcc.target/avr/pr114981-powif.c |  33 ++
 libgcc/config/avr/lib1funcs.S | 154 ++
 libgcc/config/avr/t-avr   |   4 +-
 3 files changed, 190 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.target/avr/pr114981-powif.c 
b/gcc/testsuite/gcc.target/avr/pr114981-powif.c
new file mode 100644
index ..191dcc61e6d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114981-powif.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-Os" } */
+
+const float vals[] =
+  {
+0.0625f, -0.125f, 0.25f, -0.5f,
+1.0f,
+-2.0f, 4.0f, -8.0f, 16.0f
+  };
+
+#define ARRAY_SIZE(X) ((int) (sizeof(X) / sizeof(*X)))
+
+__attribute__((noinline,noclone))
+void test1 (float x)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE (vals); ++i)
+{
+  float val0 = vals[i];
+  float val1 = __builtin_powif (x, i - 4);
+  __asm ("" : "+r" (val0));
+
+  if (val0 != val1)
+   __builtin_exit (__LINE__);
+}
+}
+
+int main (void)
+{
+  test1 (-2.0f);
+  return 0;
+}
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index af4d7d970169..a0854139a0a3 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -80,6 +80,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #endif
 .endm
 
+.macro mov4  r_dest, r_src
+wmov \r_dest,   \r_src
+wmov \r_dest+2, \r_src+2
+.endm
+
 #if defined (__AVR_HAVE_JMP_CALL__)
 #define XCALL call
 #define XJMP  jmp
@@ -3312,4 +3317,153 @@ ENDF __fmul
 #undef C0
 #undef C1
 
+
+
+/**
+ * Floating-Point
+ **/
+
+#if defined (L_powif)
+#ifndef __AVR_TINY__
+
+;; float output and arg #1
+#define A0  22
+#define A1  A0 + 1
+#define A2  A0 + 2
+#define A3  A0 + 3
+
+;; float arg #2
+#define B0  18
+#define B1  B0 + 1
+#define B2  B0 + 2
+#define B3  B0 + 3
+
+;; float X: input and iterated squares
+#define X0  10
+#define X1  X0 + 1
+#define X2  X0 + 2
+#define X3  X0 + 3
+
+;; float Y: expand result
+#define Y0  14
+#define Y1  Y0 + 1
+#define Y2  Y0 + 2
+#define Y3  Y0 + 3
+
+;; .7 = Sign of I.
+;; .0 == 0  =>  Y = 1.0f implicitly.
+#define Flags   R9
+#define Y_set   0
+
+;;;  Integer exponent input.
+#define I0  28
+#define I1  I0+1
+
+#define ONE 0x3f80
+
+DEFUN __powisf2
+;; Save 11 Registers: R9...R17, R28, R29
+do_prologue_saves 11
+
+;; Fill local vars with input parameters.
+wmovI0, 20
+mov4X0, A0
+;; Save sign of exponent for later.
+mov Flags,  I1
+;; I := abs (I)
+tst I1
+brpl 1f
+NEG2I0
+1:
+;; Y := (I % 2) ? X : 1.0f
+;; (When we come from below, this is like SET, i.e. Flags.Y_set := 1).
+bst I0, 0
+;; Flags.Y_set = false means that we have to assume Y = 1.0f below.
+bld Flags,  Y_set
+2:  ;; We have A == X when we come from above.
+mov4Y0, A0
+
+.Loop:
+;; while (I >>= 1)
+lsr I1
+ror I0
+sbiwI0, 0
+breq .Loop_done
+
+;; X := X * X
+mov4A0, X0
+#ifdef __WITH_AVRLIBC__
+XCALL   squaref
+#else
+mov4B0, X0
+XCALL   __mulsf3
+#endif /* Have AVR-LibC? */
+mov4X0, A0
+
+;; if (I % 2 == 1)  Y := Y * X
+bst I0, 0
+brtc .Loop
+bst Flags, Y_set
+;; When Y is not set  =>  Y := Y * X = 1.0f * X (= A)
+;; Plus, we have to set Y_set = 1 (= I0.0)
+brtc 1b
+;; Y is already set: Y := X * Y (= A * Y)
+mov4B0, Y0
+XCALL   __mulsf3
+rjmp 2b
+
+;; End while
+.Loop_done:
+
+;; A := 1.0f
+ldi A3, hhi8(ONE)
+ldi A2, hlo8(ONE)
+ldi A1, hi8(ONE)
+ldi A0, lo8(ONE)
+
+;; When Y is still not set, the result is 1.0f (= A).
+bst Flags, Y_set
+brtc .Lret
+
+;; if (I was < 0) Y = 1.0f / Y
+tst Flags
+brmi 1f
+;; A := Y
+mov4A0, Y0
+rjmp .Lret
+1:  ;; A := 1 / Y = A / Y
+mov4B0, Y0
+XCALL   __divsf3
+
+.Lret:
+do_epilogue_restores 11
+ENDF __powisf2
+
+#undef A0
+#undef A1
+#undef A2

[gcc r15-360] AVR: target/114981 - Tweak __builtin_powif / __powisf2

2024-05-10 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:af64af69c3cc85dbe00c520651a54850bf5cadc1

commit r15-360-gaf64af69c3cc85dbe00c520651a54850bf5cadc1
Author: Georg-Johann Lay 
Date:   Wed May 8 17:52:56 2024 +0200

AVR: target/114981 - Tweak __builtin_powif / __powisf2

Implement __powisf2 in assembly.

PR target/114981
libgcc/
* config/avr/t-avr (LIB2FUNCS_EXCLUDE): Add _powisf2.
(LIB1ASMFUNCS) [!avrtiny]: Add _powif.
* config/avr/lib1funcs.S (mov4): New .macro.
(L_powif, __powisf2) [!avrtiny]: New module and function.

gcc/testsuite/
* gcc.target/avr/pr114981-powif.c: New test.

Diff:
---
 gcc/testsuite/gcc.target/avr/pr114981-powif.c |  33 ++
 libgcc/config/avr/lib1funcs.S | 154 ++
 libgcc/config/avr/t-avr   |   4 +-
 3 files changed, 190 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.target/avr/pr114981-powif.c 
b/gcc/testsuite/gcc.target/avr/pr114981-powif.c
new file mode 100644
index ..191dcc61e6d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114981-powif.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-Os" } */
+
+const float vals[] =
+  {
+0.0625f, -0.125f, 0.25f, -0.5f,
+1.0f,
+-2.0f, 4.0f, -8.0f, 16.0f
+  };
+
+#define ARRAY_SIZE(X) ((int) (sizeof(X) / sizeof(*X)))
+
+__attribute__((noinline,noclone))
+void test1 (float x)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE (vals); ++i)
+{
+  float val0 = vals[i];
+  float val1 = __builtin_powif (x, i - 4);
+  __asm ("" : "+r" (val0));
+
+  if (val0 != val1)
+   __builtin_exit (__LINE__);
+}
+}
+
+int main (void)
+{
+  test1 (-2.0f);
+  return 0;
+}
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 4ac31fa104e3..04a4eb01ab43 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -80,6 +80,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #endif
 .endm
 
+.macro mov4  r_dest, r_src
+wmov \r_dest,   \r_src
+wmov \r_dest+2, \r_src+2
+.endm
+
 #if defined (__AVR_HAVE_JMP_CALL__)
 #define XCALL call
 #define XJMP  jmp
@@ -3312,4 +3317,153 @@ ENDF __fmul
 #undef C0
 #undef C1
 
+
+
+/**
+ * Floating-Point
+ **/
+
+#if defined (L_powif)
+#ifndef __AVR_TINY__
+
+;; float output and arg #1
+#define A0  22
+#define A1  A0 + 1
+#define A2  A0 + 2
+#define A3  A0 + 3
+
+;; float arg #2
+#define B0  18
+#define B1  B0 + 1
+#define B2  B0 + 2
+#define B3  B0 + 3
+
+;; float X: input and iterated squares
+#define X0  10
+#define X1  X0 + 1
+#define X2  X0 + 2
+#define X3  X0 + 3
+
+;; float Y: expand result
+#define Y0  14
+#define Y1  Y0 + 1
+#define Y2  Y0 + 2
+#define Y3  Y0 + 3
+
+;; .7 = Sign of I.
+;; .0 == 0  =>  Y = 1.0f implicitly.
+#define Flags   R9
+#define Y_set   0
+
+;;;  Integer exponent input.
+#define I0  28
+#define I1  I0+1
+
+#define ONE 0x3f80
+
+DEFUN __powisf2
+;; Save 11 Registers: R9...R17, R28, R29
+do_prologue_saves 11
+
+;; Fill local vars with input parameters.
+wmovI0, 20
+mov4X0, A0
+;; Save sign of exponent for later.
+mov Flags,  I1
+;; I := abs (I)
+tst I1
+brpl 1f
+NEG2I0
+1:
+;; Y := (I % 2) ? X : 1.0f
+;; (When we come from below, this is like SET, i.e. Flags.Y_set := 1).
+bst I0, 0
+;; Flags.Y_set = false means that we have to assume Y = 1.0f below.
+bld Flags,  Y_set
+2:  ;; We have A == X when we come from above.
+mov4Y0, A0
+
+.Loop:
+;; while (I >>= 1)
+lsr I1
+ror I0
+sbiwI0, 0
+breq .Loop_done
+
+;; X := X * X
+mov4A0, X0
+#ifdef __WITH_AVRLIBC__
+XCALL   squaref
+#else
+mov4B0, X0
+XCALL   __mulsf3
+#endif /* Have AVR-LibC? */
+mov4X0, A0
+
+;; if (I % 2 == 1)  Y := Y * X
+bst I0, 0
+brtc .Loop
+bst Flags, Y_set
+;; When Y is not set  =>  Y := Y * X = 1.0f * X (= A)
+;; Plus, we have to set Y_set = 1 (= I0.0)
+brtc 1b
+;; Y is already set: Y := X * Y (= A * Y)
+mov4B0, Y0
+XCALL   __mulsf3
+rjmp 2b
+
+;; End while
+.Loop_done:
+
+;; A := 1.0f
+ldi A3, hhi8(ONE)
+ldi A2, hlo8(ONE)
+ldi A1, hi8(ONE)
+ldi A0, lo8(ONE)
+
+;; When Y is still not set, the result is 1.0f (= A).
+bst Flags, Y_set
+brtc .Lret
+
+;; if (I was < 0) Y = 1.0f / Y
+tst Flags
+brmi 1f
+;; A := Y
+mov4A0, Y0
+rjmp .Lret
+1:  ;; A := 1 / Y = A / Y
+mov4B0, Y0
+XCALL   __divsf3
+
+.Lret:
+do_epilogue_restores 11
+ENDF __powisf2
+
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+
+#undef X0
+#undef X1

[gcc r14-10193] c++, mingw: Fix up types of dtor hooks to __cxa_{, thread_}atexit/__cxa_throw on mingw ia32 [PR114968

2024-05-10 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:a805de33f7be4f6886906ca5f4da493f3b743c76

commit r14-10193-ga805de33f7be4f6886906ca5f4da493f3b743c76
Author: Jakub Jelinek 
Date:   Fri May 10 09:21:38 2024 +0200

c++, mingw: Fix up types of dtor hooks to 
__cxa_{,thread_}atexit/__cxa_throw on mingw ia32 [PR114968]

__cxa_atexit/__cxa_thread_atexit/__cxa_throw functions accept function
pointers to usually directly destructors rather than wrappers around
them.
Now, mingw ia32 uses implicitly __attribute__((thiscall)) calling
conventions for METHOD_TYPE (where the this pointer is passed in %ecx
register, the rest on the stack), so these functions use:
in config/os/mingw32/os_defines.h:
 #if defined (__i386__)
 #define _GLIBCXX_CDTOR_CALLABI __thiscall
 #endif
in libsupc++/cxxabi.h
__cxa_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void*) 
_GLIBCXX_NOTHROW;
__cxa_thread_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void *) 
_GLIBCXX_NOTHROW;
__cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void 
*))
__attribute__((__noreturn__));

Now, mingw for some weird reason uses
 #define TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT hook_bool_void_true
so it never actually uses __cxa_atexit, but does use __cxa_thread_atexit
and __cxa_throw.  Recent changes for modules result in more detailed
__cxa_*atexit/__cxa_throw prototypes precreated by the compiler, and if
that happens and one also includes , the compiler complains about
mismatches in the prototypes.

One thing is the missing thiscall attribute on the FUNCTION_TYPE, the
other problem is that all of atexit/__cxa_atexit/__cxa_thread_atexit
get function pointer types created by a single function,
get_atexit_fn_ptr_type (), which creates it depending on if atexit
or __cxa_atexit will be used as either void(*)(void) or void(*)(void *),
but when using atexit and __cxa_thread_atexit it uses the wrong function
type for __cxa_thread_atexit.

The following patch adds a target hook to add the thiscall attribute to the
function pointers, and splits the get_atexit_fn_ptr_type () function into
get_atexit_fn_ptr_type () and get_cxa_atexit_fn_ptr_type (), the former 
always
creates shared void(*)(void) type, the latter creates either
void(*)(void*) (on most targets) or void(__attribute__((thiscall))*)(void*)
(on mingw ia32).  So that we don't waiste another GTY global tree for it,
because cleanup_type used for the same purpose for __cxa_throw should be
the same, the code changes it to use that type too.

In register_dtor_fn then based on the decision whether to use atexit,
__cxa_atexit or __cxa_thread_atexit it picks the right function pointer
type, and also if it decides to emit a __tcf_* wrapper for the cleanup,
uses that type for that wrapper so that it agrees on calling convention.

2024-05-10  Jakub Jelinek  

PR target/114968
gcc/
* target.def (use_atexit_for_cxa_atexit): Remove spurious space
from comment.
(adjust_cdtor_callabi_fntype): New cxx target hook.
* targhooks.h (default_cxx_adjust_cdtor_callabi_fntype): Declare.
* targhooks.cc (default_cxx_adjust_cdtor_callabi_fntype): New
function.
* doc/tm.texi.in (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Add.
* doc/tm.texi: Regenerate.
* config/i386/i386.cc (ix86_cxx_adjust_cdtor_callabi_fntype): New
function.
(TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Redefine.
gcc/cp/
* cp-tree.h (atexit_fn_ptr_type_node, cleanup_type): Adjust macro
comments.
(get_cxa_atexit_fn_ptr_type): Declare.
* decl.cc (get_atexit_fn_ptr_type): Adjust function comment, only
build type for atexit argument.
(get_cxa_atexit_fn_ptr_type): New function.
(get_atexit_node): Call get_cxa_atexit_fn_ptr_type rather than
get_atexit_fn_ptr_type when using __cxa_atexit.
(get_thread_atexit_node): Call get_cxa_atexit_fn_ptr_type
rather than get_atexit_fn_ptr_type.
(start_cleanup_fn): Add ob_parm argument, call
get_cxa_atexit_fn_ptr_type or get_atexit_fn_ptr_type depending
on it and create PARM_DECL also based on that argument.
(register_dtor_fn): Adjust start_cleanup_fn caller, use
get_cxa_atexit_fn_ptr_type rather than get_atexit_fn_ptr_type
for use_dtor casts.
* except.cc (build_throw): Use get_cxa_atexit_fn_ptr_type ().

(cherry picked from commit e5d8fd9ce05611093191d500ebc39f150d0ece2b)

Diff:
---
 gcc/config/i386/i386.cc | 16 ++
 gcc/cp/cp-tree.h|  7 +++---
 gcc/cp/decl.cc  | 59 +++--
 gcc/cp/except.cc|  6 +
 gcc/doc/tm.texi   

[gcc r15-359] bpf: fix printing of memory operands in pseudoc asm dialect

2024-05-10 Thread Jose E. Marchesi via Gcc-cvs
https://gcc.gnu.org/g:bb5f619a938567b316306bdc46f0efb8d18ddc59

commit r15-359-gbb5f619a938567b316306bdc46f0efb8d18ddc59
Author: Jose E. Marchesi 
Date:   Fri May 10 09:50:25 2024 +0200

bpf: fix printing of memory operands in pseudoc asm dialect

The BPF backend was emitting memory operands in pseudo-C syntax
without surrounding parentheses.  These were being provided in the
corresponding instruction templates.

This was causing GCC emitting invalid instructions when finding inline
assembly with memory operands like:

asm volatile (
"r1 = *(u64 *)%[ctx_a];"
"if r1 != 42 goto 1f;"
"r1 = *(u64 *)%[ctx_b];"
"if r1 != 42 goto 1f;"
"r1 = *(u64 *)%[ctx_c];"
"if r1 != 7 goto 1f;"
"r1 /= 0;"
"1:"
:
: [ctx_a]"m"(ctx.a),
  [ctx_b]"m"(ctx.b),
  [ctx_c]"m"(ctx.c)
: "r1"
);

This patch changes the backend to include the surrounding parentheses
in the printed representation of the memory operands (much like
surrounding brackets are included in normal asm syntax) and adapts the
impacted instruction templates accordingly.

Tested in target bpf-unknown-none, host x86_64-linux-gnu.

gcc/ChangeLog:

* config/bpf/bpf.cc (bpf_print_operand_address): Include
surrounding parenthesis around mem operands in pseudoc asm
dialect.
* config/bpf/bpf.md (*mov): Adapt accordingly.
(zero_extendhidi2): Likewise.
(zero_extendqidi2): Likewise.
(*extendsidi2): Likewise.
(*extendsidi2): Likewise.
(extendhidi2): Likewise.
(extendqidi2): Likewise.
(extendhisi2): Likewise.
* config/bpf/atomic.md (atomic_add): Likewise.
(atomic_and): Likewise.
(atomic_or): Likewise.
(atomic_xor): Likewise.
(atomic_fetch_add): Likewise.
(atomic_fetch_and): Likewise.
(atomic_fetch_or): Likewise.
(atomic_fetch_xor): Likewise.

Diff:
---
 gcc/config/bpf/atomic.md | 16 
 gcc/config/bpf/bpf.cc| 11 ---
 gcc/config/bpf/bpf.md| 18 +-
 3 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/gcc/config/bpf/atomic.md b/gcc/config/bpf/atomic.md
index 4c131cad8a37..65bd5f266a15 100644
--- a/gcc/config/bpf/atomic.md
+++ b/gcc/config/bpf/atomic.md
@@ -34,7 +34,7 @@
   (match_operand:SI 2 "const_int_operand")] ;; Memory model.
  UNSPEC_AADD))]
   ""
-  "{xadd\t%0,%1|lock *( *)(%w0) += %w1}"
+  "{xadd\t%0,%1|lock *( *)%w0 += %w1}"
   [(set_attr "type" "atomic")])
 
 (define_insn "atomic_and"
@@ -45,7 +45,7 @@
   (match_operand:SI 2 "const_int_operand")] ;; Memory model.
  UNSPEC_AAND))]
   "bpf_has_v3_atomics"
-  "{aand\t%0,%1|lock *( *)(%w0) &= %w1}")
+  "{aand\t%0,%1|lock *( *)%w0 &= %w1}")
 
 (define_insn "atomic_or"
   [(set (match_operand:AMO 0 "memory_operand" "+m")
@@ -55,7 +55,7 @@
   (match_operand:SI 2 "const_int_operand")] ;; Memory model.
  UNSPEC_AOR))]
   "bpf_has_v3_atomics"
-  "{aor\t%0,%1|lock *( *)(%w0) %|= %w1}")
+  "{aor\t%0,%1|lock *( *)%w0 %|= %w1}")
 
 (define_insn "atomic_xor"
   [(set (match_operand:AMO 0 "memory_operand" "+m")
@@ -65,7 +65,7 @@
   (match_operand:SI 2 "const_int_operand")] ;; Memory model.
  UNSPEC_AXOR))]
   "bpf_has_v3_atomics"
-  "{axor\t%0,%1|lock *( *)(%w0) ^= %w1}")
+  "{axor\t%0,%1|lock *( *)%w0 ^= %w1}")
 
 ;;; Feching (read-modify-store) versions of atomic operations.
 
@@ -79,7 +79,7 @@
   (match_operand:AMO 3 "const_int_operand")] ;; Memory model
 UNSPEC_AFADD))]
   "bpf_has_v3_atomics"
-  "{afadd\t%1,%0|%w0 = atomic_fetch_add(( *)(%1), %w0)}")
+  "{afadd\t%1,%0|%w0 = atomic_fetch_add(( *)%1, %w0)}")
 
 (define_insn "atomic_fetch_and"
   [(set (match_operand:AMO 0 "register_operand" "=r")
@@ -91,7 +91,7 @@
   (match_operand:AMO 3 "const_int_operand")]
  UNSPEC_AFAND))]
   "bpf_has_v3_atomics"
-  "{afand\t%1,%0|%w0 = atomic_fetch_and(( *)(%1), %w0)}")
+  "{afand\t%1,%0|%w0 = atomic_fetch_and(( *)%1, %w0)}")
 
 (define_insn "atomic_fetch_or"
   [(set (match_operand:AMO 0 "register_operand" "=r")
@@ -103,7 +103,7 @@
   (match_operand:AMO 3 "const_int_operand")]
  UNSPEC_AFOR))]
   "bpf_has_v3_atomics"
-  "{afor\t%1,%0|%w0 = atomic_fetch_or(( *)(%1), %w0)}")
+  "{afor\t%1,%0|%w0 = atomic_fetch_or(( *)%1, %w0)}")
 
 (define_insn "atomic_fetch_xor"
   [(set (match_operand:AMO 0 "register_operand" "=r")
@@ -115,7 +115,7 @@
   (match_operand:AMO 3 "const_int_operand")]
  UNSPEC_AFXOR))]
   "bpf_has_v3_atomics"
-  "{afxor\t%1,%0|%w0 = atomic_fetch_xor(( *)(%1), %w0)}")
+  "{afxor\t%1,%0|%w0 = atomic_fetch_xor(( *)%1, %w0)}")
 
 ;; Weird suffixes used in pseudo-c atomic 

[gcc r11-11425] Objective-C, NeXT, v2: Correct a regression in code-gen.

2024-05-10 Thread Iain D Sandoe via Gcc-cvs
https://gcc.gnu.org/g:48400d6c95c836d43532bb00a3a57f3c458e0778

commit r11-11425-g48400d6c95c836d43532bb00a3a57f3c458e0778
Author: Iain Sandoe 
Date:   Tue Apr 30 15:11:56 2024 +0100

Objective-C, NeXT, v2: Correct a regression in code-gen.

There have been several changes in the ABI of Objective-C which
depend on the OS version targetted.  In this case Protocols and
LabelProtocols should be made weak/hidden/extern from macOS 10.7
however there was a mistake in the code causing this to occur
from macOS 10.6.  Fixed thus.

gcc/objc/ChangeLog:

* objc-next-runtime-abi-02.c (WEAK_PROTOCOLS_AFTER): New.
(next_runtime_abi_02_protocol_decl): Use WEAK_PROTOCOLS_AFTER
to determine this ABI change.
(build_v2_protocol_list_address_table): Likewise.

Signed-off-by: Iain Sandoe 
(cherry picked from commit 9b5c0be59d0f94df0517820f00b4520b5abddd8c)

Diff:
---
 gcc/objc/objc-next-runtime-abi-02.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/gcc/objc/objc-next-runtime-abi-02.c 
b/gcc/objc/objc-next-runtime-abi-02.c
index cb22a773fcb2..2f79f99c7319 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3.  If not see
 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper2_stret"
 
 #define USE_FIXUP_BEFORE   100600
+#define WEAK_PROTOCOLS_AFTER   100700
 #define TAG_FIXUP  "_fixup"
 
 
@@ -1031,7 +1032,7 @@ next_runtime_abi_02_protocol_decl (tree p)
   /* static struct _objc_protocol _OBJC_Protocol_; */
   snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
-  if (flag_next_runtime >= USE_FIXUP_BEFORE)
+  if (flag_next_runtime >= WEAK_PROTOCOLS_AFTER)
 {
   decl = create_hidden_decl (objc_v2_protocol_template, buf);
   DECL_WEAK (decl) = true;
@@ -2317,7 +2318,7 @@ build_v2_protocol_list_address_table (void)
   gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
   snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
-  if (flag_next_runtime >= USE_FIXUP_BEFORE)
+  if (flag_next_runtime >= WEAK_PROTOCOLS_AFTER)
{
  decl = create_hidden_decl (objc_protocol_type, buf, /*is def=*/true);
  DECL_WEAK (decl) = true;


[gcc r15-358] c++, mingw: Fix up types of dtor hooks to __cxa_{, thread_}atexit/__cxa_throw on mingw ia32 [PR114968

2024-05-10 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:e5d8fd9ce05611093191d500ebc39f150d0ece2b

commit r15-358-ge5d8fd9ce05611093191d500ebc39f150d0ece2b
Author: Jakub Jelinek 
Date:   Fri May 10 09:21:38 2024 +0200

c++, mingw: Fix up types of dtor hooks to 
__cxa_{,thread_}atexit/__cxa_throw on mingw ia32 [PR114968]

__cxa_atexit/__cxa_thread_atexit/__cxa_throw functions accept function
pointers to usually directly destructors rather than wrappers around
them.
Now, mingw ia32 uses implicitly __attribute__((thiscall)) calling
conventions for METHOD_TYPE (where the this pointer is passed in %ecx
register, the rest on the stack), so these functions use:
in config/os/mingw32/os_defines.h:
 #if defined (__i386__)
 #define _GLIBCXX_CDTOR_CALLABI __thiscall
 #endif
in libsupc++/cxxabi.h
__cxa_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void*) 
_GLIBCXX_NOTHROW;
__cxa_thread_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void *) 
_GLIBCXX_NOTHROW;
__cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void 
*))
__attribute__((__noreturn__));

Now, mingw for some weird reason uses
 #define TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT hook_bool_void_true
so it never actually uses __cxa_atexit, but does use __cxa_thread_atexit
and __cxa_throw.  Recent changes for modules result in more detailed
__cxa_*atexit/__cxa_throw prototypes precreated by the compiler, and if
that happens and one also includes , the compiler complains about
mismatches in the prototypes.

One thing is the missing thiscall attribute on the FUNCTION_TYPE, the
other problem is that all of atexit/__cxa_atexit/__cxa_thread_atexit
get function pointer types created by a single function,
get_atexit_fn_ptr_type (), which creates it depending on if atexit
or __cxa_atexit will be used as either void(*)(void) or void(*)(void *),
but when using atexit and __cxa_thread_atexit it uses the wrong function
type for __cxa_thread_atexit.

The following patch adds a target hook to add the thiscall attribute to the
function pointers, and splits the get_atexit_fn_ptr_type () function into
get_atexit_fn_ptr_type () and get_cxa_atexit_fn_ptr_type (), the former 
always
creates shared void(*)(void) type, the latter creates either
void(*)(void*) (on most targets) or void(__attribute__((thiscall))*)(void*)
(on mingw ia32).  So that we don't waiste another GTY global tree for it,
because cleanup_type used for the same purpose for __cxa_throw should be
the same, the code changes it to use that type too.

In register_dtor_fn then based on the decision whether to use atexit,
__cxa_atexit or __cxa_thread_atexit it picks the right function pointer
type, and also if it decides to emit a __tcf_* wrapper for the cleanup,
uses that type for that wrapper so that it agrees on calling convention.

2024-05-10  Jakub Jelinek  

PR target/114968
gcc/
* target.def (use_atexit_for_cxa_atexit): Remove spurious space
from comment.
(adjust_cdtor_callabi_fntype): New cxx target hook.
* targhooks.h (default_cxx_adjust_cdtor_callabi_fntype): Declare.
* targhooks.cc (default_cxx_adjust_cdtor_callabi_fntype): New
function.
* doc/tm.texi.in (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Add.
* doc/tm.texi: Regenerate.
* config/i386/i386.cc (ix86_cxx_adjust_cdtor_callabi_fntype): New
function.
(TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Redefine.
gcc/cp/
* cp-tree.h (atexit_fn_ptr_type_node, cleanup_type): Adjust macro
comments.
(get_cxa_atexit_fn_ptr_type): Declare.
* decl.cc (get_atexit_fn_ptr_type): Adjust function comment, only
build type for atexit argument.
(get_cxa_atexit_fn_ptr_type): New function.
(get_atexit_node): Call get_cxa_atexit_fn_ptr_type rather than
get_atexit_fn_ptr_type when using __cxa_atexit.
(get_thread_atexit_node): Call get_cxa_atexit_fn_ptr_type
rather than get_atexit_fn_ptr_type.
(start_cleanup_fn): Add ob_parm argument, call
get_cxa_atexit_fn_ptr_type or get_atexit_fn_ptr_type depending
on it and create PARM_DECL also based on that argument.
(register_dtor_fn): Adjust start_cleanup_fn caller, use
get_cxa_atexit_fn_ptr_type rather than get_atexit_fn_ptr_type
for use_dtor casts.
* except.cc (build_throw): Use get_cxa_atexit_fn_ptr_type ().

Diff:
---
 gcc/config/i386/i386.cc | 16 ++
 gcc/cp/cp-tree.h|  7 +++---
 gcc/cp/decl.cc  | 59 +++--
 gcc/cp/except.cc|  6 +
 gcc/doc/tm.texi |  8 +++
 gcc/doc/tm.texi.in  |  2 ++
 gcc/target.def  | 

[gcc r15-357] [prange] Do not assume all pointers are the same size [PR115009]

2024-05-10 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:ac255c7afeb8a558bd6224ff77277eebcd849d6e

commit r15-357-gac255c7afeb8a558bd6224ff77277eebcd849d6e
Author: Aldy Hernandez 
Date:   Thu May 9 23:37:30 2024 +0200

[prange] Do not assume all pointers are the same size [PR115009]

In a world with same sized pointers we can always reuse the storage
slots, but since this is not always the case, we need to be more
careful.  However, we can always store an undefined, because that
requires no extra storage.

gcc/ChangeLog:

PR tree-optimization/115009
* value-range-storage.cc (prange_storage::alloc): Do not assume
all pointers are the same size.
(prange_storage::prange_storage): Same.
(prange_storage::fits_p): Same.

Diff:
---
 gcc/value-range-storage.cc | 30 +++---
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index bbae0da4772d..8e8d61d59350 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -593,12 +593,12 @@ frange_storage::fits_p (const frange &) const
 prange_storage *
 prange_storage::alloc (vrange_internal_alloc , const prange )
 {
-  // Assume all pointers are the same size.
-  unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
-  gcc_checking_assert (r.undefined_p () || TYPE_PRECISION (r.type ()) == prec);
-
-  typedef trailing_wide_ints twi;
-  size_t size = sizeof (prange_storage) + twi::extra_size (prec);
+  size_t size = sizeof (prange_storage);
+  if (!r.undefined_p ())
+{
+  unsigned prec = TYPE_PRECISION (r.type ());
+  size += trailing_wide_ints::extra_size (prec);
+}
   prange_storage *p = static_cast  (allocator.alloc (size));
   new (p) prange_storage (r);
   return p;
@@ -610,8 +610,12 @@ prange_storage::prange_storage (const prange )
 {
   // It is the caller's responsibility to allocate enough space such
   // that the precision fits.
-  unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
-  m_trailing_ints.set_precision (prec);
+  if (r.undefined_p ())
+// Undefined ranges do not require any extra space for trailing
+// wide ints.
+m_trailing_ints.set_precision (0);
+  else
+m_trailing_ints.set_precision (TYPE_PRECISION (r.type ()));
 
   set_prange (r);
 }
@@ -669,10 +673,14 @@ prange_storage::equal_p (const prange ) const
 }
 
 bool
-prange_storage::fits_p (const prange &) const
+prange_storage::fits_p (const prange ) const
 {
-  // All pointers are the same size.
-  return true;
+  // Undefined ranges always fit, because they don't store anything in
+  // the trailing wide ints.
+  if (r.undefined_p ())
+return true;
+
+  return TYPE_PRECISION (r.type ()) <= m_trailing_ints.get_precision ();
 }


[gcc r15-356] RISC-V: Fix typos in code or comment [NFC]

2024-05-10 Thread Kito Cheng via Gcc-cvs
https://gcc.gnu.org/g:d83070aebdb810e38f12d008e7a10acf1063f456

commit r15-356-gd83070aebdb810e38f12d008e7a10acf1063f456
Author: Kito Cheng 
Date:   Tue May 7 10:18:58 2024 +0800

RISC-V: Fix typos in code or comment [NFC]

Just found some typo when fixing bugs and then use aspell to find few
more typos, this patch didn't do anything other than fix typo.

gcc/ChangeLog:

* config/riscv/riscv-vsetvl.cc: Fix typos in comments.
(get_all_predecessors): Ditto.
(pre_vsetvl::m_unknow_info): Rename to...
(pre_vsetvl::m_unknown_info): this.
(pre_vsetvl::compute_vsetvl_def_data): Rename m_unknow_info to
m_unknown_info.
(pre_vsetvl::cleaup): Rename to...
(pre_vsetvl::cleanup): this.
(pre_vsetvl::compute_vsetvl_def_data): Fix typos.
(pass_vsetvl::lazy_vsetvl): Update function name and fix typos.
* config/riscv/riscv.cc: Fix typos in comments.
(struct machine_function): Fix typo in comments.
(riscv_valid_lo_sum_p): Ditto.
(riscv_force_address): Ditto.
(riscv_immediate_operand_p): Ditto.
(riscv_in_small_data_p): Ditto.
(riscv_first_stack_step): Ditto.
(riscv_expand_prologue): Ditto.
(riscv_convert_vector_chunks): Ditto.
(riscv_override_options_internal): Ditto.
(get_common_costs): Ditto.

Diff:
---
 gcc/config/riscv/riscv-vsetvl.cc | 64 
 gcc/config/riscv/riscv.cc| 36 +++---
 2 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 48ce757a6ee5..bbea2b5fd4f3 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -95,7 +95,7 @@ using namespace riscv_vector;
It's a bit different from bitmap_union_of_preds in cfganal.cc. This function
takes into account the case where pred is ENTRY basic block. The main reason
for this difference is to make it easier to insert some special value into
-   the ENTRY base block. For example, vsetvl_info with a status of UNKNOW.  */
+   the ENTRY base block. For example, vsetvl_info with a status of UNKNOWN.  */
 static void
 bitmap_union_of_preds_with_entry (sbitmap dst, sbitmap *src, basic_block b)
 {
@@ -126,9 +126,9 @@ bitmap_union_of_preds_with_entry (sbitmap dst, sbitmap 
*src, basic_block b)
   }
 }
 
-/* Compute the reaching defintion in and out based on the gen and KILL
-   informations in each Base Blocks.
-   This function references the compute_avaiable implementation in lcm.cc  */
+/* Compute the reaching definition in and out based on the gen and KILL
+   information's in each Base Blocks.
+   This function references the compute_available implementation in lcm.cc  */
 static void
 compute_reaching_defintion (sbitmap *gen, sbitmap *kill, sbitmap *in,
sbitmap *out)
@@ -719,7 +719,7 @@ get_all_predecessors (basic_block bb)
require SEW and LMUL to be fixed.
Therefore, if the former RVV instruction needs DEMAND_RATIO_P and the latter
instruction needs DEMAND_SEW_LMUL_P and its SEW/LMUL is the same as that of
-   the former instruction, then we can make the minimu demand of the former
+   the former instruction, then we can make the minimum demand of the former
instruction strict to DEMAND_SEW_LMUL_P, and its required SEW and LMUL are
the SEW and LMUL of the latter instruction, and the vsetvl instruction
generated according to the new demand can also be used for the latter
@@ -741,7 +741,7 @@ enum demand_flags : unsigned
 /* We split the demand information into three parts. They are sew and lmul
related (sew_lmul_demand_type), tail and mask policy related
(policy_demand_type) and avl related (avl_demand_type). Then we define three
-   interfaces avaiable_with, compatible_p and merge. avaiable_with is
+   interfaces available_p, compatible_p and merge. available_p is
used to determine whether the two vsetvl infos prev_info and next_info are
available or not. If prev_info is available for next_info, it means that the
RVV insn corresponding to next_info on the path from prev_info to next_info
@@ -1361,17 +1361,17 @@ public:
 
 /* Demand system is the RVV-based VSETVL info analysis tools wrapper.
It defines compatible rules for SEW/LMUL, POLICY and AVL.
-   Also, it provides 3 iterfaces avaiable_p, compatible_p and
+   Also, it provides 3 interfaces available_p, compatible_p and
merge for the VSETVL PASS analysis and optimization.
 
- - avaiable_p: Determine whether the next info can get the
-   avaiable VSETVL status from previous info.
+ - available_p: Determine whether the next info can get the
+   available VSETVL status from previous info.
e.g. bb 2 (demand SEW = 32, LMUL = M2) -> bb 3 (demand RATIO = 16).

[gcc r12-10437] Objective-C, NeXT, v2: Correct a regression in code-gen.

2024-05-10 Thread Iain D Sandoe via Gcc-cvs
https://gcc.gnu.org/g:587596d8b882da898469dfc08d56368ba31f14b2

commit r12-10437-g587596d8b882da898469dfc08d56368ba31f14b2
Author: Iain Sandoe 
Date:   Tue Apr 30 15:11:56 2024 +0100

Objective-C, NeXT, v2: Correct a regression in code-gen.

There have been several changes in the ABI of Objective-C which
depend on the OS version targetted.  In this case Protocols and
LabelProtocols should be made weak/hidden/extern from macOS 10.7
however there was a mistake in the code causing this to occur
from macOS 10.6.  Fixed thus.

gcc/objc/ChangeLog:

* objc-next-runtime-abi-02.cc (WEAK_PROTOCOLS_AFTER): New.
(next_runtime_abi_02_protocol_decl): Use WEAK_PROTOCOLS_AFTER
to determine this ABI change.
(build_v2_protocol_list_address_table): Likewise.

Signed-off-by: Iain Sandoe 
(cherry picked from commit 9b5c0be59d0f94df0517820f00b4520b5abddd8c)

Diff:
---
 gcc/objc/objc-next-runtime-abi-02.cc | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/gcc/objc/objc-next-runtime-abi-02.cc 
b/gcc/objc/objc-next-runtime-abi-02.cc
index 1dee05df7691..baf419d3350f 100644
--- a/gcc/objc/objc-next-runtime-abi-02.cc
+++ b/gcc/objc/objc-next-runtime-abi-02.cc
@@ -72,6 +72,7 @@ along with GCC; see the file COPYING3.  If not see
 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper2_stret"
 
 #define USE_FIXUP_BEFORE   100600
+#define WEAK_PROTOCOLS_AFTER   100700
 #define TAG_FIXUP  "_fixup"
 
 
@@ -1025,7 +1026,7 @@ next_runtime_abi_02_protocol_decl (tree p)
   /* static struct _objc_protocol _OBJC_Protocol_; */
   snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
-  if (flag_next_runtime >= USE_FIXUP_BEFORE)
+  if (flag_next_runtime >= WEAK_PROTOCOLS_AFTER)
 {
   decl = create_hidden_decl (objc_v2_protocol_template, buf);
   DECL_WEAK (decl) = true;
@@ -2312,7 +2313,7 @@ build_v2_protocol_list_address_table (void)
   gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
   snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
-  if (flag_next_runtime >= USE_FIXUP_BEFORE)
+  if (flag_next_runtime >= WEAK_PROTOCOLS_AFTER)
{
  decl = create_hidden_decl (objc_protocol_type, buf, /*is def=*/true);
  DECL_WEAK (decl) = true;