[gcc r15-2356] libstdc++: Remove __find_if unrolling for random access iterators

2024-07-27 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:e69456ff9a54ba3e9c93842b05757b7d8fff6d9d

commit r15-2356-ge69456ff9a54ba3e9c93842b05757b7d8fff6d9d
Author: Jonathan Wakely 
Date:   Thu Jul 4 12:01:29 2024 +0100

libstdc++: Remove __find_if unrolling for random access iterators

As the numbers in PR libstdc++/88545 show, the manual loop unrolling in
std::__find_if doesn't actually help these days, and it prevents the
compiler from auto-vectorizing.

Remove the dispatching on iterator_category and just use the simple loop
for all iterator categories.

libstdc++-v3/ChangeLog:

* include/bits/stl_algobase.h (__find_if): Remove overloads for
dispatching on iterator_category. Do not unroll loop manually.
* include/bits/stl_algo.h (__find_if_not): Remove
iterator_category argument from __find_if call.

Diff:
---
 libstdc++-v3/include/bits/stl_algo.h |  3 +-
 libstdc++-v3/include/bits/stl_algobase.h | 70 ++--
 2 files changed, 5 insertions(+), 68 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_algo.h 
b/libstdc++-v3/include/bits/stl_algo.h
index d250b2e04d4d..541f53b2 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -110,8 +110,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  _Predicate __pred)
 {
   return std::__find_if(__first, __last,
-   __gnu_cxx::__ops::__negate(__pred),
-   std::__iterator_category(__first));
+   __gnu_cxx::__ops::__negate(__pred));
 }
 
   /// Like find_if_not(), but uses and updates a count of the
diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index dec1e4c79d86..27f6c377ad6f 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -2098,77 +2098,15 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
 _GLIBCXX_END_NAMESPACE_ALGO
 
-  /// This is an overload used by find algos for the Input Iterator case.
-  template
-_GLIBCXX20_CONSTEXPR
-inline _InputIterator
-__find_if(_InputIterator __first, _InputIterator __last,
- _Predicate __pred, input_iterator_tag)
-{
-  while (__first != __last && !__pred(__first))
-   ++__first;
-  return __first;
-}
-
-  /// This is an overload used by find algos for the RAI case.
-  template
-_GLIBCXX20_CONSTEXPR
-_RandomAccessIterator
-__find_if(_RandomAccessIterator __first, _RandomAccessIterator __last,
- _Predicate __pred, random_access_iterator_tag)
-{
-  typename iterator_traits<_RandomAccessIterator>::difference_type
-   __trip_count = (__last - __first) >> 2;
-
-  for (; __trip_count > 0; --__trip_count)
-   {
- if (__pred(__first))
-   return __first;
- ++__first;
-
- if (__pred(__first))
-   return __first;
- ++__first;
-
- if (__pred(__first))
-   return __first;
- ++__first;
-
- if (__pred(__first))
-   return __first;
- ++__first;
-   }
-
-  switch (__last - __first)
-   {
-   case 3:
- if (__pred(__first))
-   return __first;
- ++__first;
- // FALLTHRU
-   case 2:
- if (__pred(__first))
-   return __first;
- ++__first;
- // FALLTHRU
-   case 1:
- if (__pred(__first))
-   return __first;
- ++__first;
- // FALLTHRU
-   case 0:
-   default:
- return __last;
-   }
-}
-
+  // Implementation of std::find_if, also used in std::remove_if and others.
   template
 _GLIBCXX20_CONSTEXPR
 inline _Iterator
 __find_if(_Iterator __first, _Iterator __last, _Predicate __pred)
 {
-  return __find_if(__first, __last, __pred,
-  std::__iterator_category(__first));
+  while (__first != __last && !__pred(__first))
+   ++__first;
+  return __first;
 }
 
   template


[gcc r15-2357] libstdc++: Add comment noting LWG 3617 support

2024-07-27 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:2da38b6a8896bff08db78e6587d6142b898c8730

commit r15-2357-g2da38b6a8896bff08db78e6587d6142b898c8730
Author: Jonathan Wakely 
Date:   Thu Jul 25 18:38:46 2024 +0100

libstdc++: Add comment noting LWG 3617 support

The resolution was implemented in r14-8752-g6f75149488b74a but I didn't
add the usual _GLIBCXX_RESOLVE_LIB_DEFECTS comment.

libstdc++-v3/ChangeLog:

* include/bits/std_function.h: Add comment about LWG 3617 being
supported.

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

diff --git a/libstdc++-v3/include/bits/std_function.h 
b/libstdc++-v3/include/bits/std_function.h
index 79b59466fe9d..bb8d8b9306cd 100644
--- a/libstdc++-v3/include/bits/std_function.h
+++ b/libstdc++-v3/include/bits/std_function.h
@@ -698,6 +698,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { using type = _Res(_Args...); };
 
 #if __cpp_explicit_this_parameter >= 202110L
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 3617. function/packaged_task deduction guides and deducing this
   template
 struct __function_guide_helper<_Res (*) (_Tp, _Args...) noexcept(_Nx)>
 { using type = _Res(_Args...); };


[gcc r15-2358] libstdc++: Fix -Wsign-compare warning in

2024-07-27 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:f793be787135ce7c52b169bf053af225b4828945

commit r15-2358-gf793be787135ce7c52b169bf053af225b4828945
Author: Jonathan Wakely 
Date:   Fri Jul 26 17:23:03 2024 +0100

libstdc++: Fix -Wsign-compare warning in 

Cast ptrdiff_t to size_t to avoid a -Wsign-compare warning. We can check
in __to_chars_i that the ptrdiff_t won't be negative, so that we know
the cast is safe.

libstdc++-v3/ChangeLog:

* include/std/charconv (__to_chars_16, __to_chars_10)
(__to_chars_8, __to_chars_2, __to_chars): Cast ptrdiff_t to
size_t for comparison.
(__to_chars_i): Check for first >= last instead of first == last
for initial sanity check.

Diff:
---
 libstdc++-v3/include/std/charconv | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/include/std/charconv 
b/libstdc++-v3/include/std/charconv
index e516e3b2da86..00c4f206922a 100644
--- a/libstdc++-v3/include/std/charconv
+++ b/libstdc++-v3/include/std/charconv
@@ -126,7 +126,7 @@ namespace __detail
 
   const unsigned __len = __to_chars_len(__val, __base);
 
-  if (__builtin_expect((__last - __first) < __len, 0))
+  if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
  __res.ptr = __last;
  __res.ec = errc::value_too_large;
@@ -166,7 +166,7 @@ namespace __detail
 
   const unsigned __len = (__to_chars_len_2(__val) + 3) / 4;
 
-  if (__builtin_expect((__last - __first) < __len, 0))
+  if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
  __res.ptr = __last;
  __res.ec = errc::value_too_large;
@@ -212,7 +212,7 @@ namespace __detail
 
   const unsigned __len = __to_chars_len(__val, 10);
 
-  if (__builtin_expect((__last - __first) < __len, 0))
+  if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
  __res.ptr = __last;
  __res.ec = errc::value_too_large;
@@ -246,7 +246,7 @@ namespace __detail
   else
__len = (__to_chars_len_2(__val) + 2) / 3;
 
-  if (__builtin_expect((__last - __first) < __len, 0))
+  if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
  __res.ptr = __last;
  __res.ec = errc::value_too_large;
@@ -288,7 +288,7 @@ namespace __detail
 
   const unsigned __len = __to_chars_len_2(__val);
 
-  if (__builtin_expect((__last - __first) < __len, 0))
+  if (__builtin_expect(size_t(__last - __first) < __len, 0))
{
  __res.ptr = __last;
  __res.ec = errc::value_too_large;
@@ -323,7 +323,7 @@ namespace __detail
   using _Up = __detail::__unsigned_least_t<_Tp>;
   _Up __unsigned_val = __value;
 
-  if (__first == __last) [[__unlikely__]]
+  if (__first >= __last) [[__unlikely__]]
return { __last, errc::value_too_large };
 
   if (__value == 0)


[gcc r15-2359] Fold ctz(-x) and ctz(abs(x)) as ctz(x) in match.pd.

2024-07-27 Thread Roger Sayle via Gcc-cvs
https://gcc.gnu.org/g:928116e94a5a8a995dffd926af58abfa7286e78e

commit r15-2359-g928116e94a5a8a995dffd926af58abfa7286e78e
Author: Roger Sayle 
Date:   Sat Jul 27 15:16:19 2024 +0100

Fold ctz(-x) and ctz(abs(x)) as ctz(x) in match.pd.

The subject line pretty much says it all; the count-trailing-zeros function
of -X and abs(X) produce the same result as count-trailing-zeros of X.
This transformation eliminates a negation which may potentially overflow
with an equivalent expression that doesn't [much like the analogous
abs(-X) simplification in match.pd].

I'd noticed this -X equivalence, which isn't mentioned in Hacker's Delight,
investigating whether ranger's non_zero_bits can help determine whether
an integer variable may be converted to a floating point type exactly
(without raising FE_INEXACT), but it turns out this observation isn't
novel, as (disappointingly) LLVM already performs this same folding.

2024-07-27  Roger Sayle  
Andrew Pinski  

gcc/ChangeLog
* match.pd (ctz (-X) => ctz (X)): New simplification.
(ctz (abs (X)) => ctz (X)): Likewise.

gcc/testsuite/ChangeLog
* gcc.dg/fold-ctz-1.c: New test case.
* gcc.dg/fold-ctz-2.c: Likewise.

Diff:
---
 gcc/match.pd  | 6 ++
 gcc/testsuite/gcc.dg/fold-ctz-1.c | 9 +
 gcc/testsuite/gcc.dg/fold-ctz-2.c | 9 +
 3 files changed, 24 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index b2e7d61790df..1c8601229e3d 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -9102,6 +9102,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
 /* CTZ simplifications.  */
 (for ctz (CTZ)
+ /* ctz (-X) => ctz (X).  ctz (abs (X)) => ctz (X).  */
+ (for op (negate abs)
+  (simplify
+   (ctz (nop_convert?@0 (op @1)))
+(with { tree t = TREE_TYPE (@0); }
+ (ctz (convert:t @1)
  (for op (ge gt le lt)
   cmp (eq eq ne ne)
   (simplify
diff --git a/gcc/testsuite/gcc.dg/fold-ctz-1.c 
b/gcc/testsuite/gcc.dg/fold-ctz-1.c
new file mode 100644
index ..dcc444cbbb6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-ctz-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int x)
+{
+  return __builtin_ctz (-x);
+}
+
+/* { dg-final { scan-tree-dump-not "-x_" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/fold-ctz-2.c 
b/gcc/testsuite/gcc.dg/fold-ctz-2.c
new file mode 100644
index ..c685698f31e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-ctz-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int x)
+{
+  return __builtin_ctz (__builtin_abs (x));
+}
+
+/* { dg-final { scan-tree-dump-not "ABS_EXPR" "optimized"} } */


[gcc r15-2361] c++: ICE with concept, local class, and lambda [PR115561]

2024-07-27 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:3129a2ed6a764c0687efaca9eba53dcf12d1d8a0

commit r15-2361-g3129a2ed6a764c0687efaca9eba53dcf12d1d8a0
Author: Jason Merrill 
Date:   Fri Jul 26 16:53:03 2024 -0400

c++: ICE with concept, local class, and lambda [PR115561]

Here when we want to synthesize methods for foo()::B maybe_push_to_top_level
calls push_function_context, which sets cfun to a dummy value; later
finish_call_expr tries to set something in
cp_function_chain (i.e. cfun->language), which isn't set.  Many places in
the compiler check cfun && cp_function_chain to avoid this problem; here we
also want to check !cp_unevaluated_operand, like set_flags_from_callee does.

PR c++/115561

gcc/cp/ChangeLog:

* semantics.cc (finish_call_expr): Check cp_unevaluated_operand.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-lambda21.C: New test.

Diff:
---
 gcc/cp/semantics.cc|  2 +-
 gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C | 69 ++
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 0f122b839c5f..a9abf32e01ff 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2968,7 +2968,7 @@ finish_call_expr (tree fn, vec **args, bool 
disallow_virtual,
 -Wredundant-move warning.  */
  suppress_warning (result, OPT_Wpessimizing_move);
 
- if (cfun)
+ if (cfun && cp_function_chain && !cp_unevaluated_operand)
{
  bool abnormal = true;
  for (lkp_iterator iter (maybe_get_fns (fn)); iter; ++iter)
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C
new file mode 100644
index ..8d701cd4bbc4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda21.C
@@ -0,0 +1,69 @@
+// PR c++/115561
+// { dg-do compile { target c++20 } }
+
+template
+auto declval() noexcept -> _Tp&&;
+
+template
+struct enable_if
+{ };
+
+template
+struct enable_if
+{ using type = _Tp; };
+
+template
+using enable_if_t = typename enable_if<_Cond, _Tp>::type;
+
+template
+struct is_void
+{ static constexpr bool value = false;  };
+
+template
+using invoke_result_t =
+decltype(declval()(declval()...));
+
+template
+using iter_reference_t = decltype(*declval());
+
+struct iter_move_fn
+{
+template
+constexpr
+auto operator() (I &&i)  -> void;
+} iter_move;
+
+template
+using iter_rvalue_reference_t = decltype(iter_move(declval()));
+
+template
+concept same_as = true;
+
+template
+concept readable_concept_ =
+same_as, iter_rvalue_reference_t>;
+
+template
+concept indirectly_readable =
+readable_concept_>;
+
+template
+using indirect_result_t =
+enable_if_t,
+invoke_result_t>>;
+
+template
+concept transformable =
+   (!is_void>::value);
+
+template
+requires transformable
+constexpr void transform(I, Fun)
+{
+}
+
+void foo()
+{
+struct B {};
+(void) transform((B*)nullptr, [](B) {return 0; });
+}


[gcc r15-2360] c++: improve C++ testsuite default versions

2024-07-27 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:dab0f35fcb4dd3ba584422013096c4ebc6bff90d

commit r15-2360-gdab0f35fcb4dd3ba584422013096c4ebc6bff90d
Author: Jason Merrill 
Date:   Fri Jul 26 15:10:50 2024 -0400

c++: improve C++ testsuite default versions

I wanted to add more cases to the setting of std_list in g++-dg.exp, but
didn't want to do a full scan through the file for each case.  So this patch
improves that in two ways: first, by extracting all interesting lines on a
single pass; second, by generating the list more flexibly: now we test every
version mentioned explicitly in the testcase, plus a few more if fewer than
three are mentioned.

This also lowers changes from testing four to three versions for most
testcases: the current default and the earliest and latest versions.  This
will reduce testing of C++14 and C++20 modes, and increase testing of C++26
mode.  C++ front-end developers are encouraged to set the
GXX_TESTSUITE_STDS environment variable to test more modes.

gcc/testsuite/ChangeLog:

* lib/gcc-dg.exp (get_matching_lines): New.
* lib/g++-dg.exp: Improve std_list selection.

Diff:
---
 gcc/testsuite/lib/g++-dg.exp | 45 ++--
 gcc/testsuite/lib/gcc-dg.exp | 13 +
 2 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/gcc/testsuite/lib/g++-dg.exp b/gcc/testsuite/lib/g++-dg.exp
index 52fba75c4a32..991be4d38677 100644
--- a/gcc/testsuite/lib/g++-dg.exp
+++ b/gcc/testsuite/lib/g++-dg.exp
@@ -53,21 +53,38 @@ proc g++-dg-runtest { testcases flags default-extra-flags } 
{
if { [llength $gpp_std_list] > 0 } {
set std_list $gpp_std_list
} else {
-   # If the test requires a newer C++ version than which
-   # is tested by default, use that C++ version for that
-   # single test.  Or if a test checks behavior specifically for
-   # one C++ version, include that version in the default list.
-   # These should be adjusted whenever the default std_list is
-   # updated or newer C++ effective target is added.
-   if [search_for $test "\{ dg-do * \{ target c++23"] {
-   set std_list { 23 26 }
-   } elseif [search_for $test "\{ dg-do * \{ target c++26"] {
-   set std_list { 26 }
-   } elseif [search_for $test "c++11_only"] {
-   set std_list { 98 11 14 20 }
-   } else {
-   set std_list { 98 14 17 20 }
+   # If the test mentions specific C++ versions, test those.
+   set lines [get_matching_lines $test {\{ dg* c++[0-9][0-9]}]
+   set std_list {}
+   set low 0
+   foreach line $lines {
+   regexp {c\+\+([0-9][0-9])} $line -> ver
+   lappend std_list $ver
+
+   if { $ver == 98 } {
+   # Leave low alone.
+   } elseif { [regexp {dg-do|dg-require-effective-target} 
$line] } {
+   set low $ver
+   }
}
+   #verbose "low: $low" 1
+
+   set std_list [lsort -unique $std_list]
+
+   # If fewer than 3 specific versions are mentioned, add more.
+   # The order of this list is significant: first $cxx_default,
+   # then the oldest and newest, then others in rough order of
+   # importance based on test coverage and usage.
+   foreach ver { 17 98 26 11 20 14 23 } {
+   set cmpver $ver
+   if { $ver == 98 } { set cmpver 03 }
+   if { [llength $std_list] < 3
+&& $ver ni $std_list
+&& $cmpver > $low } {
+   lappend std_list $ver
+   }
+   }
+   verbose "std_list: $std_list" 1
}
set option_list { }
foreach x $std_list {
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 228c21d12071..992062103c12 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -574,6 +574,19 @@ proc search_for { file pattern } {
 return 0
 }
 
+# get_matching_lines -- return a list of matching lines in file
+proc get_matching_lines { file pattern } {
+set lines {}
+set fd [open $file r]
+while { [gets $fd cur_line]>=0 } {
+   if [string match "*$pattern*" $cur_line] then {
+   lappend lines $cur_line
+   }
+}
+close $fd
+return $lines
+}
+
 # Modified dg-runtest that can cycle through a list of optimization options
 # as c-torture does.
 proc gcc-dg-runtest { testcases flags default-extra-flags } {


[gcc r15-2362] c++: consteval propagation and templates [PR115986]

2024-07-27 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:a9e9f772c7488ac0c09dd92f28890bdab939771a

commit r15-2362-ga9e9f772c7488ac0c09dd92f28890bdab939771a
Author: Jason Merrill 
Date:   Fri Jul 26 17:20:18 2024 -0400

c++: consteval propagation and templates [PR115986]

Here the call to e() makes us decide to check d() for escalation at EOF, but
while checking it we try to fold_immediate 0_c, and get confused by the
template trees.  Let's not mess with escalation for function templates.

PR c++/115986

gcc/cp/ChangeLog:

* cp-gimplify.cc (remember_escalating_expr): Skip function
templates.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/consteval-prop21.C: New test.

Diff:
---
 gcc/cp/cp-gimplify.cc |  4 
 gcc/testsuite/g++.dg/cpp2a/consteval-prop21.C | 17 +
 2 files changed, 21 insertions(+)

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index e6629dea5fdc..6a5e4cf62ca1 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -53,6 +53,10 @@ static GTY(()) hash_set *deferred_escalating_exprs;
 static void
 remember_escalating_expr (tree t)
 {
+  if (uses_template_parms (t))
+/* Templates don't escalate, and cp_fold_immediate can get confused by
+   other template trees in the function body (c++/115986).  */
+return;
   if (!deferred_escalating_exprs)
 deferred_escalating_exprs = hash_set::create_ggc (37);
   deferred_escalating_exprs->add (t);
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-prop21.C 
b/gcc/testsuite/g++.dg/cpp2a/consteval-prop21.C
new file mode 100644
index ..debbda4f4259
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval-prop21.C
@@ -0,0 +1,17 @@
+// PR c++/115986
+// { dg-do compile { target c++20 } }
+
+template 
+constexpr int b(T) {
+  return 0;
+}
+consteval __uint128_t operator"" _c(const char*) { return 0; }
+constexpr char e() {
+  long f = true ? 0 : b(long(1));
+  return b(f);
+}
+template 
+void d() {
+  0_c;
+  static_assert(e());
+}