[PATCH] RISC-V: Enable full coverage vect tests

2023-10-10 Thread Juzhe-Zhong
I have analyzed all existing FAILs.

Except these following FAILs need to be addressed:
FAIL: gcc.dg/vect/slp-reduc-7.c -flto -ffat-lto-objects execution test
FAIL: gcc.dg/vect/slp-reduc-7.c execution test
FAIL: gcc.dg/vect/vect-cond-arith-2.c -flto -ffat-lto-objects  scan-tree-dump 
optimized " = \\.COND_(LEN_)?SUB"
FAIL: gcc.dg/vect/vect-cond-arith-2.c scan-tree-dump optimized " = 
\\.COND_(LEN_)?SUB"

All other FAILs are dumple fail can be ignored (Confirm ARM SVE also has such 
FAILs and didn't fix them on either tests or implementation).

Now, It's time to enable full coverage vect tests including vec_unpack, 
vec_pack, vec_interleave, ... etc.

To see what we are still missing:

Before this patch:

=== gcc Summary ===

# of expected passes182839
# of unexpected failures79
# of unexpected successes   11
# of expected failures  1275
# of unresolved testcases   4
# of unsupported tests  4223


After this patch:

=== gcc Summary ===

# of expected passes183411
# of unexpected failures93
# of unexpected successes   7
# of expected failures  1285
# of unresolved testcases   4
# of unsupported tests  4157

There is an important issue increased that I have noticed after this patch:

FAIL: gcc.dg/vect/vect-gather-1.c -flto -ffat-lto-objects  scan-tree-dump vect 
"Loop contains only SLP stmts"
FAIL: gcc.dg/vect/vect-gather-1.c scan-tree-dump vect "Loop contains only SLP 
stmts"
FAIL: gcc.dg/vect/vect-gather-3.c -flto -ffat-lto-objects  scan-tree-dump vect 
"Loop contains only SLP stmts"
FAIL: gcc.dg/vect/vect-gather-3.c scan-tree-dump vect "Loop contains only SLP 
stmts"

It has a related PR: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111721

I am gonna fix this first in the middle-end after commit this patch.

Ok for trunk ?

gcc/testsuite/ChangeLog:

* lib/target-supports.exp: Add RVV.

---
 gcc/testsuite/lib/target-supports.exp | 45 ---
 1 file changed, 33 insertions(+), 12 deletions(-)

diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index b454b07359a..8037dbcee53 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -7876,7 +7876,9 @@ proc check_effective_target_vect_sdot_qi { } {
 || [istarget aarch64*-*-*]
 || [istarget arm*-*-*]
 || ([istarget mips*-*-*]
-&& [et-is-effective-target mips_msa]) }}]
+&& [et-is-effective-target mips_msa])
+|| ([istarget riscv*-*-*]
+&& [check_effective_target_riscv_v]) }}]
 }
 
 # Return 1 if the target plus current options supports a vector
@@ -7891,7 +7893,9 @@ proc check_effective_target_vect_udot_qi { } {
 || [istarget arm*-*-*]
 || [istarget ia64-*-*]
 || ([istarget mips*-*-*]
-&& [et-is-effective-target mips_msa]) }}]
+&& [et-is-effective-target mips_msa])
+|| ([istarget riscv*-*-*]
+&& [check_effective_target_riscv_v]) }}]
 }
 
 # Return 1 if the target plus current options supports a vector
@@ -7918,7 +7922,9 @@ proc check_effective_target_vect_sdot_hi { } {
 || [istarget ia64-*-*]
 || [istarget i?86-*-*] || [istarget x86_64-*-*]
 || ([istarget mips*-*-*]
-&& [et-is-effective-target mips_msa]) }}]
+&& [et-is-effective-target mips_msa])
+|| ([istarget riscv*-*-*]
+&& [check_effective_target_riscv_v]) }}]
 }
 
 # Return 1 if the target plus current options supports a vector
@@ -7930,7 +7936,9 @@ proc check_effective_target_vect_udot_hi { } {
 return [check_cached_effective_target_indexed vect_udot_hi {
   expr { ([istarget powerpc*-*-*] && ![istarget powerpc-*-linux*paired*])
 || ([istarget mips*-*-*]
-&& [et-is-effective-target mips_msa]) }}]
+&& [et-is-effective-target mips_msa])
+|| ([istarget riscv*-*-*]
+&& [check_effective_target_riscv_v]) }}]
 }
 
 # Return 1 if the target plus current options supports a vector
@@ -7945,7 +7953,9 @@ proc check_effective_target_vect_usad_char { } {
  || ([istarget aarch64*-*-*]
  && ![check_effective_target_aarch64_sve])
  || ([istarget powerpc*-*-*]
- && [check_p9vector_hw_available])}}]
+ && [check_p9vector_hw_available])
+ || ([istarget riscv*-*-*]
+ && [check_effective_target_riscv_v]) }}]
 }
 
 # Return 1 if the target plus current options supports both signed
@@ -7971,8 +7981,10 @@ proc check_effective_target_vect_mulhrs_hi {} {
 # by power-of-2 operations on vectors of 4-byte integers.
 
 proc check_effective_target_vect_sdiv_pow2_si {} {
-return [expr { [istarget aarch64*-*-*]
-  && 

Re: [PATCH] Fix coroutine tests for libstdc++ gnu-version-namespace mode

2023-10-10 Thread François Dumont



On 08/10/2023 15:59, Iain Sandoe wrote:

Hi François,


On 23 Sep 2023, at 21:10, François Dumont  wrote:

I'm eventually fixing those tests the same way we manage this problem in 
libstdc++ testsuite.

testsuite: Add optional libstdc++ version namespace in expected diagnostic

 When libstdc++ is build with --enable-symvers=gnu-versioned-namespace 
diagnostics are
 showing this namespace, currently __8.

 gcc/testsuite/ChangeLog:

 * testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C: Add 
optional
 '__8' version namespace in expected diagnostic.
 * testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C: 
Likewise.
 * testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C: 
Likewise.
 * 
testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C: Likewise.
 * testsuite/g++.dg/coroutines/pr97438.C: Likewise.
 * testsuite/g++.dg/coroutines/ramp-return-b.C: Likewise.

Tested under Linux x86_64.

I'm contributing to libstdc++ so I already have write access.

Ok to commit ?

As author of the tests, this LGTM as a suitable fix for now (at least, once the 
main
patch to fix versioned namespaces lands).


I just realized it was a "go", no ? Then why after the main patch ?

The "main patch" do not fix the versioned namespace. It just makes it 
adopt the cxx11 abi.


This patch fixes a problem that is as old as the tests and that is 
totally unrelated with the main one. I just wanted to improve the 
situation so that versioned namespace mode do not look more buggy than 
necessary when someone (like you) run those.




However, IMO, this could become quite painful as more g++ tests make use of std 
headers
(which is not really optional for facilities like this that are tightly-coupled 
between the FE and
the library).

For the future, it does seem that a more complete solution might be to 
introduce a
testsuite-wide definition for the C++ versioned std:: introducer, so that we 
can update it in one
place as the version changes.

So (as a thought experiment):
  - we’d have something of the form “CXX_STD” as a tcl global
  - we’d add the presence/absence of versioning to the relevant site.exp (which
means recognising the versioning choice also in the GCC configure)
  - we’d migrate tests to using ${CXX_STD} instead of "std::__N”  in matches

… I guess an alternative could be to cook up some alternate warning/error/etc
match functions that cater for arbitrary inline namespaces but that seems 
like a much
more tricky and invasive testsuite change.

thoughts?


I considered amending gcc/testsuite/lib/prune.exp to simply remove the 
version from the diagnostic. But the reply on why it was not working 
scared me, so this patch.


https://gcc.gnu.org/pipermail/gcc/2023-September/242526.html



Re: committed [RISC-V]: Harden test scan patterns

2023-10-10 Thread Joern Rennecke
On Sat, 30 Sept 2023 at 22:12, Joern Rennecke
 wrote:

> Also, we might have different directives for not scanning in LTO sections -
> or just ignoring .ascii .  Or maybe the other way round - you have to do
> something special if you want to scan inside strings, and by default we
> don't look inside strings?
> LTO information uses ascii, and ISTR sometimes also a zero-terminated
> variant (asciiz?); There might also some string constant outputs, or stabs
> information.
> One possible rule I think might work is: if the RE doesn't mention a quote,
> don't scan what's quoted inside double quotes.  Although we might to have
> to look out for backslash-escaped quotes to find the proper end of a quoted
> string.

I've though about this some more, and we need something that's simple for
dejagnu and simple to describe.

So I propose we look at the first character of the regexp, and if it's neither
^ nor \ (neither caret nor backslash), we consider the regexp un-anchored,
and prepend ^[^"]* , so it won't allow a match after a double quote.
Then document this in sourcebuild.texi, with some mention of lto information
and stabs, and also mentioning that if you really want to match irrespective
of a leading quote, you can prepend ^.* to your regexp.
There are good reasons to be more specific with your regexps in general,
but the matches in LTO are particularily damaging because they appear
semi-random, so often escape a regression test when the test is made,
only to surface during somebody else's regression test.


Re: [committed] [PR target/93062] RISC-V: Handle long conditional branches for RISC-V

2023-10-10 Thread Jeff Law




On 10/10/23 18:24, Andrew Waterman wrote:

I remembered another concern since we discussed this patch privately.
Using ra for long calls results in a sequence that will corrupt the
return-address stack.
Yup.  We've actually got data on that internally, it's not showing up in 
a significant way in practice.



  I know nothing

about the complexity of register scavenging, but it would be nice to
opportunistically use a scratch register (other than t0), falling back
to ra only when necessary.
The nice thing about making $ra fixed is some can add a register 
scavenging approach, then fall back to $ra if they're unable to find a 
register to reuse.




Tangentially, I noticed the patch uses `jump label, ra' for far
branches but uses `call label' for far jumps.  These corrupt the RAS
in opposite ways (the former pops the RAS and the latter pushes it.
Any reason for using a different sequence in one than the other?
I'd noticed it as well -- that's the way it was in the patch that was 
already in Ventana's tree ;-)  My plan was to address that separately 
after dropping in enough infrastructure to allow me to force everything 
to be far branches for testing purposes.


jeff


[PATCH] RISC-V: Remove XFAIL of ssa-dom-cse-2.c

2023-10-10 Thread Juzhe-Zhong
Confirm RISC-V is able to CSE this case no matter whether we enable RVV or not.

Remove XFAIL,  to fix:
XPASS: gcc.dg/tree-ssa/ssa-dom-cse-2.c scan-tree-dump optimized "return 28;"

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/ssa-dom-cse-2.c: Remove riscv.

---
 gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c
index a879d305971..5c89e3f8698 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c
@@ -27,4 +27,4 @@ foo ()
but the loop reads only one element at a time, and DOM cannot resolve these.
The same happens on powerpc depending on the SIMD support available.  */
 
-/* { dg-final { scan-tree-dump "return 28;" "optimized" { xfail { { alpha*-*-* 
hppa*64*-*-* nvptx*-*-* mmix-knuth-mmixware } || { { { lp64 && { powerpc*-*-* 
sparc*-*-* riscv*-*-* } } || aarch64_sve } || { arm*-*-* && { ! arm_neon } } } 
} } } } */
+/* { dg-final { scan-tree-dump "return 28;" "optimized" { xfail { { alpha*-*-* 
hppa*64*-*-* nvptx*-*-* mmix-knuth-mmixware } || { { { lp64 && { powerpc*-*-* 
sparc*-*-* } } || aarch64_sve } || { arm*-*-* && { ! arm_neon } } } } } } } */
-- 
2.36.3



RE: [PATCH] x86: set spincount 1 for x86 hybrid platform [PR109812]

2023-10-10 Thread Zhang, Jun
> -Original Message-
> From: Jakub Jelinek 
> Sent: Tuesday, October 10, 2023 3:57 PM
> To: Zhang, Jun 
> Cc: gcc-patches@gcc.gnu.org; ubiz...@gmail.com; Liu, Hongtao
> 
> Subject: Re: [PATCH] x86: set spincount 1 for x86 hybrid platform [PR109812]
> 
> On Tue, Oct 10, 2023 at 12:59:52PM +0800, Jun Zhang wrote:
> > include/ChangeLog:
> >
> > * omphook.h: define RUNOMPHOOK macro.
> 
> ChangeLog formatting.  The description should start with capital letter.  If 
> you add
> a new file, you should just mention : New file. or something similar.
> 
> But much more importantly, we don't do hooks like that in libgomp, it should 
> be
> better a static inline function where the name shows what it is doing (e.g.
> do_adjust_default_spincount), best in some already existing header (e.g. 
> wait.h),

Sorry, I don't know how to place wait.h. This patch is only for x86.
Wait.h is in libgomp/config/linux/.
if I directly place do_adjust_default_spincount in wait.h,
it maybe need #ifdef  __x86_64__, and also need a wait.h in include/
for other os platform.
if I create a new wait.h in libgomp/config/linux/x86/,
It need copy whole wait.h from libgomp/config/linux/, 
also need a wait.h in include/ for other os platform.
Could you help me?

> and best at the end of the if (!parse_spincount ("GOMP_SPINCOUNT",
> _spin_count_var)) block in env.c.
> >
> > libgomp/ChangeLog:
> >
> > * env.c (initialize_env): add RUNOMPHOOK macro.
> > * config/linux/x86/omphook.h: define RUNOMPHOOK macro.
> > ---
> >  include/omphook.h  |  1 +
> >  libgomp/config/linux/x86/omphook.h | 19 +++
> >  libgomp/env.c  |  3 +++
> >  3 files changed, 23 insertions(+)
> >  create mode 100644 include/omphook.h
> >  create mode 100644 libgomp/config/linux/x86/omphook.h
> >
> > diff --git a/include/omphook.h b/include/omphook.h new file mode
> > 100644 index 000..2ebe3ad57e6
> > --- /dev/null
> > +++ b/include/omphook.h
> > @@ -0,0 +1 @@
> > +#define RUNOMPHOOK()
> > diff --git a/libgomp/config/linux/x86/omphook.h
> > b/libgomp/config/linux/x86/omphook.h
> > new file mode 100644
> > index 000..aefb311cc07
> > --- /dev/null
> > +++ b/libgomp/config/linux/x86/omphook.h
> > @@ -0,0 +1,19 @@
> > +#ifdef __x86_64__
> > +#include "cpuid.h"
> > +
> > +/* only for x86 hybrid platform */
> 
> Comments should again start with capital letter and end with dot and 2 spaces
> before */
> 
> > +#define RUNOMPHOOK()  \
> > +  do \
> > +{ \
> > +  unsigned int eax, ebx, ecx, edx; \
> > +  if ((getenv ("GOMP_SPINCOUNT") == NULL) && (wait_policy < 0) \
> 
> Spurious ()s around the subcondition, the first shouldn't be tested when 
> placed
> right, if condition doesn't fit on one line, each subcondition should be on 
> separate
> line.
> 
> > + && __get_cpuid_count (7, 0, , , , ) \
> 
> If we don't have a macro for the CPUID.07H.0H:EDX[15] bit, there should be a
> comment which says what that bit is.
> 
> > + && ((edx >> 15) & 1)) \
> > +   gomp_spin_count_var = 1LL; \
> > +  if (gomp_throttled_spin_count_var > gomp_spin_count_var) \
> > +   gomp_throttled_spin_count_var = gomp_spin_count_var; \
> 
> The above 2 lines won't be needed if placed right.
> 
>   Jakub



[PATCH] early outs for functions in rs6000.cc

2023-10-10 Thread Jiufu Guo
Hi,

There are some piece of code like below in rs6000.cc:

 ...
 if (xx)
   return x;
 else if (yy)
   return y;
 ... //else if chain
 else
   return d;

Using early outs would be more preferable for this kind of code.

The whole function rs6000_emit_set_long_const and num_insns_constant_gpr
are refined.  And similar code are also restuctured in rs6000.cc.

This patch pass bootstrap and regtest on ppc64{,le}.
Is this ok for trunk?

BR,
Jeff (Jiufu Guo)

gcc/ChangeLog:

* config/rs6000/rs6000.cc (vspltis_shifted): Adopt early outs.
(rs6000_cost_data::determine_suggested_unroll_factor): Likewise.
(num_insns_constant_gpr): Likewise.
(easy_altivec_constant): Likewise.
(output_vec_const_move): Likewise.
(rs6000_expand_vector_set): Likewise.
(rs6000_legitimize_address): Likewise.
(rs6000_emit_set_long_const): Likewise.
(rs6000_preferred_reload_class): Likewise.
(rs6000_can_change_mode_class): Likewise.
(rs6000_output_move_128bit): Likewise.
(rs6000_emit_vector_cond_expr): Likewise.
(adjacent_mem_locations): Likewise.
(is_fusable_store): Likewise.
(insn_terminates_group_p): Likewise.
(rs6000_elf_reloc_rw_mask): Likewise.
(rs6000_rtx_costs): Likewise.
(rs6000_scalar_mode_supported_p): Likewise.
(rs6000_update_ipa_fn_target_info): Likewise.
(reg_to_non_prefixed): Likewise.
(rs6000_split_logical_inner): Likewise.
(rs6000_opaque_type_invalid_use_p): Likewise.

---
 gcc/config/rs6000/rs6000.cc | 495 ++--
 1 file changed, 249 insertions(+), 246 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index d10d22a5816..43681d9eb08 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -5522,24 +5522,22 @@ rs6000_cost_data::determine_suggested_unroll_factor 
(loop_vec_info loop_vinfo)
to vectorize it with the unrolled VF any more if the actual iteration
count is in between.  */
 return 1;
-  else
-{
-  unsigned int epil_niter_unr = est_niter % unrolled_vf;
-  unsigned int epil_niter = est_niter % vf;
-  /* Even if we have partial vector support, it can be still inefficent
-to calculate the length when the iteration count is unknown, so
-only expect it's good to unroll when the epilogue iteration count
-is not bigger than VF (only one time length calculation).  */
-  if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
- && epil_niter_unr <= vf)
-   return uf;
-  /* Without partial vector support, conservatively unroll this when
-the epilogue iteration count is less than the original one
-(epilogue execution time wouldn't be longer than before).  */
-  else if (!LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
-  && epil_niter_unr <= epil_niter)
-   return uf;
-}
+
+  unsigned int epil_niter_unr = est_niter % unrolled_vf;
+  unsigned int epil_niter = est_niter % vf;
+  /* Even if we have partial vector support, it can be still inefficent
+ to calculate the length when the iteration count is unknown, so
+ only expect it's good to unroll when the epilogue iteration count
+ is not bigger than VF (only one time length calculation).  */
+  if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) && epil_niter_unr <= 
vf)
+return uf;
+
+  /* Without partial vector support, conservatively unroll this when
+ the epilogue iteration count is less than the original one
+ (epilogue execution time wouldn't be longer than before).  */
+  if (!LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
+  && epil_niter_unr <= epil_niter)
+return uf;
 
   return 1;
 }
@@ -6044,35 +6042,31 @@ num_insns_constant_gpr (HOST_WIDE_INT value)
 return 1;
 
   /* constant loadable with addis */
-  else if ((value & 0x) == 0
-  && (value >> 31 == -1 || value >> 31 == 0))
+  if ((value & 0x) == 0 && (value >> 31 == -1 || value >> 31 == 0))
 return 1;
 
   /* PADDI can support up to 34 bit signed integers.  */
-  else if (TARGET_PREFIXED && SIGNED_INTEGER_34BIT_P (value))
+  if (TARGET_PREFIXED && SIGNED_INTEGER_34BIT_P (value))
 return 1;
 
-  else if (TARGET_POWERPC64)
-{
-  HOST_WIDE_INT low = sext_hwi (value, 32);
-  HOST_WIDE_INT high = value >> 31;
+  if (!TARGET_POWERPC64)
+return 2;
 
-  if (high == 0 || high == -1)
-   return 2;
+  /* TARGET_POWERPC64 */
+  HOST_WIDE_INT low = sext_hwi (value, 32);
+  HOST_WIDE_INT high = value >> 31;
+
+  if (high == 0 || high == -1)
+return 2;
 
-  high >>= 1;
+  high >>= 1;
 
-  if (low == 0 || low == high)
-   return num_insns_constant_gpr (high) + 1;
-  else if (high == 0)
-   return num_insns_constant_gpr (low) + 1;
-  else
-   return (num_insns_constant_gpr (high)
-   + num_insns_constant_gpr (low) + 1);
-}

RE: [PATCH] RISC-V Regression: Make pattern match more accurate of vect-live-2.c

2023-10-10 Thread Li, Pan2
Committed, thanks Jeff.

Pan

-Original Message-
From: Jeff Law  
Sent: Tuesday, October 10, 2023 11:26 PM
To: Juzhe-Zhong ; gcc-patches@gcc.gnu.org
Cc: rguent...@suse.de
Subject: Re: [PATCH] RISC-V Regression: Make pattern match more accurate of 
vect-live-2.c



On 10/10/23 08:57, Juzhe-Zhong wrote:
> Like previous patch:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632400.html
> https://patchwork.sourceware.org/project/gcc/patch/dde89b9e-49a0-d70b-0906-fb3022cac...@gmail.com/
> 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.dg/vect/vect-live-2.c: Make pattern match more accurate.
OK
jeff


RE: [PATCH] RISC-V Regression: Fix FAIL of vect-multitypes-16.c for RVV

2023-10-10 Thread Li, Pan2
Committed, thanks Jeff.

Pan

-Original Message-
From: Jeff Law  
Sent: Tuesday, October 10, 2023 11:29 PM
To: Juzhe-Zhong ; gcc-patches@gcc.gnu.org
Cc: rguent...@suse.de
Subject: Re: [PATCH] RISC-V Regression: Fix FAIL of vect-multitypes-16.c for RVV



On 10/10/23 08:49, Juzhe-Zhong wrote:
> As Richard suggested: 
> https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632288.html
> 
> Add vect_ext_char_longlong to fix FAIL for RVV.
> 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.dg/vect/vect-multitypes-16.c: Adapt check for RVV.
>   * lib/target-supports.exp: Add vect_ext_char_longlong property.
OK
jeff


[PATCH] MATCH: [PR111282] Simplify `a & (b ^ ~a)` to `a & b`

2023-10-10 Thread Andrew Pinski
While `a & (b ^ ~a)` is optimized to `a & b` on the rtl level,
it is always good to optimize this at the gimple level and allows
us to match a few extra things including where a is a comparison.

Note I had to update/change the testcase and-1.c to avoid matching
this case as we can match -2 and 1 as bitwise inversions.

PR tree-optimization/111282

gcc/ChangeLog:

* match.pd (`a & ~(a ^ b)`, `a & (a == b)`,
`a & ((~a) ^ b)`): New patterns.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/and-1.c: Update testcase to avoid
matching `~1 & (a ^ 1)` simplification.
* gcc.dg/tree-ssa/bitops-6.c: New test.
---
 gcc/match.pd | 20 ++
 gcc/testsuite/gcc.dg/tree-ssa/and-1.c|  6 ++---
 gcc/testsuite/gcc.dg/tree-ssa/bitops-6.c | 33 
 3 files changed, 56 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bitops-6.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 49740d189a7..26b05c157c1 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1358,6 +1358,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   && (!wascmp || element_precision (type) == 1))
   (bit_ior @0 (bit_not @2)
 
+/* a & ~(a ^ b)  -->  a & b  */
+(simplify
+ (bit_and:c @0 (bit_not (bit_xor:c @0 @1)))
+ (bit_and @0 @1))
+
+/* a & (a == b)  -->  a & b (boolean version of the above). */
+(simplify
+ (bit_and:c @0 (nop_convert? (eq:c @0 @1)))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+  && TYPE_PRECISION (TREE_TYPE (@0)) == 1)
+  (bit_and @0 @1)))
+
+/* a & ((~a) ^ b)  -->  a & b (alt version of the above 2) */
+(simplify
+ (bit_and:c @0 (bit_xor:c @1 @2))
+ (with { bool wascmp; }
+ (if (bitwise_inverted_equal_p (@0, @1, wascmp)
+  && (!wascmp || element_precision (type) == 1))
+  (bit_and @0 @2
+
 /* (a | b) | (a &^ b)  -->  a | b  */
 (for op (bit_and bit_xor)
  (simplify
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/and-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/and-1.c
index 276c2b9bd8a..27d38907eea 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/and-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/and-1.c
@@ -2,10 +2,10 @@
 /* { dg-options "-O -fdump-tree-optimized-raw" } */
 
 int f(int in) {
-  in = in | 3;
-  in = in ^ 1;
+  in = in | 7;
+  in = in ^ 3;
   in = (in & ~(unsigned long)1);
   return in;
 }
 
-/* { dg-final { scan-tree-dump-not "bit_and_expr" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "bit_and_expr, "  "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitops-6.c 
b/gcc/testsuite/gcc.dg/tree-ssa/bitops-6.c
new file mode 100644
index 000..e6ab2fd6c71
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/bitops-6.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized-raw" } */
+/* PR tree-optimization/111282 */
+
+
+int f(int a, int b)
+{
+  return a & (b ^ ~a); // a & b
+}
+
+_Bool fb(_Bool x, _Bool y)
+{
+  return x & (y ^ !x); // x & y
+}
+
+int fa(int w, int z)
+{
+  return (~w) & (w ^ z); // ~w & z
+}
+
+int fcmp(int x, int y)
+{
+  _Bool a = x == 2;
+  _Bool b = y == 1;
+  return a & (b ^ !a); // (x == 2) & (y == 1)
+}
+
+/* { dg-final { scan-tree-dump-not   "bit_xor_expr, "   "optimized" } } */
+/* { dg-final { scan-tree-dump-times "bit_and_expr, " 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "bit_not_expr, " 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-not   "ne_expr, ""optimized" } } */
+/* { dg-final { scan-tree-dump-times "eq_expr, "  2 "optimized" } } */
+
-- 
2.39.3



[PATCH V1] use more get_range_query

2023-10-10 Thread Jiufu Guo
Hi,

For "get_global_range_query" SSA_NAME_RANGE_INFO can be queried.
For "get_range_query", it could get more context-aware range info.
And look at the implementation of "get_range_query",  it returns
global range if no local fun info.

So, if not quering for SSA_NAME and not chaning the IL, it would
be ok to use get_range_query to replace get_global_range_query.

Patch https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630389.html,
Uses get_range_query could handle more cases.

Compare with previous version:
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632401.html
This patch remove some unsafe replacement.

Pass bootstrap & regtest on ppc64{,le} and x86_64.
Is this ok for trunk.


BR,
Jeff (Jiufu Guo)

gcc/ChangeLog:

* fold-const.cc (expr_not_equal_to): Replace get_global_range_query
by get_range_query.
* gimple-fold.cc (size_must_be_zero_p): Likewise.
* gimple-range-fold.cc (fur_source::fur_source): Likewise.
* gimple-ssa-warn-access.cc (check_nul_terminated_array): Likewise.
* tree-dfa.cc (get_ref_base_and_extent): Likewise.

---
 gcc/fold-const.cc | 6 +-
 gcc/gimple-fold.cc| 6 ++
 gcc/gimple-range-fold.cc  | 4 +---
 gcc/gimple-ssa-warn-access.cc | 2 +-
 gcc/tree-dfa.cc   | 5 +
 5 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 4f8561509ff..15134b21b9f 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -11056,11 +11056,7 @@ expr_not_equal_to (tree t, const wide_int )
   if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
return false;
 
-  if (cfun)
-   get_range_query (cfun)->range_of_expr (vr, t);
-  else
-   get_global_range_query ()->range_of_expr (vr, t);
-
+  get_range_query (cfun)->range_of_expr (vr, t);
   if (!vr.undefined_p () && !vr.contains_p (w))
return true;
   /* If T has some known zero bits and W has any of those bits set,
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index dc89975270c..853edd9e5d4 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -876,10 +876,8 @@ size_must_be_zero_p (tree size)
   wide_int zero = wi::zero (TYPE_PRECISION (type));
   value_range valid_range (type, zero, ssize_max);
   value_range vr;
-  if (cfun)
-get_range_query (cfun)->range_of_expr (vr, size);
-  else
-get_global_range_query ()->range_of_expr (vr, size);
+  get_range_query (cfun)->range_of_expr (vr, size);
+
   if (vr.undefined_p ())
 vr.set_varying (TREE_TYPE (size));
   vr.intersect (valid_range);
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index d1945ccb554..6e9530c3d7f 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -50,10 +50,8 @@ fur_source::fur_source (range_query *q)
 {
   if (q)
 m_query = q;
-  else if (cfun)
-m_query = get_range_query (cfun);
   else
-m_query = get_global_range_query ();
+m_query = get_range_query (cfun);
   m_gori = NULL;
 }
 
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index fcaff128d60..e439d1b9b68 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -332,7 +332,7 @@ check_nul_terminated_array (GimpleOrTree expr, tree src, 
tree bound)
 {
   Value_Range r (TREE_TYPE (bound));
 
-  get_global_range_query ()->range_of_expr (r, bound);
+  get_range_query (cfun)->range_of_expr (r, bound);
 
   if (r.undefined_p () || r.varying_p ())
return true;
diff --git a/gcc/tree-dfa.cc b/gcc/tree-dfa.cc
index af8e9243947..5355af2c869 100644
--- a/gcc/tree-dfa.cc
+++ b/gcc/tree-dfa.cc
@@ -531,10 +531,7 @@ get_ref_base_and_extent (tree exp, poly_int64 *poffset,
 
value_range vr;
range_query *query;
-   if (cfun)
- query = get_range_query (cfun);
-   else
- query = get_global_range_query ();
+   query = get_range_query (cfun);
 
if (TREE_CODE (index) == SSA_NAME
&& (low_bound = array_ref_low_bound (exp),
-- 
2.25.1



Re: [committed] [PR target/93062] RISC-V: Handle long conditional branches for RISC-V

2023-10-10 Thread Andrew Waterman
I remembered another concern since we discussed this patch privately.
Using ra for long calls results in a sequence that will corrupt the
return-address stack.  Corrupting the RAS is potentially more costly
than mispredicting a branch, since it can result in a cascading
sequence of mispredictions as the program returns up the stack.  Of
course, if these long calls are dynamically quite rare, this isn't the
end of the world.  But it's always preferable to use a register other
than ra or t0 to avoid this performance reduction.  I know nothing
about the complexity of register scavenging, but it would be nice to
opportunistically use a scratch register (other than t0), falling back
to ra only when necessary.

Tangentially, I noticed the patch uses `jump label, ra' for far
branches but uses `call label' for far jumps.  These corrupt the RAS
in opposite ways (the former pops the RAS and the latter pushes it.
Any reason for using a different sequence in one than the other?



On Tue, Oct 10, 2023 at 3:11 PM Jeff Law  wrote:
>
>
> Ventana has had a variant of this patch from Andrew W. in its tree for
> at least a year.   I'm dusting it off and submitting it on Andrew's behalf.
>
> There's multiple approaches we could be using here.
>
> First we could make $ra fixed and use it as the scratch register for the
> long branch sequences.
>
> Second, we could add a match_scratch to all the conditional branch
> patterns and allow the register allocator to assign the scratch register
> from the pool of GPRs.
>
> Third we could do register scavenging.  This can usually work, though it
> can get complex in some scenarios.
>
> Forth we could use trampolines for extended reach.
>
> Andrew's original patch did a bit of the first approach (make $ra fixed)
> and mostly the second approach.  The net is it was probably the worst in
> terms of impacting code generation -- we lost a register *and* forced
> every branch instruction to get a scratch register allocated.
>
> I had expected the second approach to produce better code than the
> first, but that wasn't actually the case in practice.  It's probably a
> combination of allocating a GPR at every branch point (even with a life
> of a single insn, there's a cost) and perhaps the additional operands on
> conditional branches spoiling simplistic pattern matching in one or more
> passes.
>
> In addition to performing better based on dynamic instruction counts,
> the first approach is significantly simpler to implement.  Given those
> two positives, that's what I've chosen to go with.  Yes it does remove
> $ra from the set of registers available, but the impact of that is *tiny*.
>
> If someone wanted to dive into one of the other approaches to address a
> real world impact, that's great.  If that happens I would strongly
> suggest also evaluating perlbench from spec2017.  It seems particularly
> sensitive to this issue in terms of approach #2's impact on code generation.
>
> I've built & regression tested this variant on the vt1 configuration
> without regressions.  Earlier versions have been bootstrapped as well.
>
> Pushed to the trunk,
>
> Jeff
>


[PATCH v2] c++: Improve diagnostics for constexpr cast from void*

2023-10-10 Thread Nathaniel Shead
On Mon, Oct 09, 2023 at 04:10:20PM -0400, Jason Merrill wrote:
> On 10/9/23 06:03, Nathaniel Shead wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu with
> > GXX_TESTSUITE_STDS=98,11,14,17,20,23,26,impcx.
> > 
> > -- >8 --
> > 
> > This patch improves the errors given when casting from void* in C++26 to
> > include the expected type if the type of the pointed-to object was
> > not similar to the casted-to type.
> > 
> > It also ensures (for all standard modes) that void* casts are checked
> > even for DECL_ARTIFICIAL declarations, such as lifetime-extended
> > temporaries, and is only ignored for cases where we know it's OK (heap
> > identifiers and source_location::current). This provides more accurate
> > diagnostics when using the pointer and ensures that some other casts
> > from void* are now correctly rejected.
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (is_std_source_location_current): New.
> > (cxx_eval_constant_expression): Only ignore cast from void* for
> > specific cases and improve other diagnostics.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp0x/constexpr-cast4.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >   gcc/cp/constexpr.cc  | 83 +---
> >   gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C |  7 ++
> >   2 files changed, 78 insertions(+), 12 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-cast4.C
> > 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 0f948db7c2d..f38d541a662 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -2301,6 +2301,36 @@ is_std_allocator_allocate (const constexpr_call 
> > *call)
> >   && is_std_allocator_allocate (call->fundef->decl));
> >   }
> > +/* Return true if FNDECL is std::source_location::current.  */
> > +
> > +static inline bool
> > +is_std_source_location_current (tree fndecl)
> > +{
> > +  if (!decl_in_std_namespace_p (fndecl))
> > +return false;
> > +
> > +  tree name = DECL_NAME (fndecl);
> > +  if (name == NULL_TREE || !id_equal (name, "current"))
> > +return false;
> > +
> > +  tree ctx = DECL_CONTEXT (fndecl);
> > +  if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx))
> > +return false;
> > +
> > +  name = DECL_NAME (TYPE_MAIN_DECL (ctx));
> > +  return name && id_equal (name, "source_location");
> > +}
> > +
> > +/* Overload for the above taking constexpr_call*.  */
> > +
> > +static inline bool
> > +is_std_source_location_current (const constexpr_call *call)
> > +{
> > +  return (call
> > + && call->fundef
> > + && is_std_source_location_current (call->fundef->decl));
> > +}
> > +
> >   /* Return true if FNDECL is __dynamic_cast.  */
> >   static inline bool
> > @@ -7850,33 +7880,62 @@ cxx_eval_constant_expression (const constexpr_ctx 
> > *ctx, tree t,
> > if (TYPE_PTROB_P (type)
> > && TYPE_PTR_P (TREE_TYPE (op))
> > && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op)))
> > -   /* Inside a call to std::construct_at or to
> > -  std::allocator::{,de}allocate, we permit casting from void*
> > +   /* Inside a call to std::construct_at,
> > +  std::allocator::{,de}allocate, or
> > +  std::source_location::current, we permit casting from void*
> >because that is compiler-generated code.  */
> > && !is_std_construct_at (ctx->call)
> > -   && !is_std_allocator_allocate (ctx->call))
> > +   && !is_std_allocator_allocate (ctx->call)
> > +   && !is_std_source_location_current (ctx->call))
> >   {
> > /* Likewise, don't error when casting from void* when OP is
> > uninit and similar.  */
> > tree sop = tree_strip_nop_conversions (op);
> > -   if (TREE_CODE (sop) == ADDR_EXPR
> > -   && VAR_P (TREE_OPERAND (sop, 0))
> > -   && DECL_ARTIFICIAL (TREE_OPERAND (sop, 0)))
> > +   tree decl = NULL_TREE;
> > +   if (TREE_CODE (sop) == ADDR_EXPR)
> > + decl = TREE_OPERAND (sop, 0);
> > +   if (decl
> > +   && VAR_P (decl)
> > +   && DECL_ARTIFICIAL (decl)
> > +   && (DECL_NAME (decl) == heap_identifier
> > +   || DECL_NAME (decl) == heap_uninit_identifier
> > +   || DECL_NAME (decl) == heap_vec_identifier
> > +   || DECL_NAME (decl) == heap_vec_uninit_identifier))
> >   /* OK */;
> > /* P2738 (C++26): a conversion from a prvalue P of type "pointer to
> >cv void" to a pointer-to-object type T unless P points to an
> >object whose type is similar to T.  */
> > -   else if (cxx_dialect > cxx23
> > -&& (sop = cxx_fold_indirect_ref (ctx, loc,
> > - TREE_TYPE (type), sop)))
> > +   else if (cxx_dialect > cxx23)
> >   {
> > -   r = build1 (ADDR_EXPR, type, sop);
> > -   break;
> > +   r = cxx_fold_indirect_ref (ctx, 

[PATCH v16 39/39] libstdc++: Optimize is_scalar trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_scalar trait by dispatching to
the new __is_scalar built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_scalar): Use __is_scalar built-in
trait.
(is_scalar_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 7e93923f44b..eb16a642575 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -775,11 +775,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_member_pointer;
 
   /// is_scalar
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scalar)
+  template
+struct is_scalar
+: public __bool_constant<__is_scalar(_Tp)>
+{ };
+#else
   template
 struct is_scalar
 : public __or_, is_enum<_Tp>, is_pointer<_Tp>,
is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type
 { };
+#endif
 
   /// is_compound
   template
@@ -3398,8 +3405,14 @@ template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
 #endif
 
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scalar)
+template 
+  inline constexpr bool is_scalar_v = __is_scalar(_Tp);
+#else
 template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_compound_v = !is_fundamental_v<_Tp>;
 
-- 
2.42.0



[PATCH v16 38/39] c++, libstdc++: Implement __is_scalar built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_scalar. The existent
__is_scalar codes were replaced with __is_scalar_type to avoid unintentional
macro replacement by the new built-in.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_scalar.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_SCALAR.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_scalar.
* g++.dg/ext/is_scalar.C: New test.
* g++.dg/tm/pr46567.C: Use __is_scalar_type instead.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_scalar): Rename to ...
(__is_scalar_type): ... this.
* include/bits/stl_algobase.h: Use __is_scalar_type instead.
* include/bits/valarray_array.h: Likewise.

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc|   3 +
 gcc/cp/cp-trait.def |   1 +
 gcc/cp/cp-trait.gperf   |   1 +
 gcc/cp/cp-trait.h   | 186 ++--
 gcc/cp/semantics.cc |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C|   3 +
 gcc/testsuite/g++.dg/ext/is_scalar.C|  31 
 gcc/testsuite/g++.dg/tm/pr46567.C   |  10 +-
 gcc/testsuite/g++.dg/torture/pr57107.C  |   4 +-
 libstdc++-v3/include/bits/cpp_type_traits.h |   2 +-
 libstdc++-v3/include/bits/stl_algobase.h|   8 +-
 libstdc++-v3/include/bits/valarray_array.h  |   2 +-
 12 files changed, 150 insertions(+), 105 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_scalar.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index b161c9b2c9e..78f100d2745 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3802,6 +3802,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_SAME:
   inform (loc, "  %qT is not the same as %qT", t1, t2);
   break;
+case CPTK_IS_SCALAR:
+  inform (loc, "  %qT is not a scalar type", t1);
+  break;
 case CPTK_IS_SIGNED:
   inform (loc, "  %qT is not a signed type", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b0faa4c8937..08a2780c929 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -86,6 +86,7 @@ DEFTRAIT_EXPR (IS_POINTER, "__is_pointer", 1)
 DEFTRAIT_EXPR (IS_POLYMORPHIC, "__is_polymorphic", 1)
 DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_SAME, "__is_same", 2)
+DEFTRAIT_EXPR (IS_SCALAR, "__is_scalar", 1)
 DEFTRAIT_EXPR (IS_SIGNED, "__is_signed", 1)
 DEFTRAIT_EXPR (IS_SCOPED_ENUM, "__is_scoped_enum", 1)
 DEFTRAIT_EXPR (IS_STD_LAYOUT, "__is_standard_layout", 1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index de0ba162e7a..ef51c713c58 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -66,6 +66,7 @@ struct cp_trait {
 "__is_polymorphic", CPTK_IS_POLYMORPHIC, 1, false
 "__is_reference", CPTK_IS_REFERENCE, 1, false
 "__is_same", CPTK_IS_SAME, 2, false
+"__is_scalar", CPTK_IS_SCALAR, 1, false
 "__is_signed", CPTK_IS_SIGNED, 1, false
 "__is_scoped_enum", CPTK_IS_SCOPED_ENUM, 1, false
 "__is_standard_layout", CPTK_IS_STD_LAYOUT, 1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index 6d1078de2fe..8c68af420f9 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -78,10 +78,10 @@ cp_trait_lookup::hash (const char *str, size_t len)
   126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
   126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
   126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
-  126, 126, 126, 126, 126,  20, 126,  40,  45,  50,
-   55,   0,   5,  15, 126,   0, 126, 126,  35,  10,
-   35,   0,  10, 126,  30,   5,   5,  16,  30, 126,
-  126,  10, 126, 126, 126, 126, 126, 126, 126, 126,
+  126, 126, 126, 126, 126,  40, 126,  25,  21,  50,
+0,   0,  30,  10, 126,   0, 126, 126,  25,   5,
+   50,   0,  61, 126,  10,  10,   5,   0,  15, 126,
+  126,   5, 126, 126, 126, 126, 126, 126, 126, 126,
   126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
   126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
   126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
@@ -116,7 +116,7 @@ cp_trait_lookup::find (const char *str, size_t len)
 {
   enum
 {
-  TOTAL_KEYWORDS = 61,
+  TOTAL_KEYWORDS = 62,
   MIN_WORD_LENGTH = 7,
   MAX_WORD_LENGTH = 37,
   MIN_HASH_VALUE = 7,
@@ -125,141 +125,143 @@ cp_trait_lookup::find (const char *str, size_t len)
 
   static const struct cp_trait wordlist[] =
 {
-#line 89 "../../gcc/cp/cp-trait.gperf"
+#line 90 "../../gcc/cp/cp-trait.gperf"
   {"__bases", CPTK_BASES, 1, true},
-#line 82 "../../gcc/cp/cp-trait.gperf"
-  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
+#line 52 "../../gcc/cp/cp-trait.gperf"

[PATCH v16 33/39] libstdc++: Optimize is_compound trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_compound trait by dispatching
to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_compound): Do not use __not_.
(is_compound_v): Use is_fundamental_v instead.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 88171e1a672..48d630a1478 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -784,7 +784,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// is_compound
   template
 struct is_compound
-: public __not_>::type { };
+: public __bool_constant::value> { };
 
   /// is_member_pointer
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer)
@@ -3387,7 +3387,7 @@ template 
 template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template 
-  inline constexpr bool is_compound_v = is_compound<_Tp>::value;
+  inline constexpr bool is_compound_v = !is_fundamental_v<_Tp>;
 
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer)
 template 
-- 
2.42.0



[PATCH v16 37/39] libstdc++: Optimize is_signed trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_signed trait by dispatching to
the new __is_signed built-in trait.

libstdc++-v3/ChangeLog:

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

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index f7d3815f332..7e93923f44b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -982,6 +982,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public __bool_constant<__is_abstract(_Tp)>
 { };
 
+  /// is_signed
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_signed)
+  template
+struct is_signed
+: public __bool_constant<__is_signed(_Tp)>
+{ };
+#else
   /// @cond undocumented
   template::value>
@@ -994,11 +1001,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
   /// @endcond
 
-  /// is_signed
   template
 struct is_signed
 : public __is_signed_helper<_Tp>::type
 { };
+#endif
 
   /// is_unsigned
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_unsigned)
@@ -3445,8 +3452,13 @@ template 
 template 
   inline constexpr bool is_final_v = __is_final(_Tp);
 
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_signed)
+template 
+  inline constexpr bool is_signed_v = __is_signed(_Tp);
+#else
 template 
   inline constexpr bool is_signed_v = is_signed<_Tp>::value;
+#endif
 
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_unsigned)
 template 
-- 
2.42.0



[PATCH v16 36/39] c++, libstdc++: Implement __is_signed built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_signed.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

libstdc++-v3/ChangeLog:

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

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

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c28dad702c3..b161c9b2c9e 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3802,6 +3802,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_SAME:
   inform (loc, "  %qT is not the same as %qT", t1, t2);
   break;
+case CPTK_IS_SIGNED:
+  inform (loc, "  %qT is not a signed type", t1);
+  break;
 case CPTK_IS_SCOPED_ENUM:
   inform (loc, "  %qT is not a scoped enum", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 0603b4a230f..b0faa4c8937 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -86,6 +86,7 @@ DEFTRAIT_EXPR (IS_POINTER, "__is_pointer", 1)
 DEFTRAIT_EXPR (IS_POLYMORPHIC, "__is_polymorphic", 1)
 DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_SAME, "__is_same", 2)
+DEFTRAIT_EXPR (IS_SIGNED, "__is_signed", 1)
 DEFTRAIT_EXPR (IS_SCOPED_ENUM, "__is_scoped_enum", 1)
 DEFTRAIT_EXPR (IS_STD_LAYOUT, "__is_standard_layout", 1)
 DEFTRAIT_EXPR (IS_TRIVIAL, "__is_trivial", 1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 90d05bca5c1..de0ba162e7a 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -66,6 +66,7 @@ struct cp_trait {
 "__is_polymorphic", CPTK_IS_POLYMORPHIC, 1, false
 "__is_reference", CPTK_IS_REFERENCE, 1, false
 "__is_same", CPTK_IS_SAME, 2, false
+"__is_signed", CPTK_IS_SIGNED, 1, false
 "__is_scoped_enum", CPTK_IS_SCOPED_ENUM, 1, false
 "__is_standard_layout", CPTK_IS_STD_LAYOUT, 1, false
 "__is_trivial", CPTK_IS_TRIVIAL, 1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index 75ab2b5edfa..6d1078de2fe 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 129, duplicates = 0 */
+/* maximum key range = 119, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136,  20, 136,  45,  35,  40,
-   60,   0,  55,   0, 136,   0, 136, 136,  10,  15,
-   35,   0,  10, 136,  10,  15,   5,  15,   0, 136,
-  136,  20, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
-  136, 136, 136, 136, 136, 

[PATCH v16 34/39] c++: Implement __is_unsigned built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_unsigned.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_unsigned.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_UNSIGNED.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc |   3 +
 gcc/cp/cp-trait.def  |   1 +
 gcc/cp/cp-trait.gperf|   1 +
 gcc/cp/cp-trait.h| 118 ---
 gcc/cp/semantics.cc  |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
 gcc/testsuite/g++.dg/ext/is_unsigned.C   |  47 +
 7 files changed, 120 insertions(+), 57 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_unsigned.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 3a7f968eae8..c28dad702c3 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3829,6 +3829,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_UNSIGNED:
+  inform (loc, "  %qT is not an unsigned type", t1);
+  break;
 case CPTK_IS_VOLATILE:
   inform (loc, "  %qT is not a volatile type", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index b2be7b7bbd7..0603b4a230f 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -94,6 +94,7 @@ 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_UNSIGNED, "__is_unsigned", 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)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 9050c36f105..90d05bca5c1 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -74,6 +74,7 @@ struct cp_trait {
 "__is_trivially_copyable", CPTK_IS_TRIVIALLY_COPYABLE, 1, false
 "__is_unbounded_array", CPTK_IS_UNBOUNDED_ARRAY, 1, false
 "__is_union", CPTK_IS_UNION, 1, false
+"__is_unsigned", CPTK_IS_UNSIGNED, 1, false
 "__is_volatile", CPTK_IS_VOLATILE, 1, false
 "__reference_constructs_from_temporary", CPTK_REF_CONSTRUCTS_FROM_TEMPORARY, 
2, false
 "__reference_converts_from_temporary", CPTK_REF_CONVERTS_FROM_TEMPORARY, 2, 
false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index 31fd5075f2d..75ab2b5edfa 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 97, duplicates = 0 */
+/* maximum key range = 129, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104,  20, 104,  45,  50,  40,
-5,   0,  55,   0, 104,   0, 104, 104,  10,  15,
-   35,   0,  10, 104,  10,  15,   5,   0,  20, 104,
-  104,  20, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
-  104, 104, 104, 104, 104, 104
+  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
+  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
+  136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
+  136, 136, 136, 136, 136, 136, 136, 136, 136, 

[PATCH v16 35/39] libstdc++: Optimize is_unsigned trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_unsigned trait by dispatching
to the new __is_unsigned built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_unsigned): Use __is_unsigned built-in
trait.
(is_unsigned_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 48d630a1478..f7d3815f332 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1001,10 +1001,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_unsigned
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_unsigned)
+  template
+struct is_unsigned
+: public __bool_constant<__is_unsigned(_Tp)>
+{ };
+#else
   template
 struct is_unsigned
 : public __and_, __not_>>::type
 { };
+#endif
 
   /// @cond undocumented
   template
@@ -3440,8 +3447,14 @@ template 
 
 template 
   inline constexpr bool is_signed_v = is_signed<_Tp>::value;
+
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_unsigned)
+template 
+  inline constexpr bool is_unsigned_v = __is_unsigned(_Tp);
+#else
 template 
   inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value;
+#endif
 
 template 
   inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
-- 
2.42.0



[PATCH v16 31/39] libstdc++: Optimize is_arithmetic trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_arithmetic trait by dispatching
to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

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

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 3acd843f2f2..cc466e0f606 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -726,10 +726,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   /// is_arithmetic
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_arithmetic)
+  template
+struct is_arithmetic
+: public __bool_constant<__is_arithmetic(_Tp)>
+{ };
+#else
   template
 struct is_arithmetic
 : public __or_, is_floating_point<_Tp>>::type
 { };
+#endif
 
   /// is_fundamental
   template
@@ -3344,8 +3351,14 @@ template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
 #endif
 
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_arithmetic)
+template 
+  inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+#else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
 
-- 
2.42.0



[PATCH v16 32/39] libstdc++: Optimize is_fundamental trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_fundamental trait by
dispatching to the new __is_arithmetic built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_fundamental_v): Use __is_arithmetic
built-in trait.
(is_fundamental): Likewise. Optimize the original implementation.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index cc466e0f606..88171e1a672 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -739,11 +739,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   /// is_fundamental
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_arithmetic)
+  template
+struct is_fundamental
+: public __bool_constant<__is_arithmetic(_Tp)
+ || is_void<_Tp>::value
+ || is_null_pointer<_Tp>::value>
+{ };
+#else
   template
 struct is_fundamental
-: public __or_, is_void<_Tp>,
-  is_null_pointer<_Tp>>::type
+: public __bool_constant::value
+ || is_void<_Tp>::value
+ || is_null_pointer<_Tp>::value>
 { };
+#endif
 
   /// is_object
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function) \
@@ -3354,13 +3364,15 @@ template 
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_arithmetic)
 template 
   inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp);
+template 
+  inline constexpr bool is_fundamental_v
+= __is_arithmetic(_Tp) || is_void_v<_Tp> || is_null_pointer_v<_Tp>;
 #else
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
-#endif
-
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+#endif
 
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function) \
  && _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
-- 
2.42.0



[PATCH v16 22/39] libstdc++: Optimize is_reference trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_reference trait by dispatching
to the new __is_reference built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_reference): Use __is_reference built-in
trait.
(is_reference_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 792213ebfe8..36ad9814047 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -682,6 +682,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Composite type categories.
 
   /// is_reference
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
+  template
+struct is_reference
+: public __bool_constant<__is_reference(_Tp)>
+{ };
+#else
   template
 struct is_reference
 : public false_type
@@ -696,6 +702,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_reference<_Tp&&>
 : public true_type
 { };
+#endif
 
   /// is_arithmetic
   template
@@ -3264,12 +3271,19 @@ template 
   inline constexpr bool is_class_v = __is_class(_Tp);
 template 
   inline constexpr bool is_function_v = is_function<_Tp>::value;
+
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
+template 
+  inline constexpr bool is_reference_v = __is_reference(_Tp);
+#else
 template 
   inline constexpr bool is_reference_v = false;
 template 
   inline constexpr bool is_reference_v<_Tp&> = true;
 template 
   inline constexpr bool is_reference_v<_Tp&&> = true;
+#endif
+
 template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
-- 
2.42.0



[PATCH v16 28/39] c++, libstdc++: Implement __is_pointer built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_pointer.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

libstdc++-v3/ChangeLog:

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

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

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 99a7e7247ce..c9d627fa782 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3787,6 +3787,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_POD:
   inform (loc, "  %qT is not a POD type", t1);
   break;
+case CPTK_IS_POINTER:
+  inform (loc, "  %qT is not a pointer", t1);
+  break;
 case CPTK_IS_POLYMORPHIC:
   inform (loc, "  %qT is not a polymorphic type", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 2add97ae749..c60724e869e 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -81,6 +81,7 @@ DEFTRAIT_EXPR (IS_NOTHROW_CONSTRUCTIBLE, 
"__is_nothrow_constructible", -1)
 DEFTRAIT_EXPR (IS_NOTHROW_CONVERTIBLE, "__is_nothrow_convertible", 2)
 DEFTRAIT_EXPR (IS_POINTER_INTERCONVERTIBLE_BASE_OF, 
"__is_pointer_interconvertible_base_of", 2)
 DEFTRAIT_EXPR (IS_POD, "__is_pod", 1)
+DEFTRAIT_EXPR (IS_POINTER, "__is_pointer", 1)
 DEFTRAIT_EXPR (IS_POLYMORPHIC, "__is_polymorphic", 1)
 DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_SAME, "__is_same", 2)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 8fbd67788d5..5d40e04f91c 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -61,6 +61,7 @@ struct cp_trait {
 "__is_nothrow_convertible", CPTK_IS_NOTHROW_CONVERTIBLE, 2, false
 "__is_pointer_interconvertible_base_of", 
CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF, 2, false
 "__is_pod", CPTK_IS_POD, 1, false
+"__is_pointer", CPTK_IS_POINTER, 1, false
 "__is_polymorphic", CPTK_IS_POLYMORPHIC, 1, false
 "__is_reference", CPTK_IS_REFERENCE, 1, false
 "__is_same", CPTK_IS_SAME, 2, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index ad2c2a2d250..ab783b161c7 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 109, duplicates = 0 */
+/* maximum key range = 92, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116,  20, 116,  40,   5,  40,
-   50,   0,  55,  10, 116,   0, 116, 116,   5,  25,
-   30,   0,   5, 116,  10,  15,   5,   0,  25, 116,
-  116,  20, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 

[PATCH v16 30/39] c++, libstdc++: Implement __is_arithmetic built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_arithmetic.

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

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

libstdc++-v3/ChangeLog:

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

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

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c9d627fa782..3a7f968eae8 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3714,6 +3714,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
+case CPTK_IS_ARITHMETIC:
+  inform (loc, "  %qT is not an arithmetic type", t1);
+  break;
 case CPTK_IS_ARRAY:
   inform (loc, "  %qT is not an array", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index c60724e869e..b2be7b7bbd7 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -59,6 +59,7 @@ DEFTRAIT_EXPR (HAS_UNIQUE_OBJ_REPRESENTATIONS, 
"__has_unique_object_representati
 DEFTRAIT_EXPR (HAS_VIRTUAL_DESTRUCTOR, "__has_virtual_destructor", 1)
 DEFTRAIT_EXPR (IS_ABSTRACT, "__is_abstract", 1)
 DEFTRAIT_EXPR (IS_AGGREGATE, "__is_aggregate", 1)
+DEFTRAIT_EXPR (IS_ARITHMETIC, "__is_arithmetic", 1)
 DEFTRAIT_EXPR (IS_ARRAY, "__is_array", 1)
 DEFTRAIT_EXPR (IS_ASSIGNABLE, "__is_assignable", 2)
 DEFTRAIT_EXPR (IS_BASE_OF, "__is_base_of", 2)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 5d40e04f91c..9050c36f105 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -39,6 +39,7 @@ struct cp_trait {
 "__has_virtual_destructor", CPTK_HAS_VIRTUAL_DESTRUCTOR, 1, false
 "__is_abstract", CPTK_IS_ABSTRACT, 1, false
 "__is_aggregate", CPTK_IS_AGGREGATE, 1, false
+"__is_arithmetic", CPTK_IS_ARITHMETIC, 1, false
 "__is_array", CPTK_IS_ARRAY, 1, false
 "__is_assignable", CPTK_IS_ASSIGNABLE, 2, false
 "__is_base_of", CPTK_IS_BASE_OF, 2, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index ab783b161c7..31fd5075f2d 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 92, duplicates = 0 */
+/* maximum key range = 97, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 20, 99, 40, 45, 40,
-   5,  0, 55, 10, 99,  0, 99, 99, 10, 25,
-  30,  0, 10, 99, 10, 15,  5,  0, 20, 99,
-  99, 10, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  

[PATCH v16 27/39] libstdc++: Optimize remove_pointer trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the remove_pointer trait by
dispatching to the new remove_pointer built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (remove_pointer): Use __remove_pointer
built-in trait.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 674d398c075..9c56d15c0b7 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2105,6 +2105,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // Pointer modifications.
 
+  /// remove_pointer
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_pointer)
+  template
+struct remove_pointer
+{ using type = __remove_pointer(_Tp); };
+#else
   template
 struct __remove_pointer_helper
 { using type = _Tp; };
@@ -2113,11 +2119,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct __remove_pointer_helper<_Tp, _Up*>
 { using type = _Up; };
 
-  /// remove_pointer
   template
 struct remove_pointer
 : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>>
 { };
+#endif
 
   template
 struct __add_pointer_helper
-- 
2.42.0



[PATCH v16 29/39] libstdc++: Optimize is_pointer trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_pointer trait by dispatching to
the new __is_pointer built-in trait.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_ptr): Use __is_pointer
built-in trait.
* include/std/type_traits (is_pointer): Likewise. Optimize its
implementation.
(is_pointer_v): Likewise.

Co-authored-by: Jonathan Wakely 
Signed-off-by: Ken Matsui 
---
 libstdc++-v3/include/bits/cpp_type_traits.h |  8 
 libstdc++-v3/include/std/type_traits| 44 +
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h 
b/libstdc++-v3/include/bits/cpp_type_traits.h
index 3711e4be526..4da1e7c407c 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -363,6 +363,13 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   //
   // Pointer types
   //
+#if __has_builtin(__is_pointer)
+  template
+struct __is_ptr : __truth_type<__is_pointer(_Tp)>
+{
+  enum { __value = __is_pointer(_Tp) };
+};
+#else
   template
 struct __is_ptr
 {
@@ -376,6 +383,7 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   enum { __value = 1 };
   typedef __true_type __type;
 };
+#endif
 
   //
   // An arithmetic type is an integer type or a floating point type
diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 9c56d15c0b7..3acd843f2f2 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -542,19 +542,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public true_type { };
 #endif
 
-  template
-struct __is_pointer_helper
+  /// is_pointer
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_pointer)
+  template
+struct is_pointer
+: public __bool_constant<__is_pointer(_Tp)>
+{ };
+#else
+  template
+struct is_pointer
 : public false_type { };
 
   template
-struct __is_pointer_helper<_Tp*>
+struct is_pointer<_Tp*>
 : public true_type { };
 
-  /// is_pointer
   template
-struct is_pointer
-: public __is_pointer_helper<__remove_cv_t<_Tp>>::type
-{ };
+struct is_pointer<_Tp* const>
+: public true_type { };
+
+  template
+struct is_pointer<_Tp* volatile>
+: public true_type { };
+
+  template
+struct is_pointer<_Tp* const volatile>
+: public true_type { };
+#endif
 
   /// is_lvalue_reference
   template
@@ -3254,8 +3268,22 @@ template 
   inline constexpr bool is_array_v<_Tp[_Num]> = true;
 #endif
 
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_pointer)
+template 
+  inline constexpr bool is_pointer_v = __is_pointer(_Tp);
+#else
 template 
-  inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
+  inline constexpr bool is_pointer_v = false;
+template 
+  inline constexpr bool is_pointer_v<_Tp*> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* volatile> = true;
+template 
+  inline constexpr bool is_pointer_v<_Tp* const volatile> = true;
+#endif
+
 template 
   inline constexpr bool is_lvalue_reference_v = false;
 template 
-- 
2.42.0



[PATCH v16 21/39] c++: Implement __is_reference built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_reference.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_reference.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_REFERENCE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc |   3 +
 gcc/cp/cp-trait.def  |   1 +
 gcc/cp/cp-trait.gperf|   1 +
 gcc/cp/cp-trait.h| 113 ---
 gcc/cp/semantics.cc  |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
 gcc/testsuite/g++.dg/ext/is_reference.C  |  34 +++
 7 files changed, 104 insertions(+), 55 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_reference.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 98b1f004a68..5cdb59d174e 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3787,6 +3787,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_POLYMORPHIC:
   inform (loc, "  %qT is not a polymorphic type", t1);
   break;
+case CPTK_IS_REFERENCE:
+  inform (loc, "  %qT is not a reference", t1);
+  break;
 case CPTK_IS_SAME:
   inform (loc, "  %qT is not the same as %qT", t1, t2);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 11fd70b3964..e867d9c4c47 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -81,6 +81,7 @@ DEFTRAIT_EXPR (IS_NOTHROW_CONVERTIBLE, 
"__is_nothrow_convertible", 2)
 DEFTRAIT_EXPR (IS_POINTER_INTERCONVERTIBLE_BASE_OF, 
"__is_pointer_interconvertible_base_of", 2)
 DEFTRAIT_EXPR (IS_POD, "__is_pod", 1)
 DEFTRAIT_EXPR (IS_POLYMORPHIC, "__is_polymorphic", 1)
+DEFTRAIT_EXPR (IS_REFERENCE, "__is_reference", 1)
 DEFTRAIT_EXPR (IS_SAME, "__is_same", 2)
 DEFTRAIT_EXPR (IS_SCOPED_ENUM, "__is_scoped_enum", 1)
 DEFTRAIT_EXPR (IS_STD_LAYOUT, "__is_standard_layout", 1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 32199a1fe9a..5989b84727f 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -61,6 +61,7 @@ struct cp_trait {
 "__is_pointer_interconvertible_base_of", 
CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF, 2, false
 "__is_pod", CPTK_IS_POD, 1, false
 "__is_polymorphic", CPTK_IS_POLYMORPHIC, 1, false
+"__is_reference", CPTK_IS_REFERENCE, 1, false
 "__is_same", CPTK_IS_SAME, 2, false
 "__is_scoped_enum", CPTK_IS_SCOPED_ENUM, 1, false
 "__is_standard_layout", CPTK_IS_STD_LAYOUT, 1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index 799fe2b792f..f0b4f96d4a9 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 89, duplicates = 0 */
+/* maximum key range = 94, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 20, 96, 40,  5, 40,
-  40,  0, 25, 10, 96,  0, 96, 96,  5, 25,
-  30,  0,  5, 96, 10, 15,  5,  0, 25, 96,
-  96, 20, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+  101, 101, 101, 101, 101,  20, 101,  40,   5,  40,
+   40,   0, 

[PATCH v16 25/39] libstdc++: Optimize is_object trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_object trait by dispatching to
the new __is_function and __is_reference built-in traits.

libstdc++-v3/ChangeLog:
* include/std/type_traits (is_object): Use __is_function and
__is_reference built-in traits.
(is_object_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index bd57488824b..674d398c075 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -725,11 +725,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_object
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function) \
+ && _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
+  template
+struct is_object
+: public __bool_constant::value)>
+{ };
+#else
   template
 struct is_object
 : public __not_<__or_, is_reference<_Tp>,
   is_void<_Tp>>>::type
 { };
+#endif
 
   template
 struct is_member_pointer;
@@ -3305,8 +3314,17 @@ template 
   inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 template 
   inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function) \
+ && _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
+template 
+  inline constexpr bool is_object_v
+= !(__is_function(_Tp) || __is_reference(_Tp) || is_void<_Tp>::value);
+#else
 template 
   inline constexpr bool is_object_v = is_object<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template 
-- 
2.42.0



[PATCH v16 26/39] c++: Implement __remove_pointer built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::remove_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __remove_pointer.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* semantics.cc (finish_trait_type): Handle CPTK_REMOVE_POINTER.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/cp-trait.def   |  1 +
 gcc/cp/cp-trait.gperf |  1 +
 gcc/cp/cp-trait.h | 32 +++---
 gcc/cp/semantics.cc   |  5 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C  |  3 ++
 gcc/testsuite/g++.dg/ext/remove_pointer.C | 51 +++
 6 files changed, 78 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/remove_pointer.C

diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index fa79bc0c68c..2add97ae749 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -97,6 +97,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_POINTER, "__remove_pointer", 1)
 DEFTRAIT_TYPE (REMOVE_REFERENCE, "__remove_reference", 1)
 DEFTRAIT_TYPE (TYPE_PACK_ELEMENT, "__type_pack_element", -1)
 DEFTRAIT_TYPE (UNDERLYING_TYPE, "__underlying_type", 1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 771242a7f45..8fbd67788d5 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -77,6 +77,7 @@ struct cp_trait {
 "__reference_converts_from_temporary", CPTK_REF_CONVERTS_FROM_TEMPORARY, 2, 
false
 "__remove_cv", CPTK_REMOVE_CV, 1, true
 "__remove_cvref", CPTK_REMOVE_CVREF, 1, true
+"__remove_pointer", CPTK_REMOVE_POINTER, 1, true
 "__remove_reference", CPTK_REMOVE_REFERENCE, 1, true
 "__type_pack_element", CPTK_TYPE_PACK_ELEMENT, -1, true
 "__underlying_type", CPTK_UNDERLYING_TYPE, 1, true
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index b6db58e93c9..ad2c2a2d250 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -116,7 +116,7 @@ cp_trait_lookup::find (const char *str, size_t len)
 {
   enum
 {
-  TOTAL_KEYWORDS = 56,
+  TOTAL_KEYWORDS = 57,
   MIN_WORD_LENGTH = 7,
   MAX_WORD_LENGTH = 37,
   MIN_HASH_VALUE = 7,
@@ -125,7 +125,7 @@ cp_trait_lookup::find (const char *str, size_t len)
 
   static const struct cp_trait wordlist[] =
 {
-#line 84 "../../gcc/cp/cp-trait.gperf"
+#line 85 "../../gcc/cp/cp-trait.gperf"
   {"__bases", CPTK_BASES, 1, true},
 #line 51 "../../gcc/cp/cp-trait.gperf"
   {"__is_enum", CPTK_IS_ENUM, 1, false},
@@ -137,17 +137,19 @@ cp_trait_lookup::find (const char *str, size_t len)
   {"__remove_cvref", CPTK_REMOVE_CVREF, 1, true},
 #line 50 "../../gcc/cp/cp-trait.gperf"
   {"__is_empty", CPTK_IS_EMPTY, 1, false},
+#line 80 "../../gcc/cp/cp-trait.gperf"
+  {"__remove_pointer", CPTK_REMOVE_POINTER, 1, true},
 #line 69 "../../gcc/cp/cp-trait.gperf"
   {"__is_trivial", CPTK_IS_TRIVIAL, 1, false},
-#line 80 "../../gcc/cp/cp-trait.gperf"
+#line 81 "../../gcc/cp/cp-trait.gperf"
   {"__remove_reference", CPTK_REMOVE_REFERENCE, 1, true},
-#line 85 "../../gcc/cp/cp-trait.gperf"
+#line 86 "../../gcc/cp/cp-trait.gperf"
   {"__direct_bases", CPTK_DIRECT_BASES, 1, true},
-#line 82 "../../gcc/cp/cp-trait.gperf"
+#line 83 "../../gcc/cp/cp-trait.gperf"
   {"__underlying_type", CPTK_UNDERLYING_TYPE, 1, true},
 #line 45 "../../gcc/cp/cp-trait.gperf"
   {"__is_bounded_array", CPTK_IS_BOUNDED_ARRAY, 1, false},
-#line 81 "../../gcc/cp/cp-trait.gperf"
+#line 82 "../../gcc/cp/cp-trait.gperf"
   {"__type_pack_element", CPTK_TYPE_PACK_ELEMENT, -1, true},
 #line 73 "../../gcc/cp/cp-trait.gperf"
   {"__is_unbounded_array", CPTK_IS_UNBOUNDED_ARRAY, 1, false},
@@ -235,21 +237,21 @@ cp_trait_lookup::find (const char *str, size_t len)
   {"__is_final", CPTK_IS_FINAL, 1, false},
 #line 53 "../../gcc/cp/cp-trait.gperf"
   {"__is_function", CPTK_IS_FUNCTION, 1, false},
-#line 83 "../../gcc/cp/cp-trait.gperf"
+#line 84 "../../gcc/cp/cp-trait.gperf"
   {"__is_deducible ", CPTK_IS_DEDUCIBLE, 2, false}
 };
 
   static const signed char lookup[] =
 {
   -1, -1, -1, -1, -1, -1, -1,  0, -1,  1,  2,  3, -1, -1,
-   4,  5, -1,  6,  7,  8, -1, -1,  9, 10, 11, 12, 13, 14,
-  15, -1, 16, 17, 18, 19, -1, 20, -1, 21, 22, -1, 23, -1,
-  24, 25, 26, 27, -1, 28, 29, 30, 31, -1, 32, -1, 33, 34,
-  -1, -1, 35, 36, 37, 38, -1, 39, 40, -1, -1, -1, 41, 42,
-  43, -1, -1, -1, -1, 44, 45, -1, 46, 47, 48, -1, -1, -1,
-  -1, 49, 50, -1, 51, -1, 52, -1, -1, -1, -1, 53, -1, -1,
-  54, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, 55
+   4,  5,  6,  

[PATCH v16 20/39] libstdc++: Optimize is_member_object_pointer trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_member_object_pointer trait
by dispatching to the new __is_member_object_pointer built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_member_object_pointer): Use
__is_member_object_pointer built-in trait.
(is_member_object_pointer_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index e1b10240dc2..792213ebfe8 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -574,6 +574,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_rvalue_reference<_Tp&&>
 : public true_type { };
 
+  /// is_member_object_pointer
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer)
+  template
+struct is_member_object_pointer
+: public __bool_constant<__is_member_object_pointer(_Tp)>
+{ };
+#else
   template
 struct __is_member_object_pointer_helper
 : public false_type { };
@@ -582,11 +589,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct __is_member_object_pointer_helper<_Tp _Cp::*>
 : public __not_>::type { };
 
-  /// is_member_object_pointer
+
   template
 struct is_member_object_pointer
 : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type
 { };
+#endif
 
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer)
   /// is_member_function_pointer
@@ -3227,9 +3235,16 @@ template 
   inline constexpr bool is_rvalue_reference_v = false;
 template 
   inline constexpr bool is_rvalue_reference_v<_Tp&&> = true;
+
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer)
+template 
+  inline constexpr bool is_member_object_pointer_v =
+__is_member_object_pointer(_Tp);
+#else
 template 
   inline constexpr bool is_member_object_pointer_v =
 is_member_object_pointer<_Tp>::value;
+#endif
 
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer)
 template 
-- 
2.42.0



[PATCH v16 23/39] c++: Implement __is_function built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_function.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_function.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_FUNCTION.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc |   3 +
 gcc/cp/cp-trait.def  |   1 +
 gcc/cp/cp-trait.gperf|   1 +
 gcc/cp/cp-trait.h| 143 ---
 gcc/cp/semantics.cc  |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
 gcc/testsuite/g++.dg/ext/is_function.C   |  58 +
 7 files changed, 143 insertions(+), 70 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_function.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 5cdb59d174e..99a7e7247ce 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3750,6 +3750,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_FINAL:
   inform (loc, "  %qT is not a final class", t1);
   break;
+case CPTK_IS_FUNCTION:
+  inform (loc, "  %qT is not a function", t1);
+  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 e867d9c4c47..fa79bc0c68c 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -70,6 +70,7 @@ DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 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_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-trait.gperf b/gcc/cp/cp-trait.gperf
index 5989b84727f..771242a7f45 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -50,6 +50,7 @@ struct cp_trait {
 "__is_empty", CPTK_IS_EMPTY, 1, false
 "__is_enum", CPTK_IS_ENUM, 1, false
 "__is_final", CPTK_IS_FINAL, 1, false
+"__is_function", CPTK_IS_FUNCTION, 1, false
 "__is_layout_compatible", CPTK_IS_LAYOUT_COMPATIBLE, 2, false
 "__is_literal_type", CPTK_IS_LITERAL_TYPE, 1, false
 "__is_member_function_pointer", CPTK_IS_MEMBER_FUNCTION_POINTER, 1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index f0b4f96d4a9..b6db58e93c9 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 94, duplicates = 0 */
+/* maximum key range = 109, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101,  20, 101,  40,   5,  40,
-   40,   0,  60,  10, 101,   0, 101, 101,   5,  25,
-   30,   0,   5, 101,  10,  15,   5,   0,  25, 101,
-  101,  20, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
-  101, 101, 101, 101, 101, 101
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 

[PATCH v16 24/39] libstdc++: Optimize is_function trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_function trait by dispatching
to the new __is_function built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_function): Use __is_function built-in
trait.
(is_function_v): Likewise. Optimize its implementation.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 36ad9814047..bd57488824b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -637,6 +637,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_function
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function)
+  template
+struct is_function
+: public __bool_constant<__is_function(_Tp)>
+{ };
+#else
   template
 struct is_function
 : public __bool_constant::value> { };
@@ -648,6 +654,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_function<_Tp&&>
 : public false_type { };
+#endif
 
 #ifdef __cpp_lib_is_null_pointer // C++ >= 11
   /// is_null_pointer (LWG 2247).
@@ -3269,8 +3276,18 @@ template 
   inline constexpr bool is_union_v = __is_union(_Tp);
 template 
   inline constexpr bool is_class_v = __is_class(_Tp);
+
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function)
 template 
-  inline constexpr bool is_function_v = is_function<_Tp>::value;
+  inline constexpr bool is_function_v = __is_function(_Tp);
+#else
+template 
+  inline constexpr bool is_function_v = !is_const_v;
+template 
+  inline constexpr bool is_function_v<_Tp&> = false;
+template 
+  inline constexpr bool is_function_v<_Tp&&> = false;
+#endif
 
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
 template 
-- 
2.42.0



[PATCH v16 18/39] libstdc++: Optimize is_member_function_pointer trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_member_function_pointer trait
by dispatching to the new __is_member_function_pointer built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_member_function_pointer): Use
__is_member_function_pointer built-in trait.
(is_member_function_pointer_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index d7f89cf7c06..e1b10240dc2 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -588,6 +588,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type
 { };
 
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer)
+  /// is_member_function_pointer
+  template
+struct is_member_function_pointer
+: public __bool_constant<__is_member_function_pointer(_Tp)>
+{ };
+#else
   template
 struct __is_member_function_pointer_helper
 : public false_type { };
@@ -601,6 +608,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_member_function_pointer
 : public __is_member_function_pointer_helper<__remove_cv_t<_Tp>>::type
 { };
+#endif
 
   /// is_enum
   template
@@ -3222,9 +3230,17 @@ template 
 template 
   inline constexpr bool is_member_object_pointer_v =
 is_member_object_pointer<_Tp>::value;
+
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer)
+template 
+  inline constexpr bool is_member_function_pointer_v =
+__is_member_function_pointer(_Tp);
+#else
 template 
   inline constexpr bool is_member_function_pointer_v =
 is_member_function_pointer<_Tp>::value;
+#endif
+
 template 
   inline constexpr bool is_enum_v = __is_enum(_Tp);
 template 
-- 
2.42.0



[PATCH v16 19/39] c++: Implement __is_member_object_pointer built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_member_object_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_member_object_pointer.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle
CPTK_IS_MEMBER_OBJECT_POINTER.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc  |  3 +
 gcc/cp/cp-trait.def   |  1 +
 gcc/cp/cp-trait.gperf |  1 +
 gcc/cp/cp-trait.h | 62 ++-
 gcc/cp/semantics.cc   |  4 ++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C  |  3 +
 .../g++.dg/ext/is_member_object_pointer.C | 30 +
 7 files changed, 74 insertions(+), 30 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_member_object_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index d0464dd4f6a..98b1f004a68 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3759,6 +3759,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_MEMBER_FUNCTION_POINTER:
   inform (loc, "  %qT is not a member function pointer", t1);
   break;
+case CPTK_IS_MEMBER_OBJECT_POINTER:
+  inform (loc, "  %qT is not a member object pointer", t1);
+  break;
 case CPTK_IS_MEMBER_POINTER:
   inform (loc, "  %qT is not a member pointer", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 897b96630f2..11fd70b3964 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -73,6 +73,7 @@ DEFTRAIT_EXPR (IS_FINAL, "__is_final", 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)
+DEFTRAIT_EXPR (IS_MEMBER_OBJECT_POINTER, "__is_member_object_pointer", 1)
 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)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index b28efbab322..32199a1fe9a 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -53,6 +53,7 @@ struct cp_trait {
 "__is_layout_compatible", CPTK_IS_LAYOUT_COMPATIBLE, 2, false
 "__is_literal_type", CPTK_IS_LITERAL_TYPE, 1, false
 "__is_member_function_pointer", CPTK_IS_MEMBER_FUNCTION_POINTER, 1, false
+"__is_member_object_pointer", CPTK_IS_MEMBER_OBJECT_POINTER, 1, false
 "__is_member_pointer", CPTK_IS_MEMBER_POINTER, 1, false
 "__is_nothrow_assignable", CPTK_IS_NOTHROW_ASSIGNABLE, 2, false
 "__is_nothrow_constructible", CPTK_IS_NOTHROW_CONSTRUCTIBLE, -1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index d3d4bdf9799..799fe2b792f 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -116,7 +116,7 @@ cp_trait_lookup::find (const char *str, size_t len)
 {
   enum
 {
-  TOTAL_KEYWORDS = 53,
+  TOTAL_KEYWORDS = 54,
   MIN_WORD_LENGTH = 7,
   MAX_WORD_LENGTH = 37,
   MIN_HASH_VALUE = 7,
@@ -125,57 +125,57 @@ cp_trait_lookup::find (const char *str, size_t len)
 
   static const struct cp_trait wordlist[] =
 {
-#line 81 "../../gcc/cp/cp-trait.gperf"
+#line 82 "../../gcc/cp/cp-trait.gperf"
   {"__bases", CPTK_BASES, 1, true},
 #line 51 "../../gcc/cp/cp-trait.gperf"
   {"__is_enum", CPTK_IS_ENUM, 1, false},
-#line 71 "../../gcc/cp/cp-trait.gperf"
+#line 72 "../../gcc/cp/cp-trait.gperf"
   {"__is_union", CPTK_IS_UNION, 1, false},
-#line 75 "../../gcc/cp/cp-trait.gperf"
-  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
 #line 76 "../../gcc/cp/cp-trait.gperf"
+  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
+#line 77 "../../gcc/cp/cp-trait.gperf"
   {"__remove_cvref", CPTK_REMOVE_CVREF, 1, true},
 #line 50 "../../gcc/cp/cp-trait.gperf"
   {"__is_empty", CPTK_IS_EMPTY, 1, false},
-#line 66 "../../gcc/cp/cp-trait.gperf"
+#line 67 "../../gcc/cp/cp-trait.gperf"
   {"__is_trivial", CPTK_IS_TRIVIAL, 1, false},
-#line 77 "../../gcc/cp/cp-trait.gperf"
+#line 78 "../../gcc/cp/cp-trait.gperf"
   {"__remove_reference", CPTK_REMOVE_REFERENCE, 1, true},
-#line 82 "../../gcc/cp/cp-trait.gperf"
+#line 83 "../../gcc/cp/cp-trait.gperf"
   {"__direct_bases", CPTK_DIRECT_BASES, 1, true},
-#line 79 "../../gcc/cp/cp-trait.gperf"
+#line 80 "../../gcc/cp/cp-trait.gperf"
   {"__underlying_type", CPTK_UNDERLYING_TYPE, 1, true},
 #line 45 "../../gcc/cp/cp-trait.gperf"
   {"__is_bounded_array", CPTK_IS_BOUNDED_ARRAY, 1, false},
-#line 78 "../../gcc/cp/cp-trait.gperf"
+#line 79 "../../gcc/cp/cp-trait.gperf"
   

[PATCH v16 16/39] libstdc++: Optimize is_member_pointer trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_member_pointer trait
by dispatching to the new __is_member_pointer built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_member_pointer): Use __is_member_pointer
built-in trait.
(is_member_pointer_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 7fd29d8d9f2..d7f89cf7c06 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -716,6 +716,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 struct is_compound
 : public __not_>::type { };
 
+  /// is_member_pointer
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer)
+  template
+struct is_member_pointer
+: public __bool_constant<__is_member_pointer(_Tp)>
+{ };
+#else
   /// @cond undocumented
   template
 struct __is_member_pointer_helper
@@ -726,11 +733,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : public true_type { };
   /// @endcond
 
-  /// is_member_pointer
   template
 struct is_member_pointer
 : public __is_member_pointer_helper<__remove_cv_t<_Tp>>::type
 { };
+#endif
 
   template
 struct is_same;
@@ -3242,8 +3249,14 @@ template 
   inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 template 
   inline constexpr bool is_compound_v = is_compound<_Tp>::value;
+
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer)
+template 
+  inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp);
+#else
 template 
   inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value;
+#endif
 
 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_const)
 template 
-- 
2.42.0



[PATCH v16 17/39] c++: Implement __is_member_function_pointer built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_member_function_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_member_function_pointer.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle
CPTK_IS_MEMBER_FUNCTION_POINTER.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc  |   3 +
 gcc/cp/cp-trait.def   |   1 +
 gcc/cp/cp-trait.gperf |   1 +
 gcc/cp/cp-trait.h | 176 +-
 gcc/cp/semantics.cc   |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C  |   3 +
 .../g++.dg/ext/is_member_function_pointer.C   |  31 +++
 7 files changed, 131 insertions(+), 88 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_member_function_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f0d3f89464c..d0464dd4f6a 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3756,6 +3756,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_LITERAL_TYPE:
   inform (loc, "  %qT is not a literal type", t1);
   break;
+case CPTK_IS_MEMBER_FUNCTION_POINTER:
+  inform (loc, "  %qT is not a member function pointer", t1);
+  break;
 case CPTK_IS_MEMBER_POINTER:
   inform (loc, "  %qT is not a member pointer", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 26087da3bdf..897b96630f2 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -72,6 +72,7 @@ DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 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)
 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)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 3775b11283d..b28efbab322 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -52,6 +52,7 @@ struct cp_trait {
 "__is_final", CPTK_IS_FINAL, 1, false
 "__is_layout_compatible", CPTK_IS_LAYOUT_COMPATIBLE, 2, false
 "__is_literal_type", CPTK_IS_LITERAL_TYPE, 1, false
+"__is_member_function_pointer", CPTK_IS_MEMBER_FUNCTION_POINTER, 1, false
 "__is_member_pointer", CPTK_IS_MEMBER_POINTER, 1, false
 "__is_nothrow_assignable", CPTK_IS_NOTHROW_ASSIGNABLE, 2, false
 "__is_nothrow_constructible", CPTK_IS_NOTHROW_CONSTRUCTIBLE, -1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index dfd60cec6e6..d3d4bdf9799 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 111, duplicates = 0 */
+/* maximum key range = 89, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118,  20, 118,   0,  55,  50,
-   40,   0,  40,  20, 118,   0, 118, 118,   5,   5,
-   30,   0,   5, 118,  10,  50,   5,   0,   5, 118,
-  118,   5, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
-  118, 118, 118, 118, 118, 118
+  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+  96, 96, 96, 96, 96, 96, 96, 96, 96, 

[PATCH v16 15/39] c++: Implement __is_member_pointer built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_member_pointer.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_member_pointer.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_MEMBER_POINTER.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc |   3 +
 gcc/cp/cp-trait.def  |   1 +
 gcc/cp/cp-trait.gperf|   1 +
 gcc/cp/cp-trait.h| 153 ++-
 gcc/cp/semantics.cc  |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
 gcc/testsuite/g++.dg/ext/is_member_pointer.C |  30 
 7 files changed, 120 insertions(+), 75 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_member_pointer.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 1c0b2e0f178..f0d3f89464c 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3756,6 +3756,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_LITERAL_TYPE:
   inform (loc, "  %qT is not a literal type", t1);
   break;
+case CPTK_IS_MEMBER_POINTER:
+  inform (loc, "  %qT is not a member pointer", t1);
+  break;
 case CPTK_IS_NOTHROW_ASSIGNABLE:
   inform (loc, "  %qT is not nothrow assignable from %qT", t1, t2);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index e0e3fe1d23f..26087da3bdf 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -72,6 +72,7 @@ DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
 DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
 DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
 DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
+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)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index f3fd82ba549..3775b11283d 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -52,6 +52,7 @@ struct cp_trait {
 "__is_final", CPTK_IS_FINAL, 1, false
 "__is_layout_compatible", CPTK_IS_LAYOUT_COMPATIBLE, 2, false
 "__is_literal_type", CPTK_IS_LITERAL_TYPE, 1, false
+"__is_member_pointer", CPTK_IS_MEMBER_POINTER, 1, false
 "__is_nothrow_assignable", CPTK_IS_NOTHROW_ASSIGNABLE, 2, false
 "__is_nothrow_constructible", CPTK_IS_NOTHROW_CONSTRUCTIBLE, -1, false
 "__is_nothrow_convertible", CPTK_IS_NOTHROW_CONVERTIBLE, 2, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index 9c18165eb68..dfd60cec6e6 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 92, duplicates = 0 */
+/* maximum key range = 111, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 20, 99,  0,  5, 50,
-  30,  0, 40, 15, 99,  0, 99, 99,  5, 10,
-  30,  0,  5, 99, 10, 50,  5,  0, 35, 99,
-  99,  5, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-  99, 99, 99, 99, 99, 99
+  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+  118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+  118, 118, 118, 118, 118, 118, 

[PATCH v16 14/39] libstdc++: Optimize is_scoped_enum trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_scoped_enum trait
by dispatching to the new __is_scoped_enum built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_scoped_enum): Use
__is_scoped_enum built-in trait.
(is_scoped_enum_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index d306073a797..7fd29d8d9f2 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3633,6 +3633,12 @@ template
   /// True if the type is a scoped enumeration type.
   /// @since C++23
 
+# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum)
+  template
+struct is_scoped_enum
+: bool_constant<__is_scoped_enum(_Tp)>
+{ };
+# else
   template
 struct is_scoped_enum
 : false_type
@@ -3644,11 +3650,17 @@ template
 struct is_scoped_enum<_Tp>
 : bool_constant
 { };
+# endif
 
   /// @ingroup variable_templates
   /// @since C++23
+# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum)
+  template
+inline constexpr bool is_scoped_enum_v = __is_scoped_enum(_Tp);
+# else
   template
 inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value;
+# endif
 #endif
 
 #ifdef __cpp_lib_reference_from_temporary // C++ >= 23 && 
ref_{converts,constructs}_from_temp
-- 
2.42.0



[PATCH v16 12/39] libstdc++: Optimize is_bounded_array trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_bounded_array trait by
dispatching to the new __is_bounded_array built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_bounded_array_v): Use __is_bounded_array
built-in trait.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index cb3d9e238fa..d306073a797 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3532,11 +3532,16 @@ template
   /// True for a type that is an array of known bound.
   /// @ingroup variable_templates
   /// @since C++20
+# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_bounded_array)
+  template
+inline constexpr bool is_bounded_array_v = __is_bounded_array(_Tp);
+# else
   template
 inline constexpr bool is_bounded_array_v = false;
 
   template
 inline constexpr bool is_bounded_array_v<_Tp[_Size]> = true;
+# endif
 
   /// True for a type that is an array of unknown bound.
   /// @ingroup variable_templates
-- 
2.42.0



[PATCH v16 13/39] c++: Implement __is_scoped_enum built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_scoped_enum.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_scoped_enum.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_SCOPED_ENUM.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc  |   3 +
 gcc/cp/cp-trait.def   |   1 +
 gcc/cp/cp-trait.gperf |   1 +
 gcc/cp/cp-trait.h | 161 +++---
 gcc/cp/semantics.cc   |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C  |   3 +
 gcc/testsuite/g++.dg/ext/is_scoped_enum.C |  67 +
 7 files changed, 160 insertions(+), 80 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_scoped_enum.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index d09252a56b6..1c0b2e0f178 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3781,6 +3781,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_SAME:
   inform (loc, "  %qT is not the same as %qT", t1, t2);
   break;
+case CPTK_IS_SCOPED_ENUM:
+  inform (loc, "  %qT is not a scoped enum", t1);
+  break;
 case CPTK_IS_STD_LAYOUT:
   inform (loc, "  %qT is not an standard layout type", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 6d6dff7a4c3..e0e3fe1d23f 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -79,6 +79,7 @@ DEFTRAIT_EXPR (IS_POINTER_INTERCONVERTIBLE_BASE_OF, 
"__is_pointer_interconvertib
 DEFTRAIT_EXPR (IS_POD, "__is_pod", 1)
 DEFTRAIT_EXPR (IS_POLYMORPHIC, "__is_polymorphic", 1)
 DEFTRAIT_EXPR (IS_SAME, "__is_same", 2)
+DEFTRAIT_EXPR (IS_SCOPED_ENUM, "__is_scoped_enum", 1)
 DEFTRAIT_EXPR (IS_STD_LAYOUT, "__is_standard_layout", 1)
 DEFTRAIT_EXPR (IS_TRIVIAL, "__is_trivial", 1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 90fcdc01de6..f3fd82ba549 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -59,6 +59,7 @@ struct cp_trait {
 "__is_pod", CPTK_IS_POD, 1, false
 "__is_polymorphic", CPTK_IS_POLYMORPHIC, 1, false
 "__is_same", CPTK_IS_SAME, 2, false
+"__is_scoped_enum", CPTK_IS_SCOPED_ENUM, 1, false
 "__is_standard_layout", CPTK_IS_STD_LAYOUT, 1, false
 "__is_trivial", CPTK_IS_TRIVIAL, 1, false
 "__is_trivially_assignable", CPTK_IS_TRIVIALLY_ASSIGNABLE, 2, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index f22a6e93618..9c18165eb68 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 109, duplicates = 0 */
+/* maximum key range = 92, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116,  20, 116,  45,   5,  20,
-   50,   0,  30,   5, 116,   0, 116, 116,   5,  10,
-   30,   0,   5, 116,  10,  30,   5,   0,  25, 116,
-  116,   5, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
-  116, 116, 116, 116, 116, 116
+  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+  99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+  99, 99, 99, 

[PATCH v16 11/39] c++: Implement __is_bounded_array built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_bounded_array.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_bounded_array.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_BOUNDED_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_bounded_array.
* g++.dg/ext/is_bounded_array.C: New test.

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc|  3 +
 gcc/cp/cp-trait.def |  1 +
 gcc/cp/cp-trait.gperf   |  1 +
 gcc/cp/cp-trait.h   | 86 +++--
 gcc/cp/semantics.cc |  4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 +
 gcc/testsuite/g++.dg/ext/is_bounded_array.C | 38 +
 7 files changed, 94 insertions(+), 42 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_bounded_array.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 751ac61b25a..d09252a56b6 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3723,6 +3723,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_BASE_OF:
   inform (loc, "  %qT is not a base of %qT", t1, t2);
   break;
+case CPTK_IS_BOUNDED_ARRAY:
+  inform (loc, "  %qT is not a bounded array", t1);
+  break;
 case CPTK_IS_CLASS:
   inform (loc, "  %qT is not a class", t1);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 4e02f68e4a9..6d6dff7a4c3 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -62,6 +62,7 @@ DEFTRAIT_EXPR (IS_AGGREGATE, "__is_aggregate", 1)
 DEFTRAIT_EXPR (IS_ARRAY, "__is_array", 1)
 DEFTRAIT_EXPR (IS_ASSIGNABLE, "__is_assignable", 2)
 DEFTRAIT_EXPR (IS_BASE_OF, "__is_base_of", 2)
+DEFTRAIT_EXPR (IS_BOUNDED_ARRAY, "__is_bounded_array", 1)
 DEFTRAIT_EXPR (IS_CLASS, "__is_class", 1)
 DEFTRAIT_EXPR (IS_CONST, "__is_const", 1)
 DEFTRAIT_EXPR (IS_CONSTRUCTIBLE, "__is_constructible", -1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index a894fc8c74c..90fcdc01de6 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -42,6 +42,7 @@ struct cp_trait {
 "__is_array", CPTK_IS_ARRAY, 1, false
 "__is_assignable", CPTK_IS_ASSIGNABLE, 2, false
 "__is_base_of", CPTK_IS_BASE_OF, 2, false
+"__is_bounded_array", CPTK_IS_BOUNDED_ARRAY, 1, false
 "__is_class", CPTK_IS_CLASS, 1, false
 "__is_const", CPTK_IS_CONST, 1, false
 "__is_constructible", CPTK_IS_CONSTRUCTIBLE, -1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index 47060ffbbef..f22a6e93618 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -80,7 +80,7 @@ cp_trait_lookup::hash (const char *str, size_t len)
   116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
   116, 116, 116, 116, 116,  20, 116,  45,   5,  20,
50,   0,  30,   5, 116,   0, 116, 116,   5,  10,
-   30,   0,   5, 116,  10,  30,   5,   0,   5, 116,
+   30,   0,   5, 116,  10,  30,   5,   0,  25, 116,
   116,   5, 116, 116, 116, 116, 116, 116, 116, 116,
   116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
   116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
@@ -116,7 +116,7 @@ cp_trait_lookup::find (const char *str, size_t len)
 {
   enum
 {
-  TOTAL_KEYWORDS = 49,
+  TOTAL_KEYWORDS = 50,
   MIN_WORD_LENGTH = 7,
   MAX_WORD_LENGTH = 37,
   MIN_HASH_VALUE = 7,
@@ -125,54 +125,56 @@ cp_trait_lookup::find (const char *str, size_t len)
 
   static const struct cp_trait wordlist[] =
 {
-#line 77 "../../gcc/cp/cp-trait.gperf"
+#line 78 "../../gcc/cp/cp-trait.gperf"
   {"__bases", CPTK_BASES, 1, true},
-#line 50 "../../gcc/cp/cp-trait.gperf"
+#line 51 "../../gcc/cp/cp-trait.gperf"
   {"__is_enum", CPTK_IS_ENUM, 1, false},
-#line 67 "../../gcc/cp/cp-trait.gperf"
+#line 68 "../../gcc/cp/cp-trait.gperf"
   {"__is_union", CPTK_IS_UNION, 1, false},
-#line 71 "../../gcc/cp/cp-trait.gperf"
-  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
 #line 72 "../../gcc/cp/cp-trait.gperf"
+  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
+#line 73 "../../gcc/cp/cp-trait.gperf"
   {"__remove_cvref", CPTK_REMOVE_CVREF, 1, true},
-#line 49 "../../gcc/cp/cp-trait.gperf"
+#line 50 "../../gcc/cp/cp-trait.gperf"
   {"__is_empty", CPTK_IS_EMPTY, 1, false},
-#line 62 "../../gcc/cp/cp-trait.gperf"
+#line 63 "../../gcc/cp/cp-trait.gperf"
   {"__is_trivial", CPTK_IS_TRIVIAL, 1, false},
-#line 73 "../../gcc/cp/cp-trait.gperf"
+#line 74 "../../gcc/cp/cp-trait.gperf"
   {"__remove_reference", CPTK_REMOVE_REFERENCE, 1, true},
-#line 78 "../../gcc/cp/cp-trait.gperf"
+#line 79 "../../gcc/cp/cp-trait.gperf"
   {"__direct_bases", CPTK_DIRECT_BASES, 1, true},
-#line 75 "../../gcc/cp/cp-trait.gperf"
+#line 76 "../../gcc/cp/cp-trait.gperf"
   {"__underlying_type", 

[PATCH v16 10/39] libstdc++: Optimize is_unbounded_array trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_unbounded_array trait by
dispatching to the new __is_unbounded_array built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_unbounded_array_v): Use
__is_unbounded_array built-in trait.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 4e8165e5af5..cb3d9e238fa 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3541,11 +3541,16 @@ template
   /// True for a type that is an array of unknown bound.
   /// @ingroup variable_templates
   /// @since C++20
+# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_unbounded_array)
+  template
+inline constexpr bool is_unbounded_array_v = __is_unbounded_array(_Tp);
+# else
   template
 inline constexpr bool is_unbounded_array_v = false;
 
   template
 inline constexpr bool is_unbounded_array_v<_Tp[]> = true;
+# endif
 
   /// True for a type that is an array of known bound.
   /// @since C++20
-- 
2.42.0



[PATCH v16 09/39] c++: Implement __is_unbounded_array built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_unbounded_array.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_unbounded_array.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* 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 
---
 gcc/cp/constraint.cc  |  3 ++
 gcc/cp/cp-trait.def   |  1 +
 gcc/cp/cp-trait.gperf |  1 +
 gcc/cp/cp-trait.h | 42 ++-
 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 
 7 files changed, 71 insertions(+), 20 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_unbounded_array.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 5e30a4a907a..751ac61b25a 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3796,6 +3796,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 99bc05360b9..4e02f68e4a9 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,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/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index fb162cac164..a894fc8c74c 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -63,6 +63,7 @@ struct cp_trait {
 "__is_trivially_assignable", CPTK_IS_TRIVIALLY_ASSIGNABLE, 2, false
 "__is_trivially_constructible", CPTK_IS_TRIVIALLY_CONSTRUCTIBLE, -1, false
 "__is_trivially_copyable", CPTK_IS_TRIVIALLY_COPYABLE, 1, false
+"__is_unbounded_array", CPTK_IS_UNBOUNDED_ARRAY, 1, false
 "__is_union", CPTK_IS_UNION, 1, false
 "__is_volatile", CPTK_IS_VOLATILE, 1, false
 "__reference_constructs_from_temporary", CPTK_REF_CONSTRUCTS_FROM_TEMPORARY, 
2, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index 526e63dec42..47060ffbbef 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -116,7 +116,7 @@ cp_trait_lookup::find (const char *str, size_t len)
 {
   enum
 {
-  TOTAL_KEYWORDS = 48,
+  TOTAL_KEYWORDS = 49,
   MIN_WORD_LENGTH = 7,
   MAX_WORD_LENGTH = 37,
   MIN_HASH_VALUE = 7,
@@ -125,30 +125,32 @@ cp_trait_lookup::find (const char *str, size_t len)
 
   static const struct cp_trait wordlist[] =
 {
-#line 76 "../../gcc/cp/cp-trait.gperf"
+#line 77 "../../gcc/cp/cp-trait.gperf"
   {"__bases", CPTK_BASES, 1, true},
 #line 50 "../../gcc/cp/cp-trait.gperf"
   {"__is_enum", CPTK_IS_ENUM, 1, false},
-#line 66 "../../gcc/cp/cp-trait.gperf"
+#line 67 "../../gcc/cp/cp-trait.gperf"
   {"__is_union", CPTK_IS_UNION, 1, false},
-#line 70 "../../gcc/cp/cp-trait.gperf"
-  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
 #line 71 "../../gcc/cp/cp-trait.gperf"
+  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
+#line 72 "../../gcc/cp/cp-trait.gperf"
   {"__remove_cvref", CPTK_REMOVE_CVREF, 1, true},
 #line 49 "../../gcc/cp/cp-trait.gperf"
   {"__is_empty", CPTK_IS_EMPTY, 1, false},
 #line 62 "../../gcc/cp/cp-trait.gperf"
   {"__is_trivial", CPTK_IS_TRIVIAL, 1, false},
-#line 72 "../../gcc/cp/cp-trait.gperf"
+#line 73 "../../gcc/cp/cp-trait.gperf"
   {"__remove_reference", CPTK_REMOVE_REFERENCE, 1, true},
-#line 77 "../../gcc/cp/cp-trait.gperf"
+#line 78 "../../gcc/cp/cp-trait.gperf"
   {"__direct_bases", CPTK_DIRECT_BASES, 1, true},
-#line 74 "../../gcc/cp/cp-trait.gperf"
+#line 75 "../../gcc/cp/cp-trait.gperf"
   {"__underlying_type", CPTK_UNDERLYING_TYPE, 1, true},
-#line 67 "../../gcc/cp/cp-trait.gperf"
+#line 68 "../../gcc/cp/cp-trait.gperf"
   {"__is_volatile", CPTK_IS_VOLATILE, 1, false},
-#line 73 "../../gcc/cp/cp-trait.gperf"
+#line 74 "../../gcc/cp/cp-trait.gperf"
   {"__type_pack_element", CPTK_TYPE_PACK_ELEMENT, -1, true},
+#line 66 "../../gcc/cp/cp-trait.gperf"
+  

[PATCH v16 08/39] libstdc++: Optimize is_array trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_array trait by dispatching to
the new __is_array built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_array): Use __is_array built-in trait.
(is_array_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index c01f65df22b..4e8165e5af5 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -523,6 +523,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
   /// is_array
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array)
+  template
+struct is_array
+: public __bool_constant<__is_array(_Tp)>
+{ };
+#else
   template
 struct is_array
 : public false_type { };
@@ -534,6 +540,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_array<_Tp[]>
 : public true_type { };
+#endif
 
   template
 struct __is_pointer_helper
@@ -3183,12 +3190,17 @@ template 
 template 
   inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value;
 
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array)
+template 
+  inline constexpr bool is_array_v = __is_array(_Tp);
+#else
 template 
   inline constexpr bool is_array_v = false;
 template 
   inline constexpr bool is_array_v<_Tp[]> = true;
 template 
   inline constexpr bool is_array_v<_Tp[_Num]> = true;
+#endif
 
 template 
   inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
-- 
2.42.0



[PATCH v16 07/39] c++: Implement __is_array built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_array.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_array.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_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_array.
* g++.dg/ext/is_array.C: New test.

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc |   3 +
 gcc/cp/cp-trait.def  |   1 +
 gcc/cp/cp-trait.gperf|   1 +
 gcc/cp/cp-trait.h| 148 ---
 gcc/cp/semantics.cc  |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
 gcc/testsuite/g++.dg/ext/is_array.C  |  28 +
 7 files changed, 116 insertions(+), 72 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_array.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index f031e022541..5e30a4a907a 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3714,6 +3714,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_AGGREGATE:
   inform (loc, "  %qT is not an aggregate", t1);
   break;
+case CPTK_IS_ARRAY:
+  inform (loc, "  %qT is not an array", t1);
+  break;
 case CPTK_IS_ASSIGNABLE:
   inform (loc, "  %qT is not assignable from %qT", t1, t2);
   break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index d786f47e60c..99bc05360b9 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -59,6 +59,7 @@ DEFTRAIT_EXPR (HAS_UNIQUE_OBJ_REPRESENTATIONS, 
"__has_unique_object_representati
 DEFTRAIT_EXPR (HAS_VIRTUAL_DESTRUCTOR, "__has_virtual_destructor", 1)
 DEFTRAIT_EXPR (IS_ABSTRACT, "__is_abstract", 1)
 DEFTRAIT_EXPR (IS_AGGREGATE, "__is_aggregate", 1)
+DEFTRAIT_EXPR (IS_ARRAY, "__is_array", 1)
 DEFTRAIT_EXPR (IS_ASSIGNABLE, "__is_assignable", 2)
 DEFTRAIT_EXPR (IS_BASE_OF, "__is_base_of", 2)
 DEFTRAIT_EXPR (IS_CLASS, "__is_class", 1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index ea7abda6c75..fb162cac164 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -39,6 +39,7 @@ struct cp_trait {
 "__has_virtual_destructor", CPTK_HAS_VIRTUAL_DESTRUCTOR, 1, false
 "__is_abstract", CPTK_IS_ABSTRACT, 1, false
 "__is_aggregate", CPTK_IS_AGGREGATE, 1, false
+"__is_array", CPTK_IS_ARRAY, 1, false
 "__is_assignable", CPTK_IS_ASSIGNABLE, 2, false
 "__is_base_of", CPTK_IS_BASE_OF, 2, false
 "__is_class", CPTK_IS_CLASS, 1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index f462794d5db..526e63dec42 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 89, duplicates = 0 */
+/* maximum key range = 109, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 20, 96, 35, 10, 20,
-  40,  0, 30, 15, 96,  0, 96, 96,  5, 15,
-  30,  0,  5, 96, 10, 25,  5,  0,  5, 96,
-  96,  5, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-  96, 96, 96, 96, 96, 96
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+  116, 116, 116, 116, 116,  20, 116,  45,   5,  20,
+   50,   0,  30,   5, 116,   0, 116, 116,   5,  10,
+   30,   0,   5, 116,  10,  30,   5,   0,   5, 116,
+ 

[PATCH v16 06/39] libstdc++: Optimize is_volatile trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_volatile trait by dispatching
to the new __is_volatile built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_volatile): Use __is_volatile built-in
trait.
(is_volatile_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 686e38e47c3..c01f65df22b 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -800,6 +800,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   /// is_volatile
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_volatile)
+  template
+struct is_volatile
+: public __bool_constant<__is_volatile(_Tp)>
+{ };
+#else
   template
 struct is_volatile
 : public false_type { };
@@ -807,6 +813,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_volatile<_Tp volatile>
 : public true_type { };
+#endif
 
   /// is_trivial
   template
@@ -3236,10 +3243,15 @@ template 
   inline constexpr bool is_const_v = true;
 #endif
 
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_volatile)
+template 
+  inline constexpr bool is_volatile_v = __is_volatile(_Tp);
+#else
 template 
   inline constexpr bool is_volatile_v = false;
 template 
   inline constexpr bool is_volatile_v = true;
+#endif
 
 template 
   inline constexpr bool is_trivial_v = __is_trivial(_Tp);
-- 
2.42.0



[PATCH v16 05/39] c++: Implement __is_volatile built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_volatile.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_volatile.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_VOLATILE.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc |  3 ++
 gcc/cp/cp-trait.def  |  1 +
 gcc/cp/cp-trait.gperf|  1 +
 gcc/cp/cp-trait.h| 38 +---
 gcc/cp/semantics.cc  |  4 +++
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |  3 ++
 gcc/testsuite/g++.dg/ext/is_volatile.C   | 19 
 7 files changed, 51 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_volatile.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 567dd35fe0a..f031e022541 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3796,6 +3796,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_UNION:
   inform (loc, "  %qT is not a union", t1);
   break;
+case CPTK_IS_VOLATILE:
+  inform (loc, "  %qT is not a volatile type", 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 9e4e6d798a0..d786f47e60c 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
"__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_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_CV, "__remove_cv", 1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 47a5ec9ee6f..ea7abda6c75 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -63,6 +63,7 @@ struct cp_trait {
 "__is_trivially_constructible", CPTK_IS_TRIVIALLY_CONSTRUCTIBLE, -1, false
 "__is_trivially_copyable", CPTK_IS_TRIVIALLY_COPYABLE, 1, false
 "__is_union", CPTK_IS_UNION, 1, false
+"__is_volatile", CPTK_IS_VOLATILE, 1, false
 "__reference_constructs_from_temporary", CPTK_REF_CONSTRUCTS_FROM_TEMPORARY, 
2, false
 "__reference_converts_from_temporary", CPTK_REF_CONVERTS_FROM_TEMPORARY, 2, 
false
 "__remove_cv", CPTK_REMOVE_CV, 1, true
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index c9005eee1ff..f462794d5db 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -80,7 +80,7 @@ cp_trait_lookup::hash (const char *str, size_t len)
   96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
   96, 96, 96, 96, 96, 20, 96, 35, 10, 20,
   40,  0, 30, 15, 96,  0, 96, 96,  5, 15,
-  30,  0,  5, 96, 10, 25,  5,  0, 96, 96,
+  30,  0,  5, 96, 10, 25,  5,  0,  5, 96,
   96,  5, 96, 96, 96, 96, 96, 96, 96, 96,
   96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
   96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
@@ -116,7 +116,7 @@ cp_trait_lookup::find (const char *str, size_t len)
 {
   enum
 {
-  TOTAL_KEYWORDS = 46,
+  TOTAL_KEYWORDS = 47,
   MIN_WORD_LENGTH = 7,
   MAX_WORD_LENGTH = 37,
   MIN_HASH_VALUE = 7,
@@ -125,27 +125,29 @@ cp_trait_lookup::find (const char *str, size_t len)
 
   static const struct cp_trait wordlist[] =
 {
-#line 74 "../../gcc/cp/cp-trait.gperf"
+#line 75 "../../gcc/cp/cp-trait.gperf"
   {"__bases", CPTK_BASES, 1, true},
 #line 49 "../../gcc/cp/cp-trait.gperf"
   {"__is_enum", CPTK_IS_ENUM, 1, false},
 #line 65 "../../gcc/cp/cp-trait.gperf"
   {"__is_union", CPTK_IS_UNION, 1, false},
-#line 68 "../../gcc/cp/cp-trait.gperf"
-  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
 #line 69 "../../gcc/cp/cp-trait.gperf"
+  {"__remove_cv", CPTK_REMOVE_CV, 1, true},
+#line 70 "../../gcc/cp/cp-trait.gperf"
   {"__remove_cvref", CPTK_REMOVE_CVREF, 1, true},
 #line 48 "../../gcc/cp/cp-trait.gperf"
   {"__is_empty", CPTK_IS_EMPTY, 1, false},
 #line 61 "../../gcc/cp/cp-trait.gperf"
   {"__is_trivial", CPTK_IS_TRIVIAL, 1, false},
-#line 70 "../../gcc/cp/cp-trait.gperf"
+#line 71 "../../gcc/cp/cp-trait.gperf"
   {"__remove_reference", CPTK_REMOVE_REFERENCE, 1, true},
-#line 75 "../../gcc/cp/cp-trait.gperf"
+#line 76 "../../gcc/cp/cp-trait.gperf"
   {"__direct_bases", CPTK_DIRECT_BASES, 1, true},
-#line 72 "../../gcc/cp/cp-trait.gperf"
+#line 73 

[PATCH v16 04/39] libstdc++: Optimize is_const trait performance

2023-10-10 Thread Ken Matsui
This patch optimizes the performance of the is_const trait by dispatching to
the new __is_const built-in trait.

libstdc++-v3/ChangeLog:

* include/std/type_traits (is_const): Use __is_const built-in trait.
(is_const_v): Likewise.

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

diff --git a/libstdc++-v3/include/std/type_traits 
b/libstdc++-v3/include/std/type_traits
index 677cd934b94..686e38e47c3 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -784,6 +784,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Type properties.
 
   /// is_const
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_const)
+  template
+struct is_const
+: public __bool_constant<__is_const(_Tp)>
+{ };
+#else
   template
 struct is_const
 : public false_type { };
@@ -791,6 +797,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 struct is_const<_Tp const>
 : public true_type { };
+#endif
 
   /// is_volatile
   template
@@ -3218,10 +3225,17 @@ template 
   inline constexpr bool is_compound_v = is_compound<_Tp>::value;
 template 
   inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value;
+
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_const)
+template 
+  inline constexpr bool is_const_v = __is_const(_Tp);
+#else
 template 
   inline constexpr bool is_const_v = false;
 template 
   inline constexpr bool is_const_v = true;
+#endif
+
 template 
   inline constexpr bool is_volatile_v = false;
 template 
-- 
2.42.0



[PATCH v16 03/39] c++: Implement __is_const built-in trait

2023-10-10 Thread Ken Matsui
This patch implements built-in trait for std::is_const.

gcc/cp/ChangeLog:

* Make-lang.in: Update key positions for gperf, based on
automatically computed values.
* cp-trait.def: Define __is_const.
* cp-trait.gperf: Reflect cp-trait.def change.
* cp-trait.h: Likewise.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_CONST.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Ken Matsui 
---
 gcc/cp/Make-lang.in  |   2 +-
 gcc/cp/constraint.cc |   3 +
 gcc/cp/cp-trait.def  |   1 +
 gcc/cp/cp-trait.gperf|   1 +
 gcc/cp/cp-trait.h| 202 ---
 gcc/cp/semantics.cc  |   4 +
 gcc/testsuite/g++.dg/ext/has-builtin-1.C |   3 +
 gcc/testsuite/g++.dg/ext/is_const.C  |  19 +++
 8 files changed, 135 insertions(+), 100 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/is_const.C

diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 8d4e3a1f594..b6e6cefca53 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -194,7 +194,7 @@ $(srcdir)/cp/cp-trait.h: $(srcdir)/cp/cp-trait.gperf
 else
 $(srcdir)/cp/cp-trait.h: | $(srcdir)/cp/cp-trait.gperf
 endif
-   gperf -o -C -E -k '8' -D -N 'find' -L C++ \
+   gperf -o -C -E -k '6,8' -D -N 'find' -L C++ \
$(srcdir)/cp/cp-trait.gperf --output-file 
$(srcdir)/cp/cp-trait.h
 
 # The cp-trait.gperf file itself is generated from a cp-trait.def file.
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 722fc334e6f..567dd35fe0a 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3723,6 +3723,9 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_CLASS:
   inform (loc, "  %qT is not a class", t1);
   break;
+case CPTK_IS_CONST:
+  inform (loc, "  %qT is not a const type", t1);
+  break;
 case CPTK_IS_CONSTRUCTIBLE:
   if (!t2)
 inform (loc, "  %qT is not default constructible", t1);
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 0e48e64b8dd..9e4e6d798a0 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -62,6 +62,7 @@ DEFTRAIT_EXPR (IS_AGGREGATE, "__is_aggregate", 1)
 DEFTRAIT_EXPR (IS_ASSIGNABLE, "__is_assignable", 2)
 DEFTRAIT_EXPR (IS_BASE_OF, "__is_base_of", 2)
 DEFTRAIT_EXPR (IS_CLASS, "__is_class", 1)
+DEFTRAIT_EXPR (IS_CONST, "__is_const", 1)
 DEFTRAIT_EXPR (IS_CONSTRUCTIBLE, "__is_constructible", -1)
 DEFTRAIT_EXPR (IS_CONVERTIBLE, "__is_convertible", 2)
 DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 47e3c1af499..47a5ec9ee6f 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -42,6 +42,7 @@ struct cp_trait {
 "__is_assignable", CPTK_IS_ASSIGNABLE, 2, false
 "__is_base_of", CPTK_IS_BASE_OF, 2, false
 "__is_class", CPTK_IS_CLASS, 1, false
+"__is_const", CPTK_IS_CONST, 1, false
 "__is_constructible", CPTK_IS_CONSTRUCTIBLE, -1, false
 "__is_convertible", CPTK_IS_CONVERTIBLE, 2, false
 "__is_empty", CPTK_IS_EMPTY, 1, false
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index 97ba8492d15..c9005eee1ff 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -1,5 +1,5 @@
 /* C++ code produced by gperf version 3.1 */
-/* Command-line: gperf -o -C -E -k 8 -D -N find -L C++ --output-file 
../../gcc/cp/cp-trait.h ../../gcc/cp/cp-trait.gperf  */
+/* Command-line: gperf -o -C -E -k 6,8 -D -N find -L C++ --output-file 
../../gcc/cp/cp-trait.h ../../gcc/cp/cp-trait.gperf  */
 
 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
   && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@@ -54,7 +54,7 @@ struct cp_trait {
   short arity;
   bool type;
 };
-/* maximum key range = 79, duplicates = 0 */
+/* maximum key range = 89, duplicates = 0 */
 
 class cp_trait_lookup
 {
@@ -69,32 +69,32 @@ cp_trait_lookup::hash (const char *str, size_t len)
 {
   static const unsigned char asso_values[] =
 {
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86,  1, 86, 86,
-   0, 35, 86,  0, 86,  0, 86, 86, 10, 10,
-  50, 15, 55, 86, 30,  5, 15,  0, 86, 86,
-  86, 20, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
-  86, 86, 86, 86, 86, 86, 86, 86, 

[PATCH v16 02/39] c-family, c++: Look up built-in traits through gperf

2023-10-10 Thread Ken Matsui
Since RID_MAX soon reaches 255 and all traits are used approximately once in
a C++ translation unit, this patch instead uses only RID_TRAIT_EXPR and
RID_TRAIT_TYPE for all traits and uses gperf to look up the specific trait.

gcc/c-family/ChangeLog:

* c-common.cc (c_common_reswords): Map all traits to RID_TRAIT_EXPR
and RID_TRAIT_TYPE instead.
* c-common.h (enum rid): Remove all existing RID values for traits.
Use RID_TRAIT_EXPR and RID_TRAIT_TYPE instead.

gcc/cp/ChangeLog:

* Make-lang.in: Add targets to generate cp-trait.gperf and
cp-trait.h.
* cp-objcp-common.cc (names_builtin_p): Remove all existing RID values
for traits.  Use RID_TRAIT_EXPR and RID_TRAIT_TYPE instead.
* parser.cc (cp_keyword_starts_decl_specifier_p): Likewise, for
type-yielding traits.  Use RID_TRAIT_TYPE instead.
(cp_parser_simple_type_specifier): Likewise.
(cp_parser_primary_expression): Likewise, for expression-yielding
traits.  Use RID_TRAIT_EXPR instead.
(cp_parser_trait): Look up traits through gperf instead of enum rid.
* cp-trait-head.in: New file.
* cp-trait.gperf: New file.
* cp-trait.h: New file.

Signed-off-by: Ken Matsui 
---
 gcc/c-family/c-common.cc  |  12 +-
 gcc/c-family/c-common.h   |   7 +-
 gcc/cp/Make-lang.in   |  24 
 gcc/cp/cp-objcp-common.cc |   6 +-
 gcc/cp/cp-trait-head.in   |  30 +
 gcc/cp/cp-trait.gperf |  74 
 gcc/cp/cp-trait.h | 247 ++
 gcc/cp/parser.cc  |  70 ---
 8 files changed, 412 insertions(+), 58 deletions(-)
 create mode 100644 gcc/cp/cp-trait-head.in
 create mode 100644 gcc/cp/cp-trait.gperf
 create mode 100644 gcc/cp/cp-trait.h

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index f044db5b797..f219ccd29e5 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -508,12 +508,16 @@ const struct c_common_resword c_common_reswords[] =
   { "wchar_t", RID_WCHAR,  D_CXXONLY },
   { "while",   RID_WHILE,  0 },
 
-#define DEFTRAIT(TCC, CODE, NAME, ARITY) \
-  { NAME,  RID_##CODE, D_CXXONLY },
+#define DEFTRAIT_EXPR(CODE, NAME, ARITY) \
+  { NAME,  RID_TRAIT_EXPR, D_CXXONLY },
 #include "cp/cp-trait.def"
-#undef DEFTRAIT
+#undef DEFTRAIT_EXPR
   /* An alias for __is_same.  */
-  { "__is_same_as",RID_IS_SAME,D_CXXONLY },
+  { "__is_same_as",RID_TRAIT_EXPR, D_CXXONLY },
+#define DEFTRAIT_TYPE(CODE, NAME, ARITY) \
+  { NAME,  RID_TRAIT_TYPE, D_CXXONLY },
+#include "cp/cp-trait.def"
+#undef DEFTRAIT_TYPE
 
   /* C++ transactional memory.  */
   { "synchronized",RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 1fdba7ef3ea..a1a641f4175 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -168,10 +168,9 @@ enum rid
   RID_BUILTIN_LAUNDER,
   RID_BUILTIN_BIT_CAST,
 
-#define DEFTRAIT(TCC, CODE, NAME, ARITY) \
-  RID_##CODE,
-#include "cp/cp-trait.def"
-#undef DEFTRAIT
+  /* C++ traits, defined in cp-trait.def.  */
+  RID_TRAIT_EXPR,
+  RID_TRAIT_TYPE,
 
   /* C++11 */
   RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 2727fb7f8cc..8d4e3a1f594 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -34,6 +34,8 @@
 # - the compiler proper (eg: cc1plus)
 # - define the names for selecting the language in LANGUAGES.
 
+AWK = @AWK@
+
 # Actual names to use when installing a native compiler.
 CXX_INSTALL_NAME := $(shell echo c++|sed '$(program_transform_name)')
 GXX_INSTALL_NAME := $(shell echo g++|sed '$(program_transform_name)')
@@ -186,6 +188,28 @@ endif
 # This is the file that depends on the generated header file.
 cp/name-lookup.o: $(srcdir)/cp/std-name-hint.h
 
+# We always need the dependency on the .gperf file because it itself is 
generated.
+ifeq ($(ENABLE_MAINTAINER_RULES), true)
+$(srcdir)/cp/cp-trait.h: $(srcdir)/cp/cp-trait.gperf
+else
+$(srcdir)/cp/cp-trait.h: | $(srcdir)/cp/cp-trait.gperf
+endif
+   gperf -o -C -E -k '8' -D -N 'find' -L C++ \
+   $(srcdir)/cp/cp-trait.gperf --output-file 
$(srcdir)/cp/cp-trait.h
+
+# The cp-trait.gperf file itself is generated from a cp-trait.def file.
+$(srcdir)/cp/cp-trait.gperf: $(srcdir)/cp/cp-trait.def 
$(srcdir)/cp/cp-trait-head.in
+   cat $(srcdir)/cp/cp-trait-head.in > $@
+   $(AWK) -F', *' '/^DEFTRAIT_/ { \
+   type = (index($$1, "DEFTRAIT_TYPE") != 0 ? "true" : "false"); \
+   gsub(/DEFTRAIT_(EXPR|TYPE) \(/, "", $$1); \
+   gsub(/\)/, "", $$3); \
+   print $$2", CPTK_" $$1", "$$3", "type; \
+   }' $(srcdir)/cp/cp-trait.def >> $@
+
+# This is the file that depends on the generated header file.
+cp/parser.o: $(srcdir)/cp/cp-trait.h
+
 components_in_prev = "bfd opcodes binutils 

[PATCH v16 01/39] c++: Sort built-in identifiers alphabetically

2023-10-10 Thread Ken Matsui
This patch sorts built-in identifiers alphabetically for better code
readability.

gcc/cp/ChangeLog:

* constraint.cc (diagnose_trait_expr): Sort built-in identifiers
alphabetically.
* cp-trait.def: Likewise.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.
(finish_trait_type): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Sort built-in identifiers
alphabetically.

Signed-off-by: Ken Matsui 
---
 gcc/cp/constraint.cc | 68 -
 gcc/cp/cp-trait.def  | 10 +--
 gcc/cp/semantics.cc  | 94 
 gcc/testsuite/g++.dg/ext/has-builtin-1.C | 70 +-
 4 files changed, 121 insertions(+), 121 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c9e4e7043cd..722fc334e6f 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3702,18 +3702,36 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_HAS_TRIVIAL_DESTRUCTOR:
   inform (loc, "  %qT is not trivially destructible", t1);
   break;
+case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
+  inform (loc, "  %qT does not have unique object representations", t1);
+  break;
 case CPTK_HAS_VIRTUAL_DESTRUCTOR:
   inform (loc, "  %qT does not have a virtual destructor", t1);
   break;
 case CPTK_IS_ABSTRACT:
   inform (loc, "  %qT is not an abstract class", t1);
   break;
+case CPTK_IS_AGGREGATE:
+  inform (loc, "  %qT is not an aggregate", t1);
+  break;
+case CPTK_IS_ASSIGNABLE:
+  inform (loc, "  %qT is not assignable from %qT", t1, t2);
+  break;
 case CPTK_IS_BASE_OF:
   inform (loc, "  %qT is not a base of %qT", t1, t2);
   break;
 case CPTK_IS_CLASS:
   inform (loc, "  %qT is not a class", t1);
   break;
+case CPTK_IS_CONSTRUCTIBLE:
+  if (!t2)
+inform (loc, "  %qT is not default constructible", t1);
+  else
+inform (loc, "  %qT is not constructible from %qE", t1, t2);
+  break;
+case CPTK_IS_CONVERTIBLE:
+  inform (loc, "  %qT is not convertible from %qE", t2, t1);
+  break;
 case CPTK_IS_EMPTY:
   inform (loc, "  %qT is not an empty class", t1);
   break;
@@ -3729,6 +3747,18 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_LITERAL_TYPE:
   inform (loc, "  %qT is not a literal type", t1);
   break;
+case CPTK_IS_NOTHROW_ASSIGNABLE:
+  inform (loc, "  %qT is not nothrow assignable from %qT", t1, t2);
+  break;
+case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
+  if (!t2)
+   inform (loc, "  %qT is not nothrow default constructible", t1);
+  else
+   inform (loc, "  %qT is not nothrow constructible from %qE", t1, t2);
+  break;
+case CPTK_IS_NOTHROW_CONVERTIBLE:
+ inform (loc, "  %qT is not nothrow convertible from %qE", t2, t1);
+  break;
 case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF:
   inform (loc, "  %qT is not pointer-interconvertible base of %qT",
  t1, t2);
@@ -3748,50 +3778,20 @@ diagnose_trait_expr (tree expr, tree args)
 case CPTK_IS_TRIVIAL:
   inform (loc, "  %qT is not a trivial type", t1);
   break;
-case CPTK_IS_UNION:
-  inform (loc, "  %qT is not a union", t1);
-  break;
-case CPTK_IS_AGGREGATE:
-  inform (loc, "  %qT is not an aggregate", t1);
-  break;
-case CPTK_IS_TRIVIALLY_COPYABLE:
-  inform (loc, "  %qT is not trivially copyable", t1);
-  break;
-case CPTK_IS_ASSIGNABLE:
-  inform (loc, "  %qT is not assignable from %qT", t1, t2);
-  break;
 case CPTK_IS_TRIVIALLY_ASSIGNABLE:
   inform (loc, "  %qT is not trivially assignable from %qT", t1, t2);
   break;
-case CPTK_IS_NOTHROW_ASSIGNABLE:
-  inform (loc, "  %qT is not nothrow assignable from %qT", t1, t2);
-  break;
-case CPTK_IS_CONSTRUCTIBLE:
-  if (!t2)
-   inform (loc, "  %qT is not default constructible", t1);
-  else
-   inform (loc, "  %qT is not constructible from %qE", t1, t2);
-  break;
 case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
   if (!t2)
inform (loc, "  %qT is not trivially default constructible", t1);
   else
inform (loc, "  %qT is not trivially constructible from %qE", t1, t2);
   break;
-case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
-  if (!t2)
-   inform (loc, "  %qT is not nothrow default constructible", t1);
-  else
-   inform (loc, "  %qT is not nothrow constructible from %qE", t1, t2);
-  break;
-case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
-  inform (loc, "  %qT does not have unique object representations", t1);
-  break;
-case CPTK_IS_CONVERTIBLE:
-  inform (loc, "  %qT is not convertible from %qE", t2, t1);
+case CPTK_IS_TRIVIALLY_COPYABLE:
+  inform (loc, "  %qT is not trivially copyable", t1);
   break;
-case 

[PATCH v16 00/39] Optimize type traits performance

2023-10-10 Thread Ken Matsui
This patch series optimizes type traits performance by implementing
built-in type traits and using them in libstdc++.

Changes in v16:

* Rebased on top of trunk
* Improved clarity of the commit message
* Simplified Make-lang.in and gperf struct

Changes in v15:

* Rebased on top of trunk
* Use gperf to look up traits instead of enum rid

Changes in v14:

* Added padding calculation to the commit message

Changes in v13:

* Fixed ambiguous commit message and comment

Changes in v12:

* Evaluated all paddings affected by the enum rid change

Changes in v11:

* Merged all patches into one patch series
* Rebased on top of trunk
* Unified commit message style
* Used _GLIBCXX_USE_BUILTIN_TRAIT

Ken Matsui (39):
  c++: Sort built-in identifiers alphabetically
  c-family, c++: Look up built-in traits through gperf
  c++: Implement __is_const built-in trait
  libstdc++: Optimize is_const trait performance
  c++: Implement __is_volatile built-in trait
  libstdc++: Optimize is_volatile trait performance
  c++: Implement __is_array built-in trait
  libstdc++: Optimize is_array trait performance
  c++: Implement __is_unbounded_array built-in trait
  libstdc++: Optimize is_unbounded_array trait performance
  c++: Implement __is_bounded_array built-in trait
  libstdc++: Optimize is_bounded_array trait performance
  c++: Implement __is_scoped_enum built-in trait
  libstdc++: Optimize is_scoped_enum trait performance
  c++: Implement __is_member_pointer built-in trait
  libstdc++: Optimize is_member_pointer trait performance
  c++: Implement __is_member_function_pointer built-in trait
  libstdc++: Optimize is_member_function_pointer trait performance
  c++: Implement __is_member_object_pointer built-in trait
  libstdc++: Optimize is_member_object_pointer trait performance
  c++: Implement __is_reference built-in trait
  libstdc++: Optimize is_reference trait performance
  c++: Implement __is_function built-in trait
  libstdc++: Optimize is_function trait performance
  libstdc++: Optimize is_object trait performance
  c++: Implement __remove_pointer built-in trait
  libstdc++: Optimize remove_pointer trait performance
  c++, libstdc++: Implement __is_pointer built-in trait
  libstdc++: Optimize is_pointer trait performance
  c++, libstdc++: Implement __is_arithmetic built-in trait
  libstdc++: Optimize is_arithmetic trait performance
  libstdc++: Optimize is_fundamental trait performance
  libstdc++: Optimize is_compound trait performance
  c++: Implement __is_unsigned built-in trait
  libstdc++: Optimize is_unsigned trait performance
  c++, libstdc++: Implement __is_signed built-in trait
  libstdc++: Optimize is_signed trait performance
  c++, libstdc++: Implement __is_scalar built-in trait
  libstdc++: Optimize is_scalar trait performance

 gcc/c-family/c-common.cc  |  12 +-
 gcc/c-family/c-common.h   |   7 +-
 gcc/cp/Make-lang.in   |  24 ++
 gcc/cp/constraint.cc  | 112 +--
 gcc/cp/cp-objcp-common.cc |   6 +-
 gcc/cp/cp-trait-head.in   |  30 ++
 gcc/cp/cp-trait.def   |  27 +-
 gcc/cp/cp-trait.gperf |  91 ++
 gcc/cp/cp-trait.h | 285 ++
 gcc/cp/parser.cc  |  70 ++---
 gcc/cp/semantics.cc   | 157 +++---
 gcc/testsuite/g++.dg/ext/has-builtin-1.C  | 117 +--
 gcc/testsuite/g++.dg/ext/is_arithmetic.C  |  33 ++
 gcc/testsuite/g++.dg/ext/is_array.C   |  28 ++
 gcc/testsuite/g++.dg/ext/is_bounded_array.C   |  38 +++
 gcc/testsuite/g++.dg/ext/is_const.C   |  19 ++
 gcc/testsuite/g++.dg/ext/is_function.C|  58 
 .../g++.dg/ext/is_member_function_pointer.C   |  31 ++
 .../g++.dg/ext/is_member_object_pointer.C |  30 ++
 gcc/testsuite/g++.dg/ext/is_member_pointer.C  |  30 ++
 gcc/testsuite/g++.dg/ext/is_pointer.C |  51 
 gcc/testsuite/g++.dg/ext/is_reference.C   |  34 +++
 gcc/testsuite/g++.dg/ext/is_scalar.C  |  31 ++
 gcc/testsuite/g++.dg/ext/is_scoped_enum.C |  67 
 gcc/testsuite/g++.dg/ext/is_signed.C  |  47 +++
 gcc/testsuite/g++.dg/ext/is_unbounded_array.C |  37 +++
 gcc/testsuite/g++.dg/ext/is_unsigned.C|  47 +++
 gcc/testsuite/g++.dg/ext/is_volatile.C|  19 ++
 gcc/testsuite/g++.dg/ext/remove_pointer.C |  51 
 gcc/testsuite/g++.dg/tm/pr46567.C |  48 +--
 gcc/testsuite/g++.dg/torture/20070621-1.C |   4 +-
 gcc/testsuite/g++.dg/torture/pr57107.C|   8 +-
 libstdc++-v3/include/bits/charconv.h  |   2 +-
 libstdc++-v3/include/bits/cpp_type_traits.h   |  18 +-
 libstdc++-v3/include/bits/deque.tcc   |   6 +-
 libstdc++-v3/include/bits/locale_facets.tcc   |   6 +-
 libstdc++-v3/include/bits/stl_algobase.h  |  14 +-
 

[committed] [PR target/93062] RISC-V: Handle long conditional branches for RISC-V

2023-10-10 Thread Jeff Law


Ventana has had a variant of this patch from Andrew W. in its tree for 
at least a year.   I'm dusting it off and submitting it on Andrew's behalf.


There's multiple approaches we could be using here.

First we could make $ra fixed and use it as the scratch register for the 
long branch sequences.


Second, we could add a match_scratch to all the conditional branch 
patterns and allow the register allocator to assign the scratch register 
from the pool of GPRs.


Third we could do register scavenging.  This can usually work, though it 
can get complex in some scenarios.


Forth we could use trampolines for extended reach.

Andrew's original patch did a bit of the first approach (make $ra fixed) 
and mostly the second approach.  The net is it was probably the worst in 
terms of impacting code generation -- we lost a register *and* forced 
every branch instruction to get a scratch register allocated.


I had expected the second approach to produce better code than the 
first, but that wasn't actually the case in practice.  It's probably a 
combination of allocating a GPR at every branch point (even with a life 
of a single insn, there's a cost) and perhaps the additional operands on 
conditional branches spoiling simplistic pattern matching in one or more 
passes.


In addition to performing better based on dynamic instruction counts, 
the first approach is significantly simpler to implement.  Given those 
two positives, that's what I've chosen to go with.  Yes it does remove 
$ra from the set of registers available, but the impact of that is *tiny*.


If someone wanted to dive into one of the other approaches to address a 
real world impact, that's great.  If that happens I would strongly 
suggest also evaluating perlbench from spec2017.  It seems particularly 
sensitive to this issue in terms of approach #2's impact on code generation.


I've built & regression tested this variant on the vt1 configuration 
without regressions.  Earlier versions have been bootstrapped as well.


Pushed to the trunk,

Jeff

commit 71f906498ada9ec2780660b03bd6e27a93ad350c
Author: Andrew Waterman 
Date:   Tue Oct 10 12:34:04 2023 -0600

RISC-V: far-branch: Handle far jumps and branches for functions larger than 
1MB

On RISC-V, branches further than +/-1MB require a longer instruction
sequence (3 instructions): we can reuse the jump-construction in the
assmbler (which clobbers $ra) and a temporary to set up the jump
destination.

gcc/ChangeLog:

* config/riscv/riscv.cc (struct machine_function): Track if a
far-branch/jump is used within a function (and $ra needs to be
saved).
(riscv_print_operand): Implement 'N' (inverse integer branch).
(riscv_far_jump_used_p): Implement.
(riscv_save_return_addr_reg_p): New function.
(riscv_save_reg_p): Use riscv_save_return_addr_reg_p.
* config/riscv/riscv.h (FIXED_REGISTERS): Update $ra.
(CALL_USED_REGISTERS): Update $ra.
* config/riscv/riscv.md: Add new types "ret" and "jalr".
(length attribute): Handle long conditional and unconditional
branches.
(conditional branch pattern): Handle case where jump can not
reach the intended target.
(indirect_jump, tablejump): Use new "jalr" type.
(simple_return): Use new "ret" type.
(simple_return_internal, eh_return_internal): Likewise.
(gpr_restore_return, riscv_mret): Likewise.
(riscv_uret, riscv_sret): Likewise.
* config/riscv/generic.md (generic_branch): Also recognize jalr & 
ret
types.
* config/riscv/sifive-7.md (sifive_7_jump): Likewise.

Co-authored-by: Philipp Tomsich 
Co-authored-by: Jeff Law 

diff --git a/gcc/config/riscv/generic.md b/gcc/config/riscv/generic.md
index 57d3c3b4adc..88940483829 100644
--- a/gcc/config/riscv/generic.md
+++ b/gcc/config/riscv/generic.md
@@ -47,7 +47,7 @@ (define_insn_reservation "generic_xfer" 3
 
 (define_insn_reservation "generic_branch" 1
   (and (eq_attr "tune" "generic")
-   (eq_attr "type" "branch,jump,call"))
+   (eq_attr "type" "branch,jump,call,jalr"))
   "alu")
 
 (define_insn_reservation "generic_imul" 10
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index b7acf836d02..d17139e945e 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -183,6 +183,9 @@ struct GTY(())  machine_function {
   /* True if attributes on current function have been checked.  */
   bool attributes_checked_p;
 
+  /* True if RA must be saved because of a far jump.  */
+  bool far_jump_used;
+
   /* The current frame information, calculated by riscv_compute_frame_info.  */
   struct riscv_frame_info frame;
 
@@ -5448,6 +5451,7 @@ riscv_get_v_regno_alignment (machine_mode mode)
  any outermost HIGH.
'R' Print the low-part relocation associated with OP.
'C' 

Re: Re: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'

2023-10-10 Thread 钟居哲
Thanks for investigation. I think the number 145 is reasonable.

Even though it is more than my number. 

I guess the reason you still have more FAILs than me because you are using QEMU 
(I am using SPIKE), also you need to specify miasligned option to the simulator.

For example, for SPIKE,  we need --misaligned to the SPIKE.

But anyway, no need to send me the FAILs report.  I just want to make sure I am 
not missing some FAILs.




juzhe.zh...@rivai.ai
 
From: Maciej W. Rozycki
Date: 2023-10-11 05:35
To: juzhe.zhong
CC: gcc-patches; jeffreyalaw; Robin Dapp; Kito.cheng
Subject: Re: Re: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'
On Tue, 10 Oct 2023, juzhe.zh...@rivai.ai wrote:
 
> It's weird. Could you give me the FAILs report?
 
I keep forgetting that I have a piece of code in my board description 
files that makes the testsuite leave output files in place, which helps 
much when debugging failures (although it's not a perfect solution for 
test cases like those verified at different optimisation levels where the 
output filename is reused and consequently subsequent outputs overwrite 
earlier ones; something to improve perhaps).  Unfortunately the presence 
of output files confuses some test cases and makes them fail; arguably a 
test case bug.  None of the offending test cases are directly related to 
RISC-V development, so I just ignore the presence of these failures and 
only focus on regressions and progressions between testsuite runs.
 
Here are fresh results with the testsuite output tree made tidy:
 
=== gcc Summary ===
 
# of expected passes 194602
# of unexpected failures 145
# of unexpected successes 11
# of expected failures 1631
# of unresolved testcases 120
# of unsupported tests 3828
 
It probably makes no sense to clutter the mailing list with my FAIL and 
UNRESOLVED results; I can send them off-list if you find them useful.
 
  Maciej
 


Re: Re: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'

2023-10-10 Thread Maciej W. Rozycki
On Tue, 10 Oct 2023, juzhe.zh...@rivai.ai wrote:

> It's weird. Could you give me the FAILs report?

 I keep forgetting that I have a piece of code in my board description 
files that makes the testsuite leave output files in place, which helps 
much when debugging failures (although it's not a perfect solution for 
test cases like those verified at different optimisation levels where the 
output filename is reused and consequently subsequent outputs overwrite 
earlier ones; something to improve perhaps).  Unfortunately the presence 
of output files confuses some test cases and makes them fail; arguably a 
test case bug.  None of the offending test cases are directly related to 
RISC-V development, so I just ignore the presence of these failures and 
only focus on regressions and progressions between testsuite runs.

 Here are fresh results with the testsuite output tree made tidy:

=== gcc Summary ===

# of expected passes194602
# of unexpected failures145
# of unexpected successes   11
# of expected failures  1631
# of unresolved testcases   120
# of unsupported tests  3828

It probably makes no sense to clutter the mailing list with my FAIL and 
UNRESOLVED results; I can send them off-list if you find them useful.

  Maciej


[pushed] c++: mangle multiple levels of template parms [PR109422]

2023-10-10 Thread Jason Merrill
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

This becomes be more important with concepts, but can also be seen with
generic lambdas.

PR c++/109422

gcc/cp/ChangeLog:

* mangle.cc (write_template_param): Also mangle level.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-generic-mangle1.C: New test.
* g++.dg/cpp2a/lambda-generic-mangle1a.C: New test.
---
 gcc/cp/mangle.cc| 13 +
 gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1.C |  9 +
 .../g++.dg/cpp2a/lambda-generic-mangle1a.C  | 10 ++
 3 files changed, 32 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1a.C

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index d88c779bfa2..d079f724910 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -3921,6 +3921,7 @@ static void
 write_template_param (const tree parm)
 {
   int parm_index;
+  int level;
 
   MANGLE_TRACE_TREE ("template-parm", parm);
 
@@ -3930,10 +3931,12 @@ write_template_param (const tree parm)
 case TEMPLATE_TEMPLATE_PARM:
 case BOUND_TEMPLATE_TEMPLATE_PARM:
   parm_index = TEMPLATE_TYPE_IDX (parm);
+  level = TEMPLATE_TYPE_LEVEL (parm);
   break;
 
 case TEMPLATE_PARM_INDEX:
   parm_index = TEMPLATE_PARM_IDX (parm);
+  level = TEMPLATE_PARM_LEVEL (parm);
   break;
 
 default:
@@ -3941,6 +3944,16 @@ write_template_param (const tree parm)
 }
 
   write_char ('T');
+  if (level > 1)
+{
+  if (abi_warn_or_compat_version_crosses (19))
+   G.need_abi_warning = 1;
+  if (abi_version_at_least (19))
+   {
+ write_char ('L');
+ write_compact_number (level - 1);
+   }
+}
   /* NUMBER as it appears in the mangling is (-1)-indexed, with the
  earliest template param denoted by `_'.  */
   write_compact_number (parm_index);
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1.C
new file mode 100644
index 000..0051307f53d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1.C
@@ -0,0 +1,9 @@
+// PR c++/109422
+// { dg-do compile { target c++20 } }
+
+struct C {
+  template
+  void f(decltype([](T, auto) { return 0; })) {}
+};
+void g() { C().f({}); }
+// { dg-final { scan-assembler "_ZN1C1fIiEEvDTtlNS_UlT_TL0__E_EEE" } }
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1a.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1a.C
new file mode 100644
index 000..dc7b0125631
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-generic-mangle1a.C
@@ -0,0 +1,10 @@
+// PR c++/109422
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fabi-version=18" }
+
+struct C {
+  template
+  void f(decltype([](T, auto) { return 0; })) {}
+};
+void g() { C().f({}); }
+// { dg-final { scan-assembler "_ZN1C1fIiEEvDTtlNS_UlT_T_E_EEE" } }

base-commit: aaa5a5318adbefe87c1b781b8a3e5fc332e661ec
-- 
2.39.3



Re: [RFC] RISC-V: Handle new types in scheduling descriptions

2023-10-10 Thread Edwin Lu

On 10/10/2023 10:11 AM, Jeff Law wrote:



On 10/9/23 15:02, Edwin Lu wrote:

Now that every insn is guaranteed a type, we want to ensure the types are
handled by the existing scheduling descriptions.

There are 2 approaches I see:
1. Create a new pipeline intended to eventually abort (sifive-7.md)
2. Add the types to an existing pipeline (generic.md)

Which approach do we want to go with? If there is a different approach we
want to take instead, please let me know as well.

Additionally, should types associated with specific extensions
(vector, crypto, etc) have specific pipelines dedicated to them?

* config/riscv/generic.md: update pipeline
* config/riscv/sifive-7.md (sifive_7): update pipeline
(sifive_7_other):
I'd largely expect that we look at an unhandled type and first look to 
see if its properties roughly fit into an existing define_insn_unit.  If 
so, just add it to the existing unit.  Otherwise we end up needing to 
create another unit.


The main types that were added that are not associated with any 
extension would be "trap" type and the "cbo" (cache block operation) 
type. I have added these types to an existing pipeline in the generic.md 
file.


For the vector extension, I don't believe the existing pipelines would 
support those operations. Should I create the pipelines for now?


What would be really interesting would be to see if we can get the 
scheduler to indicate that it's trying to schedule an insn that doesn't 
have a reservation.    ie, our backend tells us if we have an insn with 
no type, the next step is to see if we have a type with no 
units/reservations.



Jeff

Do you happen to have any idea on how to do this or if there are any 
existing mechanisms I should look at? I have been searching around the 
docs to see if there was any way to tell which pipeline (if any) an 
instruction is using when it is not included under a reservation without 
any luck.


Edwin


Re: [PATCH] wide-int: Allow up to 16320 bits wide_int and change widest_int precision to 32640 bits [PR102989]

2023-10-10 Thread Jakub Jelinek
On Tue, Oct 10, 2023 at 06:41:50PM +0100, Richard Sandiford wrote:
> > On the wide_int side, I see
> >  155291 576
> > (supposedly because of bound_wide_int, where we create wide_int_ref from
> > the 576-bit precision bound_wide_int and then create 576-bit wide_int when
> > using unary or binary operation on that).
> 
> 576 bits seems quite a lot for a loop bound.  We're enterning near-infinite
> territory with 128 bits. :)  But I don't want to rehash old discussions.
> If we take this size for wide_int as given, then...

We could go for 128 bits bounds_wide_int and redo the stats given that.
Though maybe such tweaks can be done incrementally.

> > So, perhaps we could get away with say WIDEST_INT_MAX_INL_ELTS of 5 or 6
> > instead of 9 but keep WIDE_INT_MAX_INL_ELTS at 9 (or whatever is computed
> > from MAX_BITSIZE_MODE_ANY_INT?).  Or keep it at 9 for both (i.e. without
> > the third patch).
> 
> ...I agree we might as well keep the widest_int size the same for
> simplicity.  It'd only be worth distinguishing them if we have positive
> proof that it's worthwhile.
> 
> So going with patches 1 + 2 sounds good to me, but I don't have a strong
> preference.

Ok.

> > +  if (prec > WIDE_INT_MAX_INL_PRECISION && !high)
> > +prec = (op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT;
> 
> Changing the precision looked a bit dangerous at first, but I agree it
> looks correct in context, in that nothing later on seems to require prec
> to be the real precision of the number.  But I wonder whether we should
> instead do:
> 
>   if (!high)
> prec = MIN ((op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT, prec);

Ok, will try that (and in other spots too).

> so that the assumption gets a bit more testing.  Same idea for the others.
> I.e. in any case where we think it's safe to reduce a precision or
> length for out-of-line buffers, I think we should try to do the same
> for inline ones.
> 
> I'm not sure off-hand why + 1 is safe here but + 2 is needed for the
> write_val estimate.  Might be worth a comment in one place or the other.

As I wrote earlier, I'm not sure about the need for the + 1 above in
prec computation, perhaps just
  if (!high)
prec = MIN ((op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT, prec);
could work too (especially if the multiplication is always signed vs. signed
or unsigned vs. unsigned).  Even say
  HOST_WIDE_INT_MIN * HOST_WIDE_INT_MIN (i.e. op1len == op2len == 1) result
of 0x4000'0'' (for smallest signed^2) or
~(unsigned HOST_WIDE_INT) 0 * ~(unsigned HOST_WIDE_INT) 0 (largest
unsigned^2) of
0x'fffe''0001
fits into prec 2; and for widest_int-like representation,
0x'ff wouldn't have op1len 1, but 2; but the + 1 on top of
that is needed because of the way wi_pack then works.  But guess will try to
play with it some more tomorrow.

> > @@ -2399,9 +2453,12 @@ from_int (int i)
> >  static void
> >  assert_deceq (const char *expected, const wide_int_ref , signop sgn)
> >  {
> > -  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
> > -  print_dec (wi, buf, sgn);
> > -  ASSERT_STREQ (expected, buf);
> > +  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
> > +  unsigned len = wi.get_len ();
> > +  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
> > +p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> 
> Is this size enough for decimal?  E.g. to go back to the 576-bit example,
> 2^575 is O(10^173), but 576/4+4 == 148.

generic_wide_ints with precision larger than HOST_BITS_PER_WIDE_INT and
length larger than 1 are always printed hexadecimally, we don't have code to
print it decimally (it wouldn't be terribly hard, we have divmod, but could
be expensive).  Though, I've always wondered why we at least for print_decs
don't print negative values as -0xwhatever, rather than 0xsomethinglarge.
Any change in this area could affect a lot of dumps though.

Jakub



Re: [PATCH] RFC: Add late-combine pass [PR106594]

2023-10-10 Thread Jeff Law




On 10/7/23 06:58, Richard Sandiford wrote:



Yeah, that'd probably be best.  I need to split the patch up into a
proper submission sequence, do more testing, and make it RFA quality.
Jeff has also found a couple of regressions that I need to look at.
When you've got updates, just let me know.  I can drop them into the CI 
system and see what pops out.


Jeff


Re: [PATCH] wide-int: Allow up to 16320 bits wide_int and change widest_int precision to 32640 bits [PR102989]

2023-10-10 Thread Richard Sandiford
Jakub Jelinek  writes:
> On Mon, Oct 09, 2023 at 03:44:10PM +0200, Jakub Jelinek wrote:
>> Thanks, just quick answers, will work on patch adjustments after trying to
>> get rid of rwide_int (seems dwarf2out has very limited needs from it, just
>> some routine to construct it in GCed memory (and never change afterwards)
>> from const wide_int_ref & or so, and then working operator ==,
>> get_precision, elt, get_len and get_val methods, so I think we could just
>> have a struct dw_wide_int { unsigned int prec, len; HOST_WIDE_INT val[1]; };
>> and perform the methods on it after converting to a storage ref.
>
> Now in patch form (again, incremental).
>
>> > Does the variable-length memcpy pay for itself?  If so, perhaps that's a
>> > sign that we should have a smaller inline buffer for this class (say 2 
>> > HWIs).
>> 
>> Guess I'll try to see what results in smaller .text size.
>
> I've left the memcpy changes into a separate patch (incremental, attached).
> Seems that second patch results in .text growth by 16256 bytes (0.04%),
> though I'd bet it probably makes compile time tiny bit faster because it
> replaces an out of line memcpy (caused by variable length) with inlined one.
>
> With even the third one it shrinks by 84544 bytes (0.21% down), but the
> extra statistics patch then shows massive number of allocations after
> running make check-gcc check-g++ check-gfortran for just a minute or two.
> On the widest_int side, I see (first number from sort | uniq -c | sort -nr,
> second the estimated or final len)
> 7289034 4
>  173586 5
>   21819 6
> i.e. there are tons of widest_ints which need len 4 (or perhaps just
> have it as upper estimation), maybe even 5 would be nice.

Thanks for running the stats.  That's definitely a lot more than I expected.

> On the wide_int side, I see
>  155291 576
> (supposedly because of bound_wide_int, where we create wide_int_ref from
> the 576-bit precision bound_wide_int and then create 576-bit wide_int when
> using unary or binary operation on that).

576 bits seems quite a lot for a loop bound.  We're enterning near-infinite
territory with 128 bits. :)  But I don't want to rehash old discussions.
If we take this size for wide_int as given, then...

> So, perhaps we could get away with say WIDEST_INT_MAX_INL_ELTS of 5 or 6
> instead of 9 but keep WIDE_INT_MAX_INL_ELTS at 9 (or whatever is computed
> from MAX_BITSIZE_MODE_ANY_INT?).  Or keep it at 9 for both (i.e. without
> the third patch).

...I agree we might as well keep the widest_int size the same for
simplicity.  It'd only be worth distinguishing them if we have positive
proof that it's worthwhile.

So going with patches 1 + 2 sounds good to me, but I don't have a strong
preference.

On the wide-int.cc changes:

> @@ -1469,6 +1452,36 @@ wi::mul_internal (HOST_WIDE_INT *val, co
>return 1;
>  }
> 
> +  /* The sizes here are scaled to support a 2x WIDE_INT_MAX_INL_PRECISION by 
> 2x
> + WIDE_INT_MAX_INL_PRECISION yielding a 4x WIDE_INT_MAX_INL_PRECISION
> + result.  */
> +
> +  unsigned HOST_HALF_WIDE_INT
> +ubuf[4 * WIDE_INT_MAX_INL_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
> +  unsigned HOST_HALF_WIDE_INT
> +vbuf[4 * WIDE_INT_MAX_INL_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
> +  /* The '2' in 'R' is because we are internally doing a full
> + multiply.  */
> +  unsigned HOST_HALF_WIDE_INT
> +rbuf[2 * 4 * WIDE_INT_MAX_INL_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
> +  const HOST_WIDE_INT mask = ((HOST_WIDE_INT)1 << 
> HOST_BITS_PER_HALF_WIDE_INT) - 1;
> +  unsigned HOST_HALF_WIDE_INT *u = ubuf;
> +  unsigned HOST_HALF_WIDE_INT *v = vbuf;
> +  unsigned HOST_HALF_WIDE_INT *r = rbuf;
> +
> +  if (prec > WIDE_INT_MAX_INL_PRECISION && !high)
> +prec = (op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT;

Changing the precision looked a bit dangerous at first, but I agree it
looks correct in context, in that nothing later on seems to require prec
to be the real precision of the number.  But I wonder whether we should
instead do:

  if (!high)
prec = MIN ((op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT, prec);

so that the assumption gets a bit more testing.  Same idea for the others.
I.e. in any case where we think it's safe to reduce a precision or
length for out-of-line buffers, I think we should try to do the same
for inline ones.

I'm not sure off-hand why + 1 is safe here but + 2 is needed for the
write_val estimate.  Might be worth a comment in one place or the other.

> +  unsigned int blocks_needed = BLOCKS_NEEDED (prec);
> +  unsigned int half_blocks_needed = blocks_needed * 2;
> +  if (UNLIKELY (prec > WIDE_INT_MAX_INL_PRECISION))
> +{
> +  unsigned HOST_HALF_WIDE_INT *buf
> + = XALLOCAVEC (unsigned HOST_HALF_WIDE_INT, 4 * 4 * blocks_needed);
> +  u = buf;
> +  v = u + 4 * blocks_needed;
> +  r = v + 4 * blocks_needed;
> +}
> +
>/* We do unsigned mul and then correct it.  */
>wi_unpack (u, op1val, op1len, half_blocks_needed, prec, 

[PATCH v2] c++: implement P2564, consteval needs to propagate up [PR107687]

2023-10-10 Thread Marek Polacek
On Tue, Aug 29, 2023 at 03:26:46PM -0400, Jason Merrill wrote:
> On 8/23/23 15:49, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > 
> > -- >8 --
> > 
> > This patch implements P2564, described at , whereby
> > certain functions are promoted to consteval.  For example:
> 
> Great, thanks!

Thanks for looking into this.  It's kept me occupied for quite a while.
 
> >consteval int id(int i) { return i; }
> > 
> >template 
> >constexpr int f(T t)
> >{
> >  return t + id(t); // id causes f to be promoted to consteval
> >}
> > 
> >void g(int i)
> >{
> >  f (3);
> >}
> > 
> > now compiles.  Previously the code was ill-formed: we would complain
> > that 't' in 'f' is not a constant expression.  Since 'f' is now
> > consteval, it means that the call to id(t) is in an immediate context,
> > so doesn't have to produce a constant -- this is how we allow consteval
> > functions composition.  But making 'f' consteval also means that
> > the call to 'f' in 'g' must yield a constant; failure to do so results
> > in an error.  I made the effort to have cc1plus explain to us what's
> > going on.  For example, calling f(i) produces this neat diagnostic:
> > 
> > q.C: In function 'void g(int)':
> > q.C:11:5: error: call to consteval function 'f(i)' is not a constant 
> > expression
> > 11 |   f (i);
> >|   ~~^~~
> > q.C:6:16: note: 'constexpr int f(T) [with T = int]' was promoted to an 
> > immediate function because its body contains an immediate-escalating 
> > expression 'id(t)'
> >  6 |   return t + id(t);
> >|  ~~^~~
> > 
> > which hopefully makes it clear what's going on.
> > 
> > Implementing this proposal has been tricky.  One problem was delayed
> > instantiation: instantiating a function can set off a domino effect
> > where one call promotes a function to consteval but that then means
> > that another function should also be promoted, etc.
> 
> What I expected was that we would instantiate when we see a call, i.e.
> immediate_invocation_p would instantiate its argument if it's an
> immediate-escalating function.  But...
> 
> > I previously thought that I could get past that by implementing the 
> > propagation in
> > cp_gimplify_expr at which point we have already instantiated everything
> > via instantiate_pending_templates.
> 
> ...this sounds like a clever way to avoid the problems we tend to see with
> eager instantiation (e.g. constexpr-inst1.C).  It still seems promising to
> me.

This v2 does the propagation much later.
 
> > But I realized that we don't gimplify e.g.
> > 
> >static auto p = 
> 
> Indeed, just cp_fully_fold_init them, at least until we build the global
> init function.

This is now handled differently, as described below.
 
> > and so we'd never detect taking the address of a consteval function.
> > Therefore this patch instantiates immediate-escalating functions
> > beforehand.
> 
> Relatedly, in one of the testcases you have
> 
> > +template 
> > +constexpr int f2(T);
> > +
> > +// ??? clang++ emits
> > +// error: immediate function 'f2' used before it is defined
> > +// error: immediate function 'f2' used before it is defined
> > +// but at this point we don't know that f2 will be updated to consteval?
> > +auto a2 = ;
> > +auto b2 = ;
> > +
> > +template 
> > +constexpr int f2(T t) {
> > +return id(t);
> 
> This is a case where we can't immediately resolve the question anyway, we
> need to remember where we've seen bare references to immediate-escalating
> functions outside of other immediate-escalating (or already immediate)
> functions, and complain later if they became consteval when instantiated.

This now works correctly by remembering the references until EOF.
 
> I don't see why this is a significant obstacle to doing escalation late.

I've described some of this in the patch description.
 
> > * cp-tree.h (ADDR_EXPR_DENOTES_CALL_P): Define.
> 
> Is this flag just for rejecting consteval-prop10.C?  I think we should not
> try to reject it.  This came up previously in the context of my patch for
> CWG2631, at which point I argued to CWG that it should be allowed, but
> nobody responded.  I'll ping that thread now, but in the mean time let's not
> go out of our way to reject this testcase that seems to me pretty clearly
> allowed by the current wording: that expression invokes an immediate
> function, so it's an immediate invocation.

(This flag was introduced in my earlier patch.)
 
> > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> > index 673ec91d60e..31f78b71fe1 100644
> > --- a/gcc/cp/call.cc
> > +++ b/gcc/cp/call.cc
> > @@ -9735,7 +9735,9 @@ build_trivial_dtor_call (tree instance, bool 
> > no_ptr_deref)
> >   /* Return true if in an immediate function context, or an unevaluated 
> > operand,
> >  or a default argument/member initializer, or a subexpression of an 
> > immediate
> > -   invocation.  */
> > +   invocation.
> > +   ??? P2564 says 

Re: [RFC] RISC-V: Handle new types in scheduling descriptions

2023-10-10 Thread Jeff Law




On 10/9/23 15:02, Edwin Lu wrote:

Now that every insn is guaranteed a type, we want to ensure the types are
handled by the existing scheduling descriptions.

There are 2 approaches I see:
1. Create a new pipeline intended to eventually abort (sifive-7.md)
2. Add the types to an existing pipeline (generic.md)

Which approach do we want to go with? If there is a different approach we
want to take instead, please let me know as well.

Additionally, should types associated with specific extensions
(vector, crypto, etc) have specific pipelines dedicated to them?

* config/riscv/generic.md: update pipeline
* config/riscv/sifive-7.md (sifive_7): update pipeline
(sifive_7_other):
I'd largely expect that we look at an unhandled type and first look to 
see if its properties roughly fit into an existing define_insn_unit.  If 
so, just add it to the existing unit.  Otherwise we end up needing to 
create another unit.


What would be really interesting would be to see if we can get the 
scheduler to indicate that it's trying to schedule an insn that doesn't 
have a reservation.ie, our backend tells us if we have an insn with 
no type, the next step is to see if we have a type with no 
units/reservations.



Jeff


[Patch] Fortran: Support OpenMP's 'allocate' directive for stack vars

2023-10-10 Thread Tobias Burnus

The attached patch adds 'omp allocate' support for stack/automatic variables
variables for Fortran.

I had originally a pure FE version for Fortran, which failed with 
'defaultmap'/'default';
I then thought I could simply piggyback on the existing C/C++ support.

But it turns out that Fortran is completely different, e.g. there is often no 
BIND_EXPR
but just some (scoped / try-final-expr) code inside of it, i.e. the scope of 
the BIND_EXPR
has no relation to where GOMP_alloc has to be added. (GOMP_free is less 
critical, except
that a longer lifetime might cause memory constraints.)

Thus, RFC:
- Is the current scheme okay or should me move moved to the FE
  there is not that much happening at the ME?
- Should for the one 'if (lang_GNU_Fortran () ...' condition a lang hook
  be introduced?

Any other suggestions?

ALSO: I decided that the wording permits 'type(c_ptr)', 'type(c_funptr)' as 
they are
rather normal variables (of opaque type) in the Fortran sense. I decided that 
we do
not want to support EQUIVALENCE, Cray pointers, COMMON blocks ever (even though 
the
first to surely could be made to work, the latter - maybe.)
I also reject coarrays as it is really incompatible for allocate/allocators; for
the 'allocate' clause, that's different and permitted (just used for 
privatization).

Thoughts, suggestions?

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
Fortran: Support OpenMP's 'allocate' directive for stack vars

gcc/fortran/ChangeLog:

	* gfortran.h (ext_attr_t): Add omp_allocate flag.
	* match.cc (gfc_free_omp_namelist): Void deleting same
	u2.allocator multiple times now that a sequence can use
	the same one.
	* openmp.cc (gfc_match_omp_clauses, gfc_match_omp_allocate): Use
	same allocator expr multiple times.
	(is_predefined_allocator): Make static.
	(gfc_resolve_omp_allocate): Update/extend restriction checks;
	remove sorry message.
	(resolve_omp_clauses): Reject corarrays in allocate/allocators
	directive.
	* parse.cc (check_omp_allocate_stmt): Permit procedure pointers
	here (rejected later) for less mislreading diagnostic.
	* trans-array.cc (gfc_trans_auto_array_allocation): Propagate
	size for GOMP_alloc and location to which it should be added to.
	* trans-decl.cc (gfc_trans_deferred_vars): Handle 'omp allocate'
	for stack variables; sorry for static variables/common blocks.
	* trans-openmp.cc (gfc_trans_omp_clauses): Evaluate 'allocate'
	clause's allocator only once; fix adding expressions to the
	block.
	(gfc_trans_omp_single): Pass a block to gfc_trans_omp_clauses.

gcc/ChangeLog:

	* gimplify.cc (gimplify_bind_expr): Handle Fortran's
	'omp allocate' for stack variables.

libgomp/ChangeLog:

	* libgomp.texi:
	* testsuite/libgomp.fortran/allocate-5.f90: New test.
	* testsuite/libgomp.fortran/allocate-6.f90: New test.
	* testsuite/libgomp.fortran/allocate-7.f90: New test.
	* testsuite/libgomp.fortran/allocate-8.f90: New test.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/allocate-14.c: Fix directive name.
	* c-c++-common/gomp/allocate-15.c: Likewise.
	* c-c++-common/gomp/allocate-9.c: Fix comment typo.
	* gfortran.dg/gomp/allocate-4.f90: Remove sorry dg-error.
	* gfortran.dg/gomp/allocate-7.f90: Likewise.
	* gfortran.dg/gomp/allocate-10.f90: New test.
	* gfortran.dg/gomp/allocate-11.f90: New test.
	* gfortran.dg/gomp/allocate-12.f90: New test.
	* gfortran.dg/gomp/allocate-13.f90: New test.
	* gfortran.dg/gomp/allocate-14.f90: New test.
	* gfortran.dg/gomp/allocate-15.f90: New test.
	* gfortran.dg/gomp/allocate-8.f90: New test.
	* gfortran.dg/gomp/allocate-9.f90: New test.

 gcc/fortran/gfortran.h   |   1 +
 gcc/fortran/match.cc |   9 +-
 gcc/fortran/openmp.cc|  62 +++-
 gcc/fortran/parse.cc |   8 +-
 gcc/fortran/trans-array.cc   |  28 +-
 gcc/fortran/trans-decl.cc| 121 
 gcc/fortran/trans-openmp.cc  |  77 +++--
 gcc/gimplify.cc  | 173 +---
 gcc/testsuite/c-c++-common/gomp/allocate-14.c|   2 +-
 gcc/testsuite/c-c++-common/gomp/allocate-15.c|   2 +-
 gcc/testsuite/c-c++-common/gomp/allocate-9.c |   2 +-
 gcc/testsuite/gfortran.dg/gomp/allocate-10.f90   |  74 +
 gcc/testsuite/gfortran.dg/gomp/allocate-11.f90   |  33 +++
 gcc/testsuite/gfortran.dg/gomp/allocate-12.f90   |  24 ++
 gcc/testsuite/gfortran.dg/gomp/allocate-13.f90   |  25 ++
 gcc/testsuite/gfortran.dg/gomp/allocate-14.f90   |  95 +++
 gcc/testsuite/gfortran.dg/gomp/allocate-15.f90   |  38 +++
 gcc/testsuite/gfortran.dg/gomp/allocate-4.f90|   4 +-
 gcc/testsuite/gfortran.dg/gomp/allocate-7.f90|  10 -
 gcc/testsuite/gfortran.dg/gomp/allocate-8.f90|  29 ++
 

Re: [PATCH] RISC-V Regression: Fix FAIL of vect-multitypes-16.c for RVV

2023-10-10 Thread Jeff Law




On 10/10/23 08:49, Juzhe-Zhong wrote:

As Richard suggested: 
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632288.html

Add vect_ext_char_longlong to fix FAIL for RVV.

gcc/testsuite/ChangeLog:

* gcc.dg/vect/vect-multitypes-16.c: Adapt check for RVV.
* lib/target-supports.exp: Add vect_ext_char_longlong property.

OK
jeff


Re: [PATCH] RISC-V Regression: Make pattern match more accurate of vect-live-2.c

2023-10-10 Thread Jeff Law




On 10/10/23 08:57, Juzhe-Zhong wrote:

Like previous patch:
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632400.html
https://patchwork.sourceware.org/project/gcc/patch/dde89b9e-49a0-d70b-0906-fb3022cac...@gmail.com/

gcc/testsuite/ChangeLog:

* gcc.dg/vect/vect-live-2.c: Make pattern match more accurate.

OK
jeff


Re: [PATCH v2 4/4] RISC-V: Implement target attribute

2023-10-10 Thread Jeff Law




On 10/9/23 22:13, Kito Cheng wrote:

The target attribute which proposed in [1], target attribute allow user
to specify a local setting per-function basis.

The syntax of target attribute is `__attribute__((target("")))`.

and the syntax of `` describes below:
```
ATTR-STRING := ATTR-STRING ';' ATTR
  | ATTR

ATTR:= ARCH-ATTR
  | CPU-ATTR
  | TUNE-ATTR

ARCH-ATTR   := 'arch=' EXTENSIONS-OR-FULLARCH

EXTENSIONS-OR-FULLARCH := 
 | 

EXTENSIONS :=  ',' 
 | 

FULLARCHSTR:= 

EXTENSION  :=   

OP := '+'

VERSION:= [0-9]+ 'p' [0-9]+
 | [1-9][0-9]*
 |

EXTENSION-NAME := Naming rule is defined in RISC-V ISA manual

CPU-ATTR:= 'cpu=' 
TUNE-ATTR   := 'tune=' 
```

[1] https://github.com/riscv-non-isa/riscv-c-api-doc/pull/35

gcc/ChangeLog:

* config.gcc (riscv): Add riscv-target-attr.o.
* config/riscv/riscv-opts.h (TARGET_MIN_VLEN_OPTS): New.
* config/riscv/riscv-protos.h (riscv_declare_function_size) New.
(riscv_option_valid_attribute_p): New.
(riscv_override_options_internal): New.
(struct riscv_tune_info): New.
(riscv_parse_tune): New.
* config/riscv/riscv-target-attr.cc
(class riscv_target_attr_parser): New.
(struct riscv_attribute_info): New.
(riscv_attributes): New.
(riscv_target_attr_parser::parse_arch):
(riscv_target_attr_parser::handle_arch):
(riscv_target_attr_parser::handle_cpu):
(riscv_target_attr_parser::handle_tune):
(riscv_target_attr_parser::update_settings):
(riscv_process_one_target_attr):
(num_occurences_in_str):
(riscv_process_target_attr):
(riscv_option_valid_attribute_p):
* config/riscv/riscv.cc: Include target-globals.h and
riscv-subset.h.
(struct riscv_tune_info): Move to riscv-protos.h.
(get_tune_str):
(riscv_parse_tune):
(riscv_declare_function_size):
(riscv_option_override): Build target_option_default_node and
target_option_current_node.
(riscv_save_restore_target_globals):
(riscv_option_restore):
(riscv_previous_fndecl):
(riscv_set_current_function): Apply the target attribute.
(TARGET_OPTION_RESTORE): Define.
(TARGET_OPTION_VALID_ATTRIBUTE_P): Ditto.
* config/riscv/riscv.h (SWITCHABLE_TARGET): Define to 1.
(ASM_DECLARE_FUNCTION_SIZE) Define.
* config/riscv/riscv.opt (mtune=): Add Save attribute.
(mcpu=): Ditto.
(mcmodel=): Ditto.
* config/riscv/t-riscv: Add build rule for riscv-target-attr.o
* doc/extend.texi: Add doc for target attribute.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/target-attr-01.c: New.
* gcc.target/riscv/target-attr-02.c: Ditto.
* gcc.target/riscv/target-attr-03.c: Ditto.
* gcc.target/riscv/target-attr-04.c: Ditto.
* gcc.target/riscv/target-attr-05.c: Ditto.
* gcc.target/riscv/target-attr-06.c: Ditto.
* gcc.target/riscv/target-attr-07.c: Ditto.
* gcc.target/riscv/target-attr-bad-01.c: Ditto.
* gcc.target/riscv/target-attr-bad-02.c: Ditto.
* gcc.target/riscv/target-attr-bad-03.c: Ditto.
* gcc.target/riscv/target-attr-bad-04.c: Ditto.
* gcc.target/riscv/target-attr-bad-05.c: Ditto.
* gcc.target/riscv/target-attr-bad-06.c: Ditto.
* gcc.target/riscv/target-attr-bad-07.c: Ditto.
* gcc.target/riscv/target-attr-warning-01.c: Ditto.
* gcc.target/riscv/target-attr-warning-02.c: Ditto.
* gcc.target/riscv/target-attr-warning-03.c: Ditto.
I probably would have split the save/restore state out as a separate 
patch, but it's not a big deal.  A bit surprised we didn't already have 
that (and thus SWITCHABLE_TARGET) enabled already.  But no worries about 
that.




And just so I can do the right thing WRT RISE, what's the state of an 
implementation for LLVM?






diff --git a/gcc/config/riscv/riscv-target-attr.cc 
b/gcc/config/riscv/riscv-target-attr.cc
new file mode 100644
index 000..33cff2c222f
--- /dev/null
+++ b/gcc/config/riscv/riscv-target-attr.cc



+  /* Parsing the extension list like "+[,+]*".  */
+  size_t len = strlen (str);
+  char *str_to_check = (char *) alloca (len + 1);
If STR is under user control, then this could be a potential security 
issue if they were to provide a crazy long string (at least until we 
implement stack-clash protection -- next year).


In general we should avoid alloca unless we know the amount of memory 
consumed is relatively small and we have a high degree of confidence the 
code isn't going to be called inside a loop (and not inlined into a loop 
in the caller).  I might even go so far as to say no programmer should 
ever use alloca.



[PATCH] RISC-V Regression: Make pattern match more accurate of vect-live-2.c

2023-10-10 Thread Juzhe-Zhong
Like previous patch:
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632400.html
https://patchwork.sourceware.org/project/gcc/patch/dde89b9e-49a0-d70b-0906-fb3022cac...@gmail.com/

gcc/testsuite/ChangeLog:

* gcc.dg/vect/vect-live-2.c: Make pattern match more accurate.

---
 gcc/testsuite/gcc.dg/vect/vect-live-2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/vect/vect-live-2.c 
b/gcc/testsuite/gcc.dg/vect/vect-live-2.c
index dae36e9ed67..0a49c96d4e0 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-live-2.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-live-2.c
@@ -58,4 +58,4 @@ main (void)
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
-/* { dg-final { scan-tree-dump-times "vec_stmt_relevant_p: stmt live but not 
relevant" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vec_stmt_relevant_p: stmt live but not 
relevant(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" } } */
-- 
2.36.3



Re: [PATCH v3 0/2] RISC-V: Support CORE-V XCVMAC and XCVALU extensions

2023-10-10 Thread Kito Cheng
Just repeat what I said on the mailing list again :P it's LGTM, just
need to rebase to deal with riscv.opt related changes :)


On Sat, Sep 30, 2023 at 8:02 PM Mary Bennett  wrote:
>
> Thank you for reviewing this patch.
>
> v1->v2:
>   * Add XCValu RTL.
>   * Change assembly mnemonics from mixed case to lower case.
>
> v2->v3:
>   * Change commit message from past tense to present.
>   * Add documentation for new dg-effective-targets.
>
> This patch series presents the comprehensive implementation of the MAC and ALU
> extension for CORE-V.
>
> Tested with riscv-gnu-toolchain on binutils, ld, gas and gcc testsuites to
> ensure its correctness and compatibility with the existing codebase.
> However, your input, reviews, and suggestions are invaluable in making this
> extension even more robust.
>
> The CORE-V builtins are described in the specification [1] and work can be
> found in the OpenHW group's Github repository [2].
>
> [1] 
> github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md
>
> [2] github.com/openhwgroup/corev-gcc
>
> Contributors:
> Mary Bennett 
> Nandni Jamnadas 
> Pietra Ferreira 
> Charlie Keaney
> Jessica Mills
> Craig Blackmore 
> Simon Cook 
> Jeremy Bennett 
> Helene Chelin 
>
>   RISC-V: Add support for XCValu extension in CV32E40P
>   RISC-V: Add support for XCVmac extension in CV32E40P
>
>  gcc/common/config/riscv/riscv-common.cc   |   6 +
>  gcc/config/riscv/constraints.md   |   7 +
>  gcc/config/riscv/corev.def|  43 ++
>  gcc/config/riscv/corev.md | 693 ++
>  gcc/config/riscv/predicates.md|   5 +
>  gcc/config/riscv/riscv-builtins.cc|  13 +
>  gcc/config/riscv/riscv-ftypes.def |  11 +
>  gcc/config/riscv/riscv-opts.h |   7 +
>  gcc/config/riscv/riscv.cc |   7 +
>  gcc/config/riscv/riscv.md |   1 +
>  gcc/config/riscv/riscv.opt|   3 +
>  gcc/doc/extend.texi   | 174 +
>  gcc/doc/sourcebuild.texi  |  12 +
>  .../gcc.target/riscv/cv-alu-compile.c | 252 +++
>  .../riscv/cv-alu-fail-compile-addn.c  |  11 +
>  .../riscv/cv-alu-fail-compile-addrn.c |  11 +
>  .../riscv/cv-alu-fail-compile-addun.c |  11 +
>  .../riscv/cv-alu-fail-compile-addurn.c|  11 +
>  .../riscv/cv-alu-fail-compile-clip.c  |  11 +
>  .../riscv/cv-alu-fail-compile-clipu.c |  11 +
>  .../riscv/cv-alu-fail-compile-subn.c  |  11 +
>  .../riscv/cv-alu-fail-compile-subrn.c |  11 +
>  .../riscv/cv-alu-fail-compile-subun.c |  11 +
>  .../riscv/cv-alu-fail-compile-suburn.c|  11 +
>  .../gcc.target/riscv/cv-alu-fail-compile.c|  32 +
>  .../gcc.target/riscv/cv-mac-compile.c | 198 +
>  .../riscv/cv-mac-fail-compile-mac.c   |  25 +
>  .../riscv/cv-mac-fail-compile-machhsn.c   |  24 +
>  .../riscv/cv-mac-fail-compile-machhsrn.c  |  24 +
>  .../riscv/cv-mac-fail-compile-machhun.c   |  24 +
>  .../riscv/cv-mac-fail-compile-machhurn.c  |  24 +
>  .../riscv/cv-mac-fail-compile-macsn.c |  24 +
>  .../riscv/cv-mac-fail-compile-macsrn.c|  24 +
>  .../riscv/cv-mac-fail-compile-macun.c |  24 +
>  .../riscv/cv-mac-fail-compile-macurn.c|  24 +
>  .../riscv/cv-mac-fail-compile-msu.c   |  25 +
>  .../riscv/cv-mac-fail-compile-mulhhsn.c   |  24 +
>  .../riscv/cv-mac-fail-compile-mulhhsrn.c  |  24 +
>  .../riscv/cv-mac-fail-compile-mulhhun.c   |  24 +
>  .../riscv/cv-mac-fail-compile-mulhhurn.c  |  24 +
>  .../riscv/cv-mac-fail-compile-mulsn.c |  24 +
>  .../riscv/cv-mac-fail-compile-mulsrn.c|  24 +
>  .../riscv/cv-mac-fail-compile-mulun.c |  24 +
>  .../riscv/cv-mac-fail-compile-mulurn.c|  24 +
>  .../riscv/cv-mac-test-autogeneration.c|  18 +
>  gcc/testsuite/lib/target-supports.exp |  26 +
>  46 files changed, 2052 insertions(+)
>  create mode 100644 gcc/config/riscv/corev.def
>  create mode 100644 gcc/config/riscv/corev.md
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-compile.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-addn.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-addrn.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-addun.c
>  create mode 100644 
> gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-addurn.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-clip.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-clipu.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-subn.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-subrn.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/cv-alu-fail-compile-subun.c
>  create 

Re: [PATCH] Optimize (ne:SI (subreg:QI (ashift:SI x 7) 0) 0) as (and:SI x 1).

2023-10-10 Thread Jeff Law




On 10/10/23 08:41, Michael Matz wrote:


On Tue, 10 Oct 2023, Roger Sayle wrote:



This patch is the middle-end piece of an improvement to PRs 101955 and
106245, that adds a missing simplification to the RTL optimizers.
This transformation is to simplify (char)(x << 7) != 0 as x & 1.


Random observation:

So, why restrict to shifts of LEN-1 and mask 1?  It's always the case that
(type-of-LEN)(x << S)) != 0  ===  (x & ((1 << (LEN - S)) - 1)) != 0.

E.g. (char)(x << 5) != 0  ===  (x & 7) != 0.

Yea, it probably could be extended as a followup.



(Eventually the mask will be a constant that's too costly to compute if S
is target-dependendly too small, but all else being equal avoiding shifts
seems sensible)

Agreed, though it's nowhere near as important as it was 20+ years ago ;-)

jeff


[PATCH] RISC-V Regression: Fix FAIL of vect-multitypes-16.c for RVV

2023-10-10 Thread Juzhe-Zhong
As Richard suggested: 
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632288.html

Add vect_ext_char_longlong to fix FAIL for RVV.

gcc/testsuite/ChangeLog:

* gcc.dg/vect/vect-multitypes-16.c: Adapt check for RVV.
* lib/target-supports.exp: Add vect_ext_char_longlong property.

---
 gcc/testsuite/gcc.dg/vect/vect-multitypes-16.c | 4 ++--
 gcc/testsuite/lib/target-supports.exp  | 9 +
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/vect/vect-multitypes-16.c 
b/gcc/testsuite/gcc.dg/vect/vect-multitypes-16.c
index a61f1a9a221..fd17ad7437e 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-multitypes-16.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-multitypes-16.c
@@ -35,6 +35,6 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target 
vect_unpack } } } */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { 
! vect_unpack } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { 
{ vect_unpack } || { vect_variable_length && vect_ext_char_longlong } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { 
{ ! vect_unpack } && {! { vect_variable_length && vect_ext_char_longlong } } } 
} } } */
 
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index 95c489d7f76..b454b07359a 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -4215,6 +4215,15 @@ proc check_effective_target_vect_floatuint_cvt { } {
&& [check_effective_target_riscv_v]) }}]
 }
 
+# Return 1 if the target supports vector integer char -> long long extend optab
+#
+
+proc check_effective_target_vect_ext_char_longlong { } {
+return [check_cached_effective_target_indexed vect_ext_char_longlong {
+  expr { ([istarget riscv*-*-*]
+ && [check_effective_target_riscv_v]) }}]
+}
+
 # Return 1 if peeling for alignment might be profitable on the target
 #
 
-- 
2.36.3



Re: [RFC gcc13 backport 0/3] Add Ztso atomic mappings

2023-10-10 Thread Patrick O'Neill



On 10/4/23 08:53, Jeff Law wrote:



On 10/3/23 16:26, Patrick O'Neill wrote:

I vaugely recall some discussion about backporting the Ztso mappings
along with the RVWMO mappings. Now that the RVWMO mappings have been
backported for 13.3, is there interest in also backporting the Ztso
mappings?

Tested using for regressions using rv32gc/rv64gc glibc.

Jeff Law (1):
   [RISCV][committed] Remove spurious newline in ztso sequence

Patrick O'Neill (2):
   RISC-V: Add Ztso atomic mappings
   RISC-V: Specify -mabi for ztso testcases
I recall discussing Ztso mappings, but not the final conclusion. I 
think the final decision comes down to the motivation behind the changes.


If they're primarily optimized sequences utilizing the stronger 
ordering guarantees from Ztso, then it's probably not a good candidate 
for gcc-13.  If the primary motivation is to make it easier to port 
code from targets with stronger memory models (ie x86), then the Ztso 
work is a reasonable candidate for backporting.


Jeff


Discussed during the GCC patchworks meeting.

The Ztso mappings are a subset of RVWMO fences/ordering constraints
(it's an optimization change) [1].
This backport also makes tip-of-tree sync.md files match gcc 13.3+ which
simplifies future atomic-related backports.

If in the future someone needs Ztso/there is a need to backport we can
re-evaluate this backport then.

Thanks
Patrick

[1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/391



Re: [PATCH] Optimize (ne:SI (subreg:QI (ashift:SI x 7) 0) 0) as (and:SI x 1).

2023-10-10 Thread Michael Matz


On Tue, 10 Oct 2023, Roger Sayle wrote:

> 
> This patch is the middle-end piece of an improvement to PRs 101955 and
> 106245, that adds a missing simplification to the RTL optimizers.
> This transformation is to simplify (char)(x << 7) != 0 as x & 1.

Random observation:

So, why restrict to shifts of LEN-1 and mask 1?  It's always the case that
(type-of-LEN)(x << S)) != 0  ===  (x & ((1 << (LEN - S)) - 1)) != 0.

E.g. (char)(x << 5) != 0  ===  (x & 7) != 0.

(Eventually the mask will be a constant that's too costly to compute if S 
is target-dependendly too small, but all else being equal avoiding shifts 
seems sensible)


Ciao,
Michael.


Re: [PATCH] Optimize (ne:SI (subreg:QI (ashift:SI x 7) 0) 0) as (and:SI x 1).

2023-10-10 Thread Jeff Law




On 10/10/23 06:28, Roger Sayle wrote:


This patch is the middle-end piece of an improvement to PRs 101955 and
106245, that adds a missing simplification to the RTL optimizers.
This transformation is to simplify (char)(x << 7) != 0 as x & 1.
Technically, the cast can be any truncation, where shift is by one
less than the narrower type's precision, setting the most significant
(only) bit from the least significant bit.

This transformation applies to any target, but it's easy to see
(and add a new test case) on x86, where the following function:

int f(int a) { return (a << 31) >> 31; }

currently gets compiled with -O2 to:

foo:movl%edi, %eax
 sall$7, %eax
 sarb$7, %al
 movsbl  %al, %eax
 ret

but with this patch, we now generate the slightly simpler.

foo:movl%edi, %eax
 sall$31, %eax
 sarl$31, %eax
 ret


This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check with no new failures.  Ok for mainline?


2023-10-10  Roger Sayle  

gcc/ChangeLog
 PR middle-end/101955
 PR tree-optimization/106245
 * simplify-rtx.c (simplify_relational_operation_1): Simplify
 the RTL (ne:SI (subreg:QI (ashift:SI x 7) 0) 0) to (and:SI x 1).

gcc/testsuite/ChangeLog
 * gcc.target/i386/pr106245-1.c: New test case.

OK.  Thanks!  I must admit, I'm a bit surprised this wasn't already handled.

jeff


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

2023-10-10 Thread Jeff Law




On 10/10/23 05:59, Manolis Tsamis wrote:


It's a code quality issue as long as we don't transform the code into
movl $0, -18874240, at which point it would become a correctness issue.


Ok, thanks for pointing that out as I thought that movl $0, -18874240
and movl $0, -18874240(eax) with eax == 0 were the same.
It's a quirk of x32 related to sign extension of the address.  Certainly 
not obvious!  But it's better than the PA where:


(mem (plus (reg A) (reg B)))

Is semantically different than

(mem (plus (reg B) (reg A)))


Due to the implicit segment register selection that happens on the high 
bits of the base register rather than the high bits of the effective 
address.









With regards to the "recognize that the base register is 0", that
would be nice but how would we recognise that? f-m-o can only
calculate the folded offset but that is not enough to prove that the
base register is zero or not.

It's a chain of insns that produce an address and use it in the memory
reference.  We essentially changed the first insn in the chain from movl
-18874240, %eax into movl 0, %eax.  So we'd have to someone note that
the base register in the memory reference has the value zero in the
chain of instructions.  That may or may not be reasonable to do.


Ok, do you believe it would be worthwhile to add a REG_EQ note or
something similar? I assume some REG_EQ notes will be added from the
following cprop-hardreg pass too?
I think it really depends on the degree of difficulty and whether or not 
we think there are other cases like this one lurking.


Given this scenario can only happen with an absolute address, I would 
probably explore if there's a way to trivially detect this case, but I 
wouldn't spend a lot of time on it.


And I wasn't necessarily thinking of a note in the RTL, just a bit of 
state within f-m-o when updating an arithmetic chain so that we could 
determine that the final instruction was a memory reference to an 
absolute address.








You could use the costing model to cost the entire sequence
before/after.  There's an interface to walk a sequence and return a
cost.  In the case of f-m-o the insns are part of the larger chain, so
we'd need a different API.

The other option would be to declare this is known, but not important
issue.  I would think that it's going to be rare to have absolute
addresses and x32 isn't really used much.  The combination of the two
should be exceedingly rare.  Hence my willingness to use
-fno-fold-mem-offsets in the test.


Yes, I now better understand why you suggested adding
-fno-fold-mem-offsets to the testcase. Or we could also make the test
not fail in this case where the memory access has the base register,
as there's no correctness issue.

:)




Then, going back to the code quality regression, wouldn't things be
much better if we would emit xor eax, eax instead of mov eax, 0? In
that case xor eax, eax should be 2 bytes instead of 5 for mov eax, 0
and hence the code size difference should be trivial. Then we can keep
f-m-o as is, including this testcase.
The selection of xor vs mov imm is handled elsewhere.  On some uarchs 
the former is preferred, on others the latter.


If you think about xor %eax,%eax as an example.  Unless you special case 
that scenario in your cpu front-end, the xor will have a data dependency 
on any prior set of %eax which inhibits ILP.





Is there a way to emit a taret-specific optimized register zero insn?
If so I'll use that and adjust the testcase as needed, and I think
we're done with this one.

I can live with just adjusting the testcase.  Let's go with that.

jeff


Re: Re: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'

2023-10-10 Thread 钟居哲
Thanks Jeff.

I have found multiple dump FAIL issues are related to middle-end.

For example: 111721 – RISC-V: Failed to SLP for gather_load in RVV (gnu.org)

I have file bugzilla and I will fix them eventually but I am planning to fix 
the FAILs first which are the testcase issues.

Then come back to fix the implementation issues that I have filed bugzilla.

So, don't worry. Will keep you posted.



juzhe.zh...@rivai.ai
 
From: Jeff Law
Date: 2023-10-10 22:02
To: juzhe.zhong
CC: macro; gcc-patches; Robin Dapp; Kito.cheng; Richard Biener
Subject: Re: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'
 
 
On 10/10/23 07:53, juzhe.zhong wrote:
> I am working on it. Currently,  we have about 50+ additional FAILs after 
> enabling vectorization.
> 
> some of them need fixed on middle-end. E.g richard fixed a missed cse 
> optimization.
> 
> Some need fix on test case.
> 
> I am analyzing each fail one by one.
> 
> I prefer postpone this patch since it will cause some additional fails 
> and I will handle that eventually after full coverage analysis.
OK.  We can defer.  I just want to make sure we're all know where things 
stand.
 
jeff
 


RE: [PATCH] RISC-V Regression: Fix FAIL of predcom-2.c

2023-10-10 Thread Li, Pan2
Committed, thanks Jeff.

Pan

-Original Message-
From: Jeff Law  
Sent: Tuesday, October 10, 2023 9:49 PM
To: Juzhe-Zhong ; gcc-patches@gcc.gnu.org
Cc: rguent...@suse.de
Subject: Re: [PATCH] RISC-V Regression: Fix FAIL of predcom-2.c



On 10/9/23 20:58, Juzhe-Zhong wrote:
> Like GCN, add -fno-tree-vectorize.
> 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.dg/tree-ssa/predcom-2.c: Add riscv.
OK.
jeff


[PATCH 3/3] [GCC] arm: vst1q_types_x4 ACLE intrinsics

2023-10-10 Thread Ezra.Sitorus
From: Ezra Sitorus 

This patch is part of a series of patches implementing the _xN variants of the 
vst1q intrinsic for AArch32.
This patch adds the _x4 variants of the vst1q intrinsic.

ACLE documents are at https://developer.arm.com/documentation/ihi0053/latest/
ISA documents are at https://developer.arm.com/documentation/ddi0487/latest/

gcc/ChangeLog:
* config/arm/arm_neon.h
(vst1q_u8_x4, vst1q_u16_x4, vst1q_u32_x4, vst1q_u64_x4): New.
(vst1q_s8_x4, vst1q_s16_x4, vst1q_s32_x4, vst1q_s64_x4): New.
(vst1q_f16_x4, vst1q_f32_x4): New.
(vst1q_p8_x4, vst1q_p16_x4, vst1q_p64_x4): New.
(vst1q_bf16_x4): New.
* config/arm/arm_neon_builtins.def (vst1q_x4): New entries.
* config/arm/neon.md (neon_vst1q_x4): New.

gcc/testsuite/ChangeLog:
* gcc.target/arm/simd/vst1q_base_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_bf16_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_fp16_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_p64_xN_1.c: Add new tests.
---
 gcc/config/arm/arm_neon.h | 114 ++
 gcc/config/arm/arm_neon_builtins.def  |   1 +
 gcc/config/arm/neon.md|  26 
 .../gcc.target/arm/simd/vst1q_base_xN_1.c |  59 +
 .../gcc.target/arm/simd/vst1q_bf16_xN_1.c |   8 +-
 .../gcc.target/arm/simd/vst1q_fp16_xN_1.c |   6 +
 .../gcc.target/arm/simd/vst1q_p64_xN_1.c  |   6 +
 7 files changed, 219 insertions(+), 1 deletion(-)

diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h
index 46ee888410f..df3e23b6e95 100644
--- a/gcc/config/arm/arm_neon.h
+++ b/gcc/config/arm/arm_neon.h
@@ -11391,6 +11391,38 @@ vst1q_s64_x3 (int64_t * __a, int64x2x3_t __b)
   __builtin_neon_vst1q_x3v2di ((__builtin_neon_di *) __a, __bu.__o);
 }
 
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s8_x4 (int8_t * __a, int8x16x4_t __b)
+{
+  union { int8x16x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x4v16qi ((__builtin_neon_qi *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s16_x4 (int16_t * __a, int16x8x4_t __b)
+{
+  union { int16x8x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x4v8hi ((__builtin_neon_hi *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s32_x4 (int32_t * __a, int32x4x4_t __b)
+{
+  union { int32x4x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x4v4si ((__builtin_neon_si *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s64_x4 (int64_t * __a, int64x2x4_t __b)
+{
+  union { int64x2x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x4v2di ((__builtin_neon_di *) __a, __bu.__o);
+}
+
 __extension__ extern __inline void
 __attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
 vst1_s8_x3 (int8_t * __a, int8x8x3_t __b)
@@ -11736,6 +11768,14 @@ vst1q_p64_x3 (poly64_t * __a, poly64x2x3_t __b)
   __builtin_neon_vst1q_x3v2di ((__builtin_neon_di *) __a, __bu.__o);
 }
 
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_p64_x4 (poly64_t * __a, poly64x2x4_t __b)
+{
+  union { poly64x2x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x4v2di ((__builtin_neon_di *) __a, __bu.__o);
+}
+
 #pragma GCC pop_options
 __extension__ extern __inline void
 __attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
@@ -11817,6 +11857,24 @@ vst1q_f32_x3 (float32_t * __a, float32x4x3_t __b)
   __builtin_neon_vst1q_x3v4sf (__a, __bu.__o);
 }
 
+#if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE)
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_f16_x4 (float16_t * __a, float16x8x4_t __b)
+{
+  union { float16x8x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x4v8hf (__a, __bu.__o);
+}
+#endif
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_f32_x4 (float32_t * __a, float32x4x4_t __b)
+{
+  union { float32x4x4_t __i; __builtin_neon_xi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x4v4sf (__a, __bu.__o);
+}
+
 __extension__ extern __inline void
 __attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
 vst1q_u8 (uint8_t * __a, uint8x16_t __b)
@@ -11909,6 +11967,38 @@ vst1q_u64_x3 (uint64_t * __a, uint64x2x3_t __b)
   __builtin_neon_vst1q_x3v2di ((__builtin_neon_di *) __a, __bu.__o);
 }
 
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_u8_x4 (uint8_t * __a, uint8x16x4_t __b)
+{
+  union { uint8x16x4_t __i; 

[PATCH 1/3] [GCC] arm: vst1q_types_x2 ACLE intrinsics

2023-10-10 Thread Ezra.Sitorus
From: Ezra Sitorus 

This patch is part of a series of patches implementing the _xN variants of the 
vst1q intrinsic for AArch32.
This patch adds the _x2 variants of the vst1q intrinsic. Tests use xN so that 
the latter variants (_x3, _x4) could be added.

ACLE documents are at https://developer.arm.com/documentation/ihi0053/latest/
ISA documents are at https://developer.arm.com/documentation/ddi0487/latest/

gcc/ChangeLog:
* config/arm/arm_neon.h
(vst1q_u8_x2, vst1q_u16_x2, vst1q_u32_x2, vst1q_u64_x32): New.
(vst1q_s8_x2, vst1q_s16_x2, vst1q_s32_x2, vst1q_s64_x2): New.
(vst1q_f16_x2, vst1q_f32_x2): New.
(vst1q_p8_x2, vst1q_p16_x2, vst1q_p64_x2): New.
(vst1q_bf16_x2): New.
* config/arm/arm_neon_builtins.def (vst1<_x2): New entries.
* config/arm/neon.md (neon_vst1_x2): Updated from 
neon_vst1_x2.
* config/arm/iterators.md (VMEMX2): New mode iterator.
(VMEMX2_q): New mode attribute.

gcc/testsuite/ChangeLog:
* gcc.target/arm/simd/vst1q_base_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_bf16_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_fp16_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_p64_xN_1.c: Add new tests.
---
 gcc/config/arm/arm_neon.h | 114 ++
 gcc/config/arm/arm_neon_builtins.def  |   1 +
 gcc/config/arm/iterators.md   |   6 +
 gcc/config/arm/neon.md|   6 +-
 .../gcc.target/arm/simd/vst1q_base_xN_1.c |  70 +++
 .../gcc.target/arm/simd/vst1q_bf16_xN_1.c |  13 ++
 .../gcc.target/arm/simd/vst1q_fp16_xN_1.c |  13 ++
 .../gcc.target/arm/simd/vst1q_p64_xN_1.c  |  13 ++
 8 files changed, 233 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/simd/vst1q_base_xN_1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/simd/vst1q_bf16_xN_1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/simd/vst1q_fp16_xN_1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/simd/vst1q_p64_xN_1.c

diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h
index 41e645d8352..b8f3fca3060 100644
--- a/gcc/config/arm/arm_neon.h
+++ b/gcc/config/arm/arm_neon.h
@@ -11327,6 +11327,38 @@ vst1_s64_x2 (int64_t * __a, int64x1x2_t __b)
   __builtin_neon_vst1_x2di ((__builtin_neon_di *) __a, __bu.__o);
 }
 
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s8_x2 (int8_t * __a, int8x16x2_t __b)
+{
+  union { int8x16x2_t __i; __builtin_neon_oi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x2v16qi ((__builtin_neon_qi *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s16_x2 (int16_t * __a, int16x8x2_t __b)
+{
+  union { int16x8x2_t __i; __builtin_neon_oi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x2v8hi ((__builtin_neon_hi *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s32_x2 (int32_t * __a, int32x4x2_t __b)
+{
+  union { int32x4x2_t __i; __builtin_neon_oi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x2v4si ((__builtin_neon_si *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s64_x2 (int64_t * __a, int64x2x2_t __b)
+{
+  union { int64x2x2_t __i; __builtin_neon_oi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x2v2di ((__builtin_neon_di *) __a, __bu.__o);
+}
+
 __extension__ extern __inline void
 __attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
 vst1_s8_x3 (int8_t * __a, int8x8x3_t __b)
@@ -11656,6 +11688,14 @@ vst1q_p64 (poly64_t * __a, poly64x2_t __b)
   __builtin_neon_vst1v2di ((__builtin_neon_di *) __a, (int64x2_t) __b);
 }
 
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_p64_x2 (poly64_t * __a, poly64x2x2_t __b)
+{
+  union { poly64x2x2_t __i; __builtin_neon_oi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x2v2di ((__builtin_neon_di *) __a, __bu.__o);
+}
+
 #pragma GCC pop_options
 __extension__ extern __inline void
 __attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
@@ -11701,6 +11741,24 @@ vst1q_f32 (float32_t * __a, float32x4_t __b)
   __builtin_neon_vst1v4sf ((__builtin_neon_sf *) __a, __b);
 }
 
+#if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE)
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_f16_x2 (float16_t * __a, float16x8x2_t __b)
+{
+  union { float16x8x2_t __i; __builtin_neon_oi __o; } __bu = { __b };
+  __builtin_neon_vst1q_x2v8hf (__a, __bu.__o);
+}
+#endif
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_f32_x2 (float32_t * __a, float32x4x2_t __b)
+{
+  union { 

RE: [PATCH] RISC-V Regression: Make match patterns more accurate

2023-10-10 Thread Li, Pan2
Committed, thanks Jeff.

Pan

-Original Message-
From: Jeff Law  
Sent: Tuesday, October 10, 2023 9:47 PM
To: Juzhe-Zhong ; gcc-patches@gcc.gnu.org
Cc: rguent...@suse.de; rdapp@gmail.com
Subject: Re: [PATCH] RISC-V Regression: Make match patterns more accurate



On 10/9/23 20:47, Juzhe-Zhong wrote:
> This patch fixes following 2 FAILs in RVV regression since the check is not 
> accurate.
> 
> It's inspired by Robin's previous patch:
> https://patchwork.sourceware.org/project/gcc/patch/dde89b9e-49a0-d70b-0906-fb3022cac...@gmail.com/
> 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.dg/vect/no-scevccp-outer-7.c: Adjust regex pattern.
>   * gcc.dg/vect/no-scevccp-vect-iv-3.c: Ditto.
OK.   We might see other ports flipping to a pass if they were 
exhibiting the same behavior with failing to vectorize with the first 
selected type, but passing on the second type.

Jeff


[PATCH 2/3] [GCC] arm: vst1q_types_x3 ACLE intrinsics

2023-10-10 Thread Ezra.Sitorus
From: Ezra Sitorus 

This patch is part of a series of patches implementing the _xN variants of the 
vst1q intrinsic for AArch32.
This patch adds the _x3 variants of the vst1q intrinsic.

ACLE documents are at https://developer.arm.com/documentation/ihi0053/latest/
ISA documents are at https://developer.arm.com/documentation/ddi0487/latest/

gcc/ChangeLog:
* config/arm/arm_neon.h
(vst1q_u8_x3, vst1q_u16_x3, vst1q_u32_x3, vst1q_u64_x3): New.
(vst1q_s8_x3, vst1q_s16_x3, vst1q_s32_x3, vst1q_s64_x3): New.
(vst1q_f16_x3, vst1q_f32_x3): New.
(vst1q_p8_x3, vst1q_p16_x3, vst1q_p64_x3): New.
(vst1q_bf16_x3): New.
* config/arm/arm_neon_builtins.def (vst1q_x3): New entries.
* config/arm/neon.md (neon_vst1q_x3): New.

gcc/testsuite/ChangeLog:
* gcc.target/arm/simd/vst1q_base_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_bf16_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_fp16_xN_1.c: Add new tests.
* gcc.target/arm/simd/vst1q_p64_xN_1.c: Add new tests.
---
 gcc/config/arm/arm_neon.h | 114 ++
 gcc/config/arm/arm_neon_builtins.def  |   1 +
 gcc/config/arm/neon.md|  24 
 .../gcc.target/arm/simd/vst1q_base_xN_1.c |  60 +
 .../gcc.target/arm/simd/vst1q_bf16_xN_1.c |   6 +
 .../gcc.target/arm/simd/vst1q_fp16_xN_1.c |   6 +
 .../gcc.target/arm/simd/vst1q_p64_xN_1.c  |   6 +
 7 files changed, 217 insertions(+)

diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h
index b8f3fca3060..46ee888410f 100644
--- a/gcc/config/arm/arm_neon.h
+++ b/gcc/config/arm/arm_neon.h
@@ -11359,6 +11359,38 @@ vst1q_s64_x2 (int64_t * __a, int64x2x2_t __b)
   __builtin_neon_vst1q_x2v2di ((__builtin_neon_di *) __a, __bu.__o);
 }
 
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s8_x3 (int8_t * __a, int8x16x3_t __b)
+{
+  union { int8x16x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+  __builtin_neon_vst1q_x3v16qi ((__builtin_neon_qi *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s16_x3 (int16_t * __a, int16x8x3_t __b)
+{
+  union { int16x8x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+  __builtin_neon_vst1q_x3v8hi ((__builtin_neon_hi *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s32_x3 (int32_t * __a, int32x4x3_t __b)
+{
+  union { int32x4x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+  __builtin_neon_vst1q_x3v4si ((__builtin_neon_si *) __a, __bu.__o);
+}
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_s64_x3 (int64_t * __a, int64x2x3_t __b)
+{
+  union { int64x2x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+  __builtin_neon_vst1q_x3v2di ((__builtin_neon_di *) __a, __bu.__o);
+}
+
 __extension__ extern __inline void
 __attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
 vst1_s8_x3 (int8_t * __a, int8x8x3_t __b)
@@ -11696,6 +11728,14 @@ vst1q_p64_x2 (poly64_t * __a, poly64x2x2_t __b)
   __builtin_neon_vst1q_x2v2di ((__builtin_neon_di *) __a, __bu.__o);
 }
 
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_p64_x3 (poly64_t * __a, poly64x2x3_t __b)
+{
+  union { poly64x2x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+  __builtin_neon_vst1q_x3v2di ((__builtin_neon_di *) __a, __bu.__o);
+}
+
 #pragma GCC pop_options
 __extension__ extern __inline void
 __attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
@@ -11759,6 +11799,24 @@ vst1q_f32_x2 (float32_t * __a, float32x4x2_t __b)
   __builtin_neon_vst1q_x2v4sf (__a, __bu.__o);
 }
 
+#if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE)
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_f16_x3 (float16_t * __a, float16x8x3_t __b)
+{
+  union { float16x8x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+  __builtin_neon_vst1q_x3v8hf (__a, __bu.__o);
+}
+#endif
+
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_f32_x3 (float32_t * __a, float32x4x3_t __b)
+{
+  union { float32x4x3_t __i; __builtin_neon_ci __o; } __bu = { __b };
+  __builtin_neon_vst1q_x3v4sf (__a, __bu.__o);
+}
+
 __extension__ extern __inline void
 __attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
 vst1q_u8 (uint8_t * __a, uint8x16_t __b)
@@ -11819,6 +11877,38 @@ vst1q_u64_x2 (uint64_t * __a, uint64x2x2_t __b)
   __builtin_neon_vst1q_x2v2di ((__builtin_neon_di *) __a, __bu.__o);
 }
 
+__extension__ extern __inline void
+__attribute__  ((__always_inline__, __gnu_inline__, __artificial__))
+vst1q_u8_x3 (uint8_t * __a, uint8x16x3_t __b)
+{
+  

[PATCH 0/3] [GCC] arm: vst1q_types_xN ACLE intrinsics

2023-10-10 Thread Ezra.Sitorus
Add xN variants of vst1q_types intrinsic for AArch32.




Re: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'

2023-10-10 Thread Jeff Law




On 10/10/23 07:53, juzhe.zhong wrote:
I am working on it. Currently,  we have about 50+ additional FAILs after 
enabling vectorization.


some of them need fixed on middle-end. E.g richard fixed a missed cse 
optimization.


Some need fix on test case.

I am analyzing each fail one by one.

I prefer postpone this patch since it will cause some additional fails 
and I will handle that eventually after full coverage analysis.
OK.  We can defer.  I just want to make sure we're all know where things 
stand.


jeff


Re: [PATCH v2 3/4] RISC-V: Extend riscv_subset_list, preparatory for target attribute support

2023-10-10 Thread Jeff Law




On 10/9/23 22:13, Kito Cheng wrote:

riscv_subset_list only accept a full arch string before, but we need to
parse single extension when supporting target attribute, also we may set
a riscv_subset_list directly rather than re-parsing the ISA string
again.

gcc/ChangeLog:

* config/riscv/riscv-subset.h (riscv_subset_list::parse_single_std_ext):
New.
(riscv_subset_list::parse_single_multiletter_ext): Ditto.
(riscv_subset_list::clone): Ditto.
(riscv_subset_list::parse_single_ext): Ditto.
(riscv_subset_list::set_loc): Ditto.
(riscv_set_arch_by_subset_list): Ditto.
* common/config/riscv/riscv-common.cc
(riscv_subset_list::parse_single_std_ext): New.
(riscv_subset_list::parse_single_multiletter_ext): Ditto.
(riscv_subset_list::clone): Ditto.
(riscv_subset_list::parse_single_ext): Ditto.
(riscv_subset_list::set_loc): Ditto.
(riscv_set_arch_by_subset_list): Ditto.
---
  gcc/common/config/riscv/riscv-common.cc | 203 
  gcc/config/riscv/riscv-subset.h |  11 ++
  2 files changed, 214 insertions(+)

diff --git a/gcc/common/config/riscv/riscv-common.cc 
b/gcc/common/config/riscv/riscv-common.cc
index 9a0a68fe5db..25630d5923e 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -1138,6 +1173,102 @@ riscv_subset_list::handle_combine_ext ()
  }
  }
  
+/* Parsing function for multi-letter extensions.

+
+   Return Value:
+ Points to the end of extensions.
+
+   Arguments:
+ `p`: Current parsing position.
+ `ext_type`: What kind of extensions, 's', 'z' or 'x'.
+ `ext_type_str`: Full name for kind of extension.  */
+
+
+const char *
+riscv_subset_list::parse_single_multiletter_ext (const char *p,
+const char *ext_type,
+const char *ext_type_str)

[ ... ]





+
+  if (end_of_version == NULL)
+return NULL;

I think when we hit this path we leak SUBSET.




  
  std::string

@@ -1498,6 +1673,34 @@ static const riscv_ext_flag_table_t 
riscv_ext_flag_table[] =
{NULL, NULL, 0}
  };
  
+void

+riscv_set_arch_by_subset_list (riscv_subset_list *subset_list,
+  struct gcc_options *opts)

Needs a function comment.

OK with those two minor issues fixed.

jeff


C++ patch ping^2

2023-10-10 Thread Jakub Jelinek
Hi!

I'd like to ping a couple of C++ patches.

- c++, v2: Implement C++26 P2169R4 - Placeholder variables with no name 
[PR110349]
  https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630802.html

- c++: Implement C++26 P2361R6 - Unevaluated strings [PR110342]
  https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628375.html

- c++, v2: Implement C++26 P2741R3 - user-generated static_assert messages 
[PR110348]
  https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630803.html

- c++: Implement C++ DR 2406 - [[fallthrough]] attribute and iteration 
statements [PR107571]
  https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628487.html
  (from this one Richi approved the middle-end changes)

- c++: Implement C++26 P1854R4 - Making non-encodable string literals 
ill-formed [PR110341]
  https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628490.html

- libcpp, v2: Small incremental patch for P1854R4 [PR110341]
  https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628586.html

Jakub



Re: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'

2023-10-10 Thread juzhe.zhong
I am working on it. Currently,  we have about 50+ additional FAILs after enabling vectorization.some of them need fixed on middle-end. E.g richard fixed a missed cse optimization.Some need fix on test case.I am analyzing each fail one by one.I prefer postpone this patch since it will cause some additional fails and I will handle that eventually after full coverage analysis. Replied Message FromJeff LawDate10/10/2023 21:33 Tojuzhe.zh...@rivai.ai,macro Ccgcc-patches,Robin Dapp,Kito.cheng,Richard BienerSubjectRe: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'

On 10/9/23 19:13, juzhe.zh...@rivai.ai wrote:
> Oh. I realize this patch increase FAIL that I recently fixed:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632247.html  
> 
>  
> This fail because RVV doesn't have vec_pack_trunc_optab (Loop vectorizer  
> will failed at first time but succeed at 2nd time),
> then RVV will dump 4 times FOLD_EXTRACT_LAST instead of 2  (ARM SVE 2  
> times because they have vec_pack_trunc_optab).
>  
> I think the root cause of RVV failing at multiple tests of "vect" is  
> that we don't enable vec_pack/vec_unpack/... stuff,
> we still succeed at vectorizations and we want to enable tests of them
> (Mostly just using different approach to vectorize it (cause dump FAIL)  
> because of some changing I have done previously in the middle-end).
>  
> So enabling "vec_pack" for RVV will fix some FAILs but increase some  
> other FAILs.
>  
> CC to Richi to see more reasonable suggestions.
So what is the summary on Maciej's patch to enable vec_pack_trunc?  ie,  
is it something we should move forward with as-is, is it superceded by  
your work in this space or does it need further investigation because of  
differences in testing methodologies or something else?

jeff



Re: [PATCH v2 2/4] RISC-V: Refactor riscv_option_override and riscv_convert_vector_bits. [NFC]

2023-10-10 Thread Jeff Law




On 10/9/23 22:13, Kito Cheng wrote:

Allow those funciton apply from a local gcc_options rather than the
global options.

Preparatory for target attribute, sperate this change for eaiser reivew
since it's a NFC.

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_convert_vector_bits): Get setting
from argument rather than get setting from global setting.
(riscv_override_options_internal): New, splited from
riscv_override_options, also take a gcc_options argument.
(riscv_option_override): Splited most part to
riscv_override_options_internal.

OK.
jeff


Re: [PATCH v2 1/4] options: Define TARGET__P and TARGET__OPTS_P macro for Mask and InverseMask

2023-10-10 Thread Jeff Law




On 10/9/23 22:13, Kito Cheng wrote:

We TARGET__P marcro to test a Mask and InverseMask with user
specified target_variable, however we may want to test with specific
gcc_options variable rather than target_variable.

Like RISC-V has defined lots of Mask with TargetVariable, which is not
easy to use, because that means we need to known which Mask are associate with
which TargetVariable, so take a gcc_options variable is a better interface
for such use case.

gcc/ChangeLog:

* doc/options.texi (Mask): Document TARGET__P and
TARGET__OPTS_P.
(InverseMask): Ditto.
* opth-gen.awk (Mask): Generate TARGET__P and
TARGET__OPTS_P macro.
(InverseMask): Ditto.

OK assuming it passes a build cycle on x86 or some other common target.

jeff


Re: [PATCH] RISC-V Regression: Fix FAIL of predcom-2.c

2023-10-10 Thread Jeff Law




On 10/9/23 20:58, Juzhe-Zhong wrote:

Like GCN, add -fno-tree-vectorize.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/predcom-2.c: Add riscv.

OK.
jeff


[PATCH v5] c++: Check for indirect change of active union member in constexpr [PR101631,PR102286]

2023-10-10 Thread Nathaniel Shead
On Mon, Oct 09, 2023 at 04:46:46PM -0400, Jason Merrill wrote:
> On 10/8/23 21:03, Nathaniel Shead wrote:
> > Ping for 
> > https://gcc.gnu.org/pipermail/gcc-patches/2023-September/631203.html
> > 
> > + && (TREE_CODE (t) == MODIFY_EXPR
> > + /* Also check if initializations have implicit change of active
> > +member earlier up the access chain.  */
> > + || !refs->is_empty())
> 
> I'm not sure what the cumulative point of these two tests is.  TREE_CODE (t)
> will be either MODIFY_EXPR or INIT_EXPR, and either should be OK.
> 
> As I understand it, the problematic case is something like
> constexpr-union2.C, where we're also looking at a MODIFY_EXPR.  So what is
> this check doing?

The reasoning was to correctly handle cases like the the following (in
constexpr-union6.C):

  constexpr int test1() {
U u {};
std::construct_at(, S{ 1, 2 });
return u.s.b;
  }
  static_assert(test1() == 2);

The initialisation of  here is not a member access expression within
the call to std::construct_at, since it's just a pointer, but this code
is still legal; in general, an INIT_EXPR to initialise a union member
should always be OK (I believe?), hence constraining to just
MODIFY_EXPR.

However, just that would then (incorrectly) allow all the following
cases in that test to compile, such as

  constexpr int test2() {
U u {};
int* p = 
std::construct_at(p, 5);
return u.s.b;
  }
  constexpr int x2 = test2();

since the INIT_EXPR is really only initialising 'b', but the implicit
"modification" of active member to 'u.s' is illegal.

Maybe a better way of expressing this condition would be something like
this?

  /* An INIT_EXPR of the last member in an access chain is always OK,
 but still check implicit change of members earlier on; see 
 cpp2a/constexpr-union6.C.  */
  && !(TREE_CODE (t) == INIT_EXPR && refs->is_empty ())

Otherwise I'll see if I can rework some of the other conditions instead.

> Incidentally, I think constexpr-union6.C could use a test where we pass 
> to a function other than construct_at, and then try (and fail) to assign to
> the b member from that function.
> 
> Jason
> 

Sounds good; I've added the following test:

  constexpr void foo(S* s) {
s->b = 10;  // { dg-error "accessing .U::s. member instead of initialized 
.U::k." }
  }
  constexpr int test3() {
U u {};
foo();  // { dg-message "in .constexpr. expansion" }
return u.s.b;
  }
  constexpr int x3 = test3();  // { dg-message "in .constexpr. expansion" }

Incidentally I found this particular example caused a very unhelpful
error + ICE due to reporting that S could not be value-initialized in
the current version of the patch. The updated version below fixes that
by using 'build_zero_init' instead -- is this an appropriate choice
here?

A similar (but unrelated) issue is with e.g.
  
  struct S { const int a; int b; };
  union U { int k; S s; };

  constexpr int test() {
U u {};
return u.s.b;
  }
  constexpr int x = test();

giving me this pretty unhelpful error message:

/home/ns/main.cpp:8:23:   in ‘constexpr’ expansion of ‘test()’
/home/ns/main.cpp:6:12: error: use of deleted function ‘S::S()’
6 |   return u.s.b;
  |  ~~^
/home/ns/main.cpp:1:8: note: ‘S::S()’ is implicitly deleted because the default 
definition would be ill-formed:
1 | struct S { const int a; int b; };
  |^
/home/ns/main.cpp:1:8: error: uninitialised const member in ‘struct S’
/home/ns/main.cpp:1:22: note: ‘const int S::a’ should be initialised
1 | struct S { const int a; int b; };
  |  ^
/home/ns/main.cpp:8:23:   in ‘constexpr’ expansion of ‘test()’
/home/ns/main.cpp:6:12: error: use of deleted function ‘S::S()’
6 |   return u.s.b;
  |  ~~^
/home/ns/main.cpp:8:23:   in ‘constexpr’ expansion of ‘test()’
/home/ns/main.cpp:6:12: error: use of deleted function ‘S::S()’

but I'll try and fix this separately (it exists on current trunk without
this patch as well).

Bootstrapped and regtested on x86_64-pc-linux-gnu. Thanks!

-- >8 --

This patch adds checks for attempting to change the active member of a
union by methods other than a member access expression.

To be able to properly distinguish `*() = ` from `u.a = `, this
patch redoes the solution for c++/59950 to avoid extranneous *&; it
seems that the only case that needed the workaround was when copying
empty classes.

This patch also ensures that constructors for a union field mark that
field as the active member before entering the call itself; this ensures
that modifications of the field within the constructor's body don't
cause false positives (as these will not appear to be member access
expressions). This means that we no longer need to start the lifetime of
empty union members after the constructor body completes.

As a drive-by fix, this patch also ensures that value-initialised unions
are considered to have activated their initial member for the purpose of

Re: [PATCH] RISC-V Regression: Make match patterns more accurate

2023-10-10 Thread Jeff Law




On 10/9/23 20:47, Juzhe-Zhong wrote:

This patch fixes following 2 FAILs in RVV regression since the check is not 
accurate.

It's inspired by Robin's previous patch:
https://patchwork.sourceware.org/project/gcc/patch/dde89b9e-49a0-d70b-0906-fb3022cac...@gmail.com/

gcc/testsuite/ChangeLog:

* gcc.dg/vect/no-scevccp-outer-7.c: Adjust regex pattern.
* gcc.dg/vect/no-scevccp-vect-iv-3.c: Ditto.
OK.   We might see other ports flipping to a pass if they were 
exhibiting the same behavior with failing to vectorize with the first 
selected type, but passing on the second type.


Jeff


Re: [PATCH] RISC-V Regression: Fix dump check of bb-slp-68.c

2023-10-10 Thread Jeff Law




On 10/9/23 19:16, Juzhe-Zhong wrote:

Like GCN, RVV also has 64 bytes vectors (512 bits) which cause FAIL in this 
test.

It's more reasonable to use "vect512" instead of AMDGCN.

gcc/testsuite/ChangeLog:

* gcc.dg/vect/bb-slp-68.c: Use vect512.
Just a note for the record.  At this time the only target obviously 
advertising 512 bit vectors in available_vector_sizes is amdgcn -- 
avx512 doesn't signal 512 bit vectors right now.  SVE might, but it's a 
bit hard to tell easily and I don't have a cross handy.  I'd hazard a 
guess it would via -msve-vector-bits.


Anyway, OK for the trunk.  Just keep an eye out for reports of any 
issues with this test on aarch64.


Thanks,
Jeff



Re: [PATCH] dwarf2out: Stop using wide_int in GC structures

2023-10-10 Thread Richard Biener
On Tue, 10 Oct 2023, Jakub Jelinek wrote:

> Hi!
> 
> On Tue, Oct 10, 2023 at 09:30:31AM +, Richard Biener wrote:
> > On Mon, 9 Oct 2023, Jakub Jelinek wrote:
> > > > This makes wide_int unusable in GC structures, so for dwarf2out
> > > > which was the only place which needed it there is a new rwide_int type
> > > > (restricted wide_int) which supports only up to RWIDE_INT_MAX_ELTS limbs
> > > > inline and is trivially copyable (dwarf2out should never deal with large
> > > > _BitInt constants, those should have been lowered earlier).
> > > 
> > > As discussed on IRC, the dwarf2out.{h,cc} needs are actually quite 
> > > limited,
> > > it just needs to allocate new GC structures val_wide points to 
> > > (constructed
> > > from some const wide_int_ref &) and needs to call operator==,
> > > get_precision, elt, get_len and get_val methods on it.
> > > Even trailing_wide_int would be overkill for that, the following just adds
> > > a new struct with precision/len and trailing val array members and
> > > implements the needed methods (only 2 of them using wide_int_ref 
> > > constructed
> > > from those).
> > > 
> > > Incremental patch, so far compile time tested only:
> > 
> > LGTM, wonder if we can push this separately as prerequesite?
> 
> Here it is as a separate independent patch.  Even without the
> wide_int changing patch it should save some memory, by not always
> allocating room for 9 limbs, but say just the 2/3 or how many we actually
> need.  And, another advantage is that if we really need it at some point,
> it could support even more than 9 limbs if it is created from a wide_int_ref
> with get_len () > 9.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK by me if Jason doesn't object.

Thanks,
Richard.

> 2023-10-10  Jakub Jelinek  
> 
>   * dwarf2out.h (wide_int_ptr): Remove.
>   (dw_wide_int_ptr): New typedef.
>   (struct dw_val_node): Change type of val_wide from wide_int_ptr
>   to dw_wide_int_ptr.
>   (struct dw_wide_int): New type.
>   (dw_wide_int::elt): New method.
>   (dw_wide_int::operator ==): Likewise.
>   * dwarf2out.cc (get_full_len): Change argument type to
>   const dw_wide_int & from const wide_int &.  Use CEIL.  Call
>   get_precision method instead of calling wi::get_precision.
>   (alloc_dw_wide_int): New function.
>   (add_AT_wide): Change w argument type to const wide_int_ref &
>   from const wide_int &.  Use alloc_dw_wide_int.
>   (mem_loc_descriptor, loc_descriptor): Use alloc_dw_wide_int.
>   (insert_wide_int): Change val argument type to const wide_int_ref &
>   from const wide_int &.
>   (add_const_value_attribute): Pass rtx_mode_t temporary directly to
>   add_AT_wide instead of using a temporary variable.
> 
> --- gcc/dwarf2out.h.jj2023-10-09 14:37:45.890939965 +0200
> +++ gcc/dwarf2out.h   2023-10-09 16:46:14.705816928 +0200
> @@ -30,7 +30,7 @@ typedef struct dw_cfi_node *dw_cfi_ref;
>  typedef struct dw_loc_descr_node *dw_loc_descr_ref;
>  typedef struct dw_loc_list_struct *dw_loc_list_ref;
>  typedef struct dw_discr_list_node *dw_discr_list_ref;
> -typedef wide_int *wide_int_ptr;
> +typedef struct dw_wide_int *dw_wide_int_ptr;
>  
>  
>  /* Call frames are described using a sequence of Call Frame
> @@ -252,7 +252,7 @@ struct GTY(()) dw_val_node {
>unsigned HOST_WIDE_INT
>   GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
>double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
> -  wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
> +  dw_wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
>dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
>struct dw_val_die_union
>   {
> @@ -313,6 +313,35 @@ struct GTY(()) dw_discr_list_node {
>int dw_discr_range;
>  };
>  
> +struct GTY((variable_size)) dw_wide_int {
> +  unsigned int precision;
> +  unsigned int len;
> +  HOST_WIDE_INT val[1];
> +
> +  unsigned int get_precision () const { return precision; }
> +  unsigned int get_len () const { return len; }
> +  const HOST_WIDE_INT *get_val () const { return val; }
> +  inline HOST_WIDE_INT elt (unsigned int) const;
> +  inline bool operator == (const dw_wide_int &) const;
> +};
> +
> +inline HOST_WIDE_INT
> +dw_wide_int::elt (unsigned int i) const
> +{
> +  if (i < len)
> +return val[i];
> +  wide_int_ref ref = wi::storage_ref (val, len, precision);
> +  return wi::sign_mask (ref);
> +}
> +
> +inline bool
> +dw_wide_int::operator == (const dw_wide_int ) const
> +{
> +  wide_int_ref ref1 = wi::storage_ref (val, len, precision);
> +  wide_int_ref ref2 = wi::storage_ref (o.val, o.len, o.precision);
> +  return ref1 == ref2;
> +}
> +
>  /* Interface from dwarf2out.cc to dwarf2cfi.cc.  */
>  extern struct dw_loc_descr_node *build_cfa_loc
>(dw_cfa_location *, poly_int64);
> --- gcc/dwarf2out.cc.jj   2023-10-09 14:37:45.894939909 +0200
> +++ gcc/dwarf2out.cc  

[PATCH] dwarf2out: Stop using wide_int in GC structures

2023-10-10 Thread Jakub Jelinek
Hi!

On Tue, Oct 10, 2023 at 09:30:31AM +, Richard Biener wrote:
> On Mon, 9 Oct 2023, Jakub Jelinek wrote:
> > > This makes wide_int unusable in GC structures, so for dwarf2out
> > > which was the only place which needed it there is a new rwide_int type
> > > (restricted wide_int) which supports only up to RWIDE_INT_MAX_ELTS limbs
> > > inline and is trivially copyable (dwarf2out should never deal with large
> > > _BitInt constants, those should have been lowered earlier).
> > 
> > As discussed on IRC, the dwarf2out.{h,cc} needs are actually quite limited,
> > it just needs to allocate new GC structures val_wide points to (constructed
> > from some const wide_int_ref &) and needs to call operator==,
> > get_precision, elt, get_len and get_val methods on it.
> > Even trailing_wide_int would be overkill for that, the following just adds
> > a new struct with precision/len and trailing val array members and
> > implements the needed methods (only 2 of them using wide_int_ref constructed
> > from those).
> > 
> > Incremental patch, so far compile time tested only:
> 
> LGTM, wonder if we can push this separately as prerequesite?

Here it is as a separate independent patch.  Even without the
wide_int changing patch it should save some memory, by not always
allocating room for 9 limbs, but say just the 2/3 or how many we actually
need.  And, another advantage is that if we really need it at some point,
it could support even more than 9 limbs if it is created from a wide_int_ref
with get_len () > 9.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2023-10-10  Jakub Jelinek  

* dwarf2out.h (wide_int_ptr): Remove.
(dw_wide_int_ptr): New typedef.
(struct dw_val_node): Change type of val_wide from wide_int_ptr
to dw_wide_int_ptr.
(struct dw_wide_int): New type.
(dw_wide_int::elt): New method.
(dw_wide_int::operator ==): Likewise.
* dwarf2out.cc (get_full_len): Change argument type to
const dw_wide_int & from const wide_int &.  Use CEIL.  Call
get_precision method instead of calling wi::get_precision.
(alloc_dw_wide_int): New function.
(add_AT_wide): Change w argument type to const wide_int_ref &
from const wide_int &.  Use alloc_dw_wide_int.
(mem_loc_descriptor, loc_descriptor): Use alloc_dw_wide_int.
(insert_wide_int): Change val argument type to const wide_int_ref &
from const wide_int &.
(add_const_value_attribute): Pass rtx_mode_t temporary directly to
add_AT_wide instead of using a temporary variable.

--- gcc/dwarf2out.h.jj  2023-10-09 14:37:45.890939965 +0200
+++ gcc/dwarf2out.h 2023-10-09 16:46:14.705816928 +0200
@@ -30,7 +30,7 @@ typedef struct dw_cfi_node *dw_cfi_ref;
 typedef struct dw_loc_descr_node *dw_loc_descr_ref;
 typedef struct dw_loc_list_struct *dw_loc_list_ref;
 typedef struct dw_discr_list_node *dw_discr_list_ref;
-typedef wide_int *wide_int_ptr;
+typedef struct dw_wide_int *dw_wide_int_ptr;
 
 
 /* Call frames are described using a sequence of Call Frame
@@ -252,7 +252,7 @@ struct GTY(()) dw_val_node {
   unsigned HOST_WIDE_INT
GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
   double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
-  wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
+  dw_wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
   dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
   struct dw_val_die_union
{
@@ -313,6 +313,35 @@ struct GTY(()) dw_discr_list_node {
   int dw_discr_range;
 };
 
+struct GTY((variable_size)) dw_wide_int {
+  unsigned int precision;
+  unsigned int len;
+  HOST_WIDE_INT val[1];
+
+  unsigned int get_precision () const { return precision; }
+  unsigned int get_len () const { return len; }
+  const HOST_WIDE_INT *get_val () const { return val; }
+  inline HOST_WIDE_INT elt (unsigned int) const;
+  inline bool operator == (const dw_wide_int &) const;
+};
+
+inline HOST_WIDE_INT
+dw_wide_int::elt (unsigned int i) const
+{
+  if (i < len)
+return val[i];
+  wide_int_ref ref = wi::storage_ref (val, len, precision);
+  return wi::sign_mask (ref);
+}
+
+inline bool
+dw_wide_int::operator == (const dw_wide_int ) const
+{
+  wide_int_ref ref1 = wi::storage_ref (val, len, precision);
+  wide_int_ref ref2 = wi::storage_ref (o.val, o.len, o.precision);
+  return ref1 == ref2;
+}
+
 /* Interface from dwarf2out.cc to dwarf2cfi.cc.  */
 extern struct dw_loc_descr_node *build_cfa_loc
   (dw_cfa_location *, poly_int64);
--- gcc/dwarf2out.cc.jj 2023-10-09 14:37:45.894939909 +0200
+++ gcc/dwarf2out.cc2023-10-09 16:48:24.565014459 +0200
@@ -397,11 +397,9 @@ dump_struct_debug (tree type, enum debug
of the number.  */
 
 static unsigned int
-get_full_len (const wide_int )
+get_full_len (const dw_wide_int )
 {
-  int prec = wi::get_precision (op);
-  return ((prec + HOST_BITS_PER_WIDE_INT - 1)
- / 

Re: [PATCH] tree-optimization/111519 - strlen optimization skips clobbering store

2023-10-10 Thread Richard Biener
On Tue, 10 Oct 2023, Jakub Jelinek wrote:

> On Tue, Oct 10, 2023 at 11:59:28AM +, Richard Biener wrote:
> > > I don't see why the CONSTRUCTOR case couldn't be fine regardless of the
> > > vuse.  Though, am not really sure when a CONSTRUCTOR would appear, the
> > > lhs would need to be an SSA_NAME, so wouldn't for vectors that be a
> > > VECTOR_CST instead, etc.?  Ah, perhaps a vector with some non-constant
> > > element in it.
> > 
> > Yeah, but what should that be interpreted to in terms of object-size?!
> 
> The function in question doesn't compute object sizes, just minimum/maximum
> number of non-zero bytes in some rhs of a store and whether everything
> stored is 0s, or everything non-zeros, or some non-zeros followed by zero.
> 
> > I think the only real case we'd see here is the MEM_REF RHS given
> > we know we have a register type value.  I'll note the function
> > totally misses handled_component_p (), it only seems to handle
> > *p and 'decl'.
> 
> Yeah, maybe we could handle even that at some point.
> Though perhaps better first to rewrite it completely, because the recursive
> calls where in some cases it means one thing and in another case something
> completely different are just bad design (or lack thereof).

Yeah ... (true for many similar pieces in pointer-query and other
diagnostic passes...)

> > > So maybe pass the vuse down to count_nonzero_bytes_addr and return false
> > > in the idx > 0 case in there if gimple_vuse (stmt) != vuse?
> > 
> > I don't know enough of the pass to do better, can you take it from here?
> > One of the points is that we need to know the memory context (aka vuse)
> > of both the original store and the load we are interpreting.  For
> > _addr I wasn't sure how we arrive here.  As you said, this is a bit
> > of spaghetti and I don't want to untangle this any further.
> 
> I meant something like below, without getting rid of the -Wshadow stuff
> in there my initial attempt didn't work.  This passes the new testcase
> as well as the testcase you've been touching, but haven't tested it beyond
> that yet.

Works for me if it turns out working.

> In theory we could even handle some cases with gimple_vuse (stmt) != vuse,
> because we save a copy of the strinfo state at the end of basic blocks and
> only throw that away after we process all dominator children.  But we'd need
> to figure out at which bb to look and temporarily switch the vectors.

As we need sth for the branch(es) I think we should do that as followup
at most.

Thanks,
Richard.

> 2023-10-10  Richard Biener  
>   Jakub Jelinek  
> 
>   PR tree-optimization/111519
>   * tree-ssa-strlen.cc (strlen_pass::count_nonzero_bytes): Add vuse
>   argument and pass it through to recursive calls and
>   count_nonzero_bytes_addr calls.  Don't shadow the stmt argument, but
>   change stmt for gimple_assign_single_p statements for which we don't
>   immediately punt.
>   (strlen_pass::count_nonzero_bytes_addr): Add vuse argument and pass
>   it through to recursive calls and count_nonzero_bytes calls.  Don't
>   use get_strinfo if gimple_vuse (stmt) is different from vuse.  Don't
>   shadow the stmt argument.
> 
>   * gcc.dg/torture/pr111519.c: New testcase.
> 
> --- gcc/tree-ssa-strlen.cc.jj 2023-08-30 11:21:38.539521966 +0200
> +++ gcc/tree-ssa-strlen.cc2023-10-10 15:05:44.731871218 +0200
> @@ -281,14 +281,14 @@ public:
>   gimple *stmt,
>   unsigned lenrange[3], bool *nulterm,
>   bool *allnul, bool *allnonnul);
> -  bool count_nonzero_bytes (tree exp,
> +  bool count_nonzero_bytes (tree exp, tree vuse,
>   gimple *stmt,
>   unsigned HOST_WIDE_INT offset,
>   unsigned HOST_WIDE_INT nbytes,
>   unsigned lenrange[3], bool *nulterm,
>   bool *allnul, bool *allnonnul,
>   ssa_name_limit_t );
> -  bool count_nonzero_bytes_addr (tree exp,
> +  bool count_nonzero_bytes_addr (tree exp, tree vuse,
>gimple *stmt,
>unsigned HOST_WIDE_INT offset,
>unsigned HOST_WIDE_INT nbytes,
> @@ -4531,8 +4531,8 @@ nonzero_bytes_for_type (tree type, unsig
>  }
>  
>  /* Recursively determine the minimum and maximum number of leading nonzero
> -   bytes in the representation of EXP and set LENRANGE[0] and LENRANGE[1]
> -   to each.
> +   bytes in the representation of EXP at memory state VUSE and set
> +   LENRANGE[0] and LENRANGE[1] to each.
> Sets LENRANGE[2] to the total size of the access (which may be less
> than LENRANGE[1] when what's being referenced by EXP is a pointer
> rather than an array).
> @@ -4546,7 +4546,7 @@ nonzero_bytes_for_type (tree type, unsig
> Returns true on success and false otherwise.  */
>  
>  bool
> 

Re: [PATCH] RISC-V/testsuite: Enable `vect_pack_trunc'

2023-10-10 Thread Jeff Law




On 10/9/23 19:13, juzhe.zh...@rivai.ai wrote:

Oh. I realize this patch increase FAIL that I recently fixed:
https://gcc.gnu.org/pipermail/gcc-patches/2023-October/632247.html 



This fail because RVV doesn't have vec_pack_trunc_optab (Loop vectorizer 
will failed at first time but succeed at 2nd time),
then RVV will dump 4 times FOLD_EXTRACT_LAST instead of 2  (ARM SVE 2 
times because they have vec_pack_trunc_optab).


I think the root cause of RVV failing at multiple tests of "vect" is 
that we don't enable vec_pack/vec_unpack/... stuff,

we still succeed at vectorizations and we want to enable tests of them
(Mostly just using different approach to vectorize it (cause dump FAIL) 
because of some changing I have done previously in the middle-end).


So enabling "vec_pack" for RVV will fix some FAILs but increase some 
other FAILs.


CC to Richi to see more reasonable suggestions.
So what is the summary on Maciej's patch to enable vec_pack_trunc?  ie, 
is it something we should move forward with as-is, is it superceded by 
your work in this space or does it need further investigation because of 
differences in testing methodologies or something else?


jeff


RE: [PATCH] RISC-V Regression: Fix FAIL of pr65947-8.c for RVV

2023-10-10 Thread Li, Pan2
Committed, thanks Jeff.

Pan

-Original Message-
From: Jeff Law  
Sent: Tuesday, October 10, 2023 9:24 PM
To: Juzhe-Zhong ; gcc-patches@gcc.gnu.org
Cc: rguent...@suse.de
Subject: Re: [PATCH] RISC-V Regression: Fix FAIL of pr65947-8.c for RVV



On 10/10/23 06:55, Juzhe-Zhong wrote:
> This test is testing fold_extract_last pattern so it's more reasonable use
> vect_fold_extract_last instead of specifying targets.
> 
> This is the vect_fold_extract_last property:
> proc check_effective_target_vect_fold_extract_last { } {
>  return [expr { [check_effective_target_aarch64_sve]
>  || [istarget amdgcn*-*-*]
>  || [check_effective_target_riscv_v] }]
> }
> 
> include ARM SVE/GCN/RVV.
> 
> It perfectly matches what we want and more reasonable, better maintainment.
> 
> gcc/testsuite/ChangeLog:
> 
>   * gcc.dg/vect/pr65947-8.c: Use vect_fold_extract_last.
OK
jeff


Re: [PATCH] tree-optimization/111519 - strlen optimization skips clobbering store

2023-10-10 Thread Jakub Jelinek
On Tue, Oct 10, 2023 at 11:59:28AM +, Richard Biener wrote:
> > I don't see why the CONSTRUCTOR case couldn't be fine regardless of the
> > vuse.  Though, am not really sure when a CONSTRUCTOR would appear, the
> > lhs would need to be an SSA_NAME, so wouldn't for vectors that be a
> > VECTOR_CST instead, etc.?  Ah, perhaps a vector with some non-constant
> > element in it.
> 
> Yeah, but what should that be interpreted to in terms of object-size?!

The function in question doesn't compute object sizes, just minimum/maximum
number of non-zero bytes in some rhs of a store and whether everything
stored is 0s, or everything non-zeros, or some non-zeros followed by zero.

> I think the only real case we'd see here is the MEM_REF RHS given
> we know we have a register type value.  I'll note the function
> totally misses handled_component_p (), it only seems to handle
> *p and 'decl'.

Yeah, maybe we could handle even that at some point.
Though perhaps better first to rewrite it completely, because the recursive
calls where in some cases it means one thing and in another case something
completely different are just bad design (or lack thereof).

> > So maybe pass the vuse down to count_nonzero_bytes_addr and return false
> > in the idx > 0 case in there if gimple_vuse (stmt) != vuse?
> 
> I don't know enough of the pass to do better, can you take it from here?
> One of the points is that we need to know the memory context (aka vuse)
> of both the original store and the load we are interpreting.  For
> _addr I wasn't sure how we arrive here.  As you said, this is a bit
> of spaghetti and I don't want to untangle this any further.

I meant something like below, without getting rid of the -Wshadow stuff
in there my initial attempt didn't work.  This passes the new testcase
as well as the testcase you've been touching, but haven't tested it beyond
that yet.
In theory we could even handle some cases with gimple_vuse (stmt) != vuse,
because we save a copy of the strinfo state at the end of basic blocks and
only throw that away after we process all dominator children.  But we'd need
to figure out at which bb to look and temporarily switch the vectors.

2023-10-10  Richard Biener  
Jakub Jelinek  

PR tree-optimization/111519
* tree-ssa-strlen.cc (strlen_pass::count_nonzero_bytes): Add vuse
argument and pass it through to recursive calls and
count_nonzero_bytes_addr calls.  Don't shadow the stmt argument, but
change stmt for gimple_assign_single_p statements for which we don't
immediately punt.
(strlen_pass::count_nonzero_bytes_addr): Add vuse argument and pass
it through to recursive calls and count_nonzero_bytes calls.  Don't
use get_strinfo if gimple_vuse (stmt) is different from vuse.  Don't
shadow the stmt argument.

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

--- gcc/tree-ssa-strlen.cc.jj   2023-08-30 11:21:38.539521966 +0200
+++ gcc/tree-ssa-strlen.cc  2023-10-10 15:05:44.731871218 +0200
@@ -281,14 +281,14 @@ public:
gimple *stmt,
unsigned lenrange[3], bool *nulterm,
bool *allnul, bool *allnonnul);
-  bool count_nonzero_bytes (tree exp,
+  bool count_nonzero_bytes (tree exp, tree vuse,
gimple *stmt,
unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT nbytes,
unsigned lenrange[3], bool *nulterm,
bool *allnul, bool *allnonnul,
ssa_name_limit_t );
-  bool count_nonzero_bytes_addr (tree exp,
+  bool count_nonzero_bytes_addr (tree exp, tree vuse,
 gimple *stmt,
 unsigned HOST_WIDE_INT offset,
 unsigned HOST_WIDE_INT nbytes,
@@ -4531,8 +4531,8 @@ nonzero_bytes_for_type (tree type, unsig
 }
 
 /* Recursively determine the minimum and maximum number of leading nonzero
-   bytes in the representation of EXP and set LENRANGE[0] and LENRANGE[1]
-   to each.
+   bytes in the representation of EXP at memory state VUSE and set
+   LENRANGE[0] and LENRANGE[1] to each.
Sets LENRANGE[2] to the total size of the access (which may be less
than LENRANGE[1] when what's being referenced by EXP is a pointer
rather than an array).
@@ -4546,7 +4546,7 @@ nonzero_bytes_for_type (tree type, unsig
Returns true on success and false otherwise.  */
 
 bool
-strlen_pass::count_nonzero_bytes (tree exp, gimple *stmt,
+strlen_pass::count_nonzero_bytes (tree exp, tree vuse, gimple *stmt,
  unsigned HOST_WIDE_INT offset,
  unsigned HOST_WIDE_INT nbytes,
  unsigned lenrange[3], bool *nulterm,
@@ -4566,22 +4566,23 @@ strlen_pass::count_nonzero_bytes (tree e
 exact value is not 

Re: [PATCH] RISC-V Regression: Fix FAIL of pr65947-8.c for RVV

2023-10-10 Thread Jeff Law




On 10/10/23 06:55, Juzhe-Zhong wrote:

This test is testing fold_extract_last pattern so it's more reasonable use
vect_fold_extract_last instead of specifying targets.

This is the vect_fold_extract_last property:
proc check_effective_target_vect_fold_extract_last { } {
 return [expr { [check_effective_target_aarch64_sve]
   || [istarget amdgcn*-*-*]
   || [check_effective_target_riscv_v] }]
}

include ARM SVE/GCN/RVV.

It perfectly matches what we want and more reasonable, better maintainment.

gcc/testsuite/ChangeLog:

* gcc.dg/vect/pr65947-8.c: Use vect_fold_extract_last.

OK
jeff


Re: [PATCH 3/3]middle-end: maintain LCSSA throughout loop peeling

2023-10-10 Thread Richard Biener
On Mon, 2 Oct 2023, Tamar Christina wrote:

> Hi All,
> 
> This final patch updates peeling to maintain LCSSA all the way through.
> 
> It's significantly easier to maintain it during peeling while we still know
> where all new edges connect rather than touching it up later as is currently
> being done.
> 
> This allows us to remove many of the helper functions that touch up the loops
> at various parts.  The only complication is for loop distribution where we
> should be able to use the same,  however ldist depending on whether
> redirect_lc_phi_defs is true or not will either try to maintain a limited 
> LCSSA
> form itself or removes are non-virtual phis.
> 
> The problem here is that if we maintain LCSSA then in some cases the blocks
> connecting the two loops get PHIs to keep the loop IV up to date.
> 
> However there is no loop, the guard condition is rewritten as 0 != 0, to the
> "loop" always exits.   However due to the PHI nodes the probabilities get
> completely wrong.  It seems to think that the impossible exit is the likely
> edge.  This causes incorrect warnings and the presence of the PHIs prevent the
> blocks to be simplified.
> 
> While it may be possible to make ldist work with LCSSA form, doing so seems 
> more
> work than not.  For that reason the peeling code has an additional parameter
> used by only ldist to not connect the two loops during peeling.
> 
> This preserves the current behaviour from ldist until I can dive into the
> implementation more.  Hopefully that's ok for now.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-linux-gnu, and
> no issues.
> 
> Ok for master?
> 
> Thanks,
> Tamar
> 
> gcc/ChangeLog:
> 
>   * tree-loop-distribution.cc (copy_loop_before): Request no LCSSA.
>   * tree-vect-loop-manip.cc (adjust_phi_and_debug_stmts): Add additional
>   asserts.
>   (slpeel_tree_duplicate_loop_to_edge_cfg): Keep LCSSA during peeling.
>   (find_guard_arg): Look value up through explicit edge and original defs.
>   (vect_do_peeling): Use it.
>   (slpeel_update_phi_nodes_for_guard2): Take explicit exit edge.
>   (slpeel_update_phi_nodes_for_lcssa, slpeel_update_phi_nodes_for_loops):
>   Remove.
>   * tree-vect-loop.cc (vect_create_epilog_for_reduction): Initialize phi.
>   * tree-vectorizer.h (slpeel_tree_duplicate_loop_to_edge_cfg): Add
>   optional param to turn off LCSSA mode.
> 
> --- inline copy of patch -- 
> diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc
> index 
> 902edc49ab588152a5b845f2c8a42a7e2a1d6080..14fb884d3e91d79785867debaee4956a2d5b0bb1
>  100644
> --- a/gcc/tree-loop-distribution.cc
> +++ b/gcc/tree-loop-distribution.cc
> @@ -950,7 +950,7 @@ copy_loop_before (class loop *loop, bool 
> redirect_lc_phi_defs)
>  
>initialize_original_copy_tables ();
>res = slpeel_tree_duplicate_loop_to_edge_cfg (loop, single_exit (loop), 
> NULL,
> - NULL, preheader, NULL);
> + NULL, preheader, NULL, false);
>gcc_assert (res != NULL);
>  
>/* When a not last partition is supposed to keep the LC PHIs computed
> diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
> index 
> 77f8e668bcc8beca99ba4052e1b12e0d17300262..0e8c0be5384aab2399ed93966e7bf4918f6c87a5
>  100644
> --- a/gcc/tree-vect-loop-manip.cc
> +++ b/gcc/tree-vect-loop-manip.cc
> @@ -252,6 +252,9 @@ adjust_phi_and_debug_stmts (gimple *update_phi, edge e, 
> tree new_def)
>  {
>tree orig_def = PHI_ARG_DEF_FROM_EDGE (update_phi, e);
>  
> +  gcc_assert (TREE_CODE (orig_def) != SSA_NAME
> +   || orig_def != new_def);
> +
>SET_PHI_ARG_DEF (update_phi, e->dest_idx, new_def);
>  
>if (MAY_HAVE_DEBUG_BIND_STMTS)
> @@ -1445,12 +1448,19 @@ slpeel_duplicate_current_defs_from_edges (edge from, 
> edge to)
> on E which is either the entry or exit of LOOP.  If SCALAR_LOOP is
> non-NULL, assume LOOP and SCALAR_LOOP are equivalent and copy the
> basic blocks from SCALAR_LOOP instead of LOOP, but to either the
> -   entry or exit of LOOP.  */
> +   entry or exit of LOOP.  If FLOW_LOOPS then connect LOOP to SCALAR_LOOP as 
> a
> +   continuation.  This is correct for cases where one loop continues from the
> +   other like in the vectorizer, but not true for uses in e.g. loop 
> distribution
> +   where the loop is duplicated and then modified.

But for loop distribution the other loop also "continues" from the other,
maybe better say ", but not true for uses in e.g. loop distribution where
the contents of the loop body are split but the iteration space of both
copies remains the same."  It's an implementation limitation in loop
distribution that it for example doesn't support producing reductions
as the first loop (aka it cannot handle LC PHI nodes "inbetween").

> +
> +   If UPDATED_DOMS is not NULL it is update with the list of basic blocks 
> whoms
> +   dominators were updated during the 

  1   2   >