Re: [PATCH] Add std::deque shrink_to_fit test

2025-04-14 Thread François Dumont


On 14/04/2025 08:29, Tomasz Kaminski wrote:



On Sun, Apr 13, 2025 at 12:13 PM François Dumont 
 wrote:



On 11/04/2025 08:36, Tomasz Kaminski wrote:



On Thu, Apr 10, 2025 at 10:47 PM Jonathan Wakely
 wrote:

On 10/04/25 22:36 +0200, François Dumont wrote:
>After running the test with -fno-exceptions option we rather
need this
>patch.
>
>Ok to commit ?
>
>François
>
>
>On 10/04/2025 21:08, François Dumont wrote:
>>Hi
>>
>>    No problem detected now that we really test std::deque
>>shrink_to_fit implementation.
>>
>>    libstdc++: Add std::deque<>::shrink_to_fit test
>>
>>    The existing test is currently testing std::vector.
Make it test
>>std::deque.
>>
>>    libstdc++-v3/ChangeLog:
>>
>>    *
>>testsuite/23_containers/deque/capacity/shrink_to_fit.cc:
Adapt test
>>    to check std::deque shrink_to_fit method.
>>
>>Tested under Linux x64.
>>
>>Ok to commit ?
>>
>>François

>diff --git
a/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
b/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
>index 7cb67079214..9c8b3a926e8 100644
>---
a/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
>+++
b/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
>@@ -1,4 +1,5 @@
> // { dg-do run { target c++11 } }
>+// { dg-add-options no_pch }

Tests using replacement_memory_operators.h need:

// { dg-require-effective-target std_allocator_new }
// { dg-xfail-run-if "AIX operator new" { powerpc-ibm-aix* } }

See e.g. 23_containers/unordered_set/96088.cc


Thanks, I new I needed to add something like that but then forgot
to amend my test.




>
> // 2010-01-08  Paolo Carlini  
>
>@@ -19,18 +20,39 @@
> // with this library; see the file COPYING3. If not see
> // .
>
>-#include 
>+#define _GLIBCXX_DEQUE_BUF_SIZE sizeof(int) * 3

Couldn't the test just create more elements, instead of
modifying the
internals? We should test it using the default parameters, no?


Sounds better indeed, done using std::__deque_buf_size extension.



In from_range test I have used a class that contains some padding,
to be able to fill the deque buffer, while still test with few
elements,

struct EightInBuf

{
  EightInBuf(int x) : elems{x}
  { }

 private:
   int elems[512 / (sizeof(int) * 8)];

  friend constexpr bool operator==(EightInBuf const& lhs, int rhs)
  { return lhs.elems[0] == rhs; }
 }; 






It is a nice alternative even if you are still relying on the 512
implementation detail hidden by _GLIBCXX_DEQUE_BUF_SIZE macro.

This is why I preferred to use__deque_buf_size.

When using _GLIBCXX_DEBUG this function will be defined inside 
std::__cxx1998 namespace, not in the std directly.
There is a macro _GLIBCXX_STD_C that can be used to refer to it, but 
it works only inside std namespace.


Fixed in this new version.

Ok to commit ?

François

diff --git 
a/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc 
b/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
index 7cb67079214..4dbf405d57b 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
@@ -1,4 +1,6 @@
 // { dg-do run { target c++11 } }
+// { dg-require-effective-target std_allocator_new }
+// { dg-xfail-run-if "AIX operator new" { powerpc-ibm-aix* } }
 
 // 2010-01-08  Paolo Carlini  
 
@@ -19,18 +21,42 @@
 // with this library; see the file COPYING3.  If not see
 // .
 
-#include 
+#include 
 #include 
+#include 
 
 // libstdc++/42573
 void test01()
 {
-  std::vector d(100);
-  d.push_back(1);
-  d.push_back(1);
-  // VERIFY( d.size() < d.capacity() );
+  using namespace std;
+  __gnu_test::counter::reset();
+
+  const size_t buf_size = _GLIBCXX_STD_C::__deque_buf_size(sizeof(size_t));
+  deque d;
+  for (size_t i = 0; i != buf_size; ++i)
+d.push_back(i);
+
+  // No shrink if 1st buffer is full, create some front capacity.
+  d.pop_front();
+
+  // 1 node array allocation + 2 node allocation = 3.
+  VERIFY( __gnu_test::counter::count() == 3 );
+  VERIFY( __gnu_test::counter::get()._M_increments == 3 );
+
   d.shrink_to_fit();
-  // VERIFY( d.size() == d.capacity() );
+
+  // No reallocation if no exception support, shrink_to_fit is then a
+  // no-op.
+#if __cpp_exceptions
+  // 1 node array alloca

[r15-9431 Regression] FAIL: gcc.target/i386/apx-interrupt-1.c scan-assembler-times .cfi_restore 15 on Linux/x86_64

2025-04-14 Thread haochen.jiang
On Linux/x86_64,

0a074b8c7e79f9d9359d044f1499b0a9ce9d2801 is the first bad commit
commit 0a074b8c7e79f9d9359d044f1499b0a9ce9d2801
Author: H.J. Lu 
Date:   Sun Apr 13 12:20:42 2025 -0700

APX: Don't use red-zone with 32 GPRs and no caller-saved registers

caused

FAIL: gcc.target/i386/apx-interrupt-1.c scan-assembler-times .cfi_restore 15

with GCC configured with

../../gcc/configure 
--prefix=/export/users/haochenj/src/gcc-bisect/master/master/r15-9431/usr 
--enable-clocale=gnu --with-system-zlib --with-demangler-in-ld 
--with-fpmath=sse --enable-languages=c,c++,fortran --enable-cet --without-isl 
--enable-libmpx x86_64-linux --disable-bootstrap

To reproduce:

$ cd {build_dir}/gcc && make check 
RUNTESTFLAGS="i386.exp=gcc.target/i386/apx-interrupt-1.c 
--target_board='unix{-m64}'"
$ cd {build_dir}/gcc && make check 
RUNTESTFLAGS="i386.exp=gcc.target/i386/apx-interrupt-1.c 
--target_board='unix{-m64\ -march=cascadelake}'"

(Please do not reply to this email, for question about this report, contact me 
at haochen dot jiang at intel.com.)
(If you met problems with cascadelake related, disabling AVX512F in command 
line might save that.)
(However, please make sure that there is no potential problems with AVX512.)


[PUSHED] Add PR119692 "C++ 'typeinfo', 'vtable' vs. OpenACC, OpenMP 'target' offloading" test cases [PR119692]

2025-04-14 Thread Thomas Schwinge
... documenting the status quo.

PR c++/119692
gcc/testsuite/
* g++.target/gcn/pr119692-1-1.C: New.
* g++.target/nvptx/pr119692-1-1.C: Likewise.
libgomp/
* testsuite/libgomp.c++/pr119692-1-1.C: New.
* testsuite/libgomp.c++/pr119692-1-2.C: Likewise.
* testsuite/libgomp.c++/pr119692-1-3.C: Likewise.
* testsuite/libgomp.c++/pr119692-1-4.C: Likewise.
* testsuite/libgomp.c++/pr119692-1-5.C: Likewise.
* testsuite/libgomp.oacc-c++/pr119692-1-1.C: Likewise.
* testsuite/libgomp.oacc-c++/pr119692-1-2.C: Likewise.
* testsuite/libgomp.oacc-c++/pr119692-1-3.C: Likewise.
---
 gcc/testsuite/g++.target/gcn/pr119692-1-1.C   |  6 +++
 gcc/testsuite/g++.target/nvptx/pr119692-1-1.C |  6 +++
 libgomp/testsuite/libgomp.c++/pr119692-1-1.C  | 10 +
 libgomp/testsuite/libgomp.c++/pr119692-1-2.C  | 11 +
 libgomp/testsuite/libgomp.c++/pr119692-1-3.C  | 10 +
 libgomp/testsuite/libgomp.c++/pr119692-1-4.C  | 10 +
 libgomp/testsuite/libgomp.c++/pr119692-1-5.C  | 10 +
 .../testsuite/libgomp.oacc-c++/pr119692-1-1.C | 42 +++
 .../testsuite/libgomp.oacc-c++/pr119692-1-2.C | 12 ++
 .../testsuite/libgomp.oacc-c++/pr119692-1-3.C | 12 ++
 10 files changed, 129 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/gcn/pr119692-1-1.C
 create mode 100644 gcc/testsuite/g++.target/nvptx/pr119692-1-1.C
 create mode 100644 libgomp/testsuite/libgomp.c++/pr119692-1-1.C
 create mode 100644 libgomp/testsuite/libgomp.c++/pr119692-1-2.C
 create mode 100644 libgomp/testsuite/libgomp.c++/pr119692-1-3.C
 create mode 100644 libgomp/testsuite/libgomp.c++/pr119692-1-4.C
 create mode 100644 libgomp/testsuite/libgomp.c++/pr119692-1-5.C
 create mode 100644 libgomp/testsuite/libgomp.oacc-c++/pr119692-1-1.C
 create mode 100644 libgomp/testsuite/libgomp.oacc-c++/pr119692-1-2.C
 create mode 100644 libgomp/testsuite/libgomp.oacc-c++/pr119692-1-3.C

diff --git a/gcc/testsuite/g++.target/gcn/pr119692-1-1.C 
b/gcc/testsuite/g++.target/gcn/pr119692-1-1.C
new file mode 100644
index 000..b44b08d667d
--- /dev/null
+++ b/gcc/testsuite/g++.target/gcn/pr119692-1-1.C
@@ -0,0 +1,6 @@
+/* PR119692 "C++ 'typeinfo', 'vtable' vs. OpenACC, OpenMP 'target' offloading" 
*/
+
+/* { dg-do run } */
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+
+#include "../../../../libgomp/testsuite/libgomp.oacc-c++/pr119692-1-1.C"
diff --git a/gcc/testsuite/g++.target/nvptx/pr119692-1-1.C 
b/gcc/testsuite/g++.target/nvptx/pr119692-1-1.C
new file mode 100644
index 000..b44b08d667d
--- /dev/null
+++ b/gcc/testsuite/g++.target/nvptx/pr119692-1-1.C
@@ -0,0 +1,6 @@
+/* PR119692 "C++ 'typeinfo', 'vtable' vs. OpenACC, OpenMP 'target' offloading" 
*/
+
+/* { dg-do run } */
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+
+#include "../../../../libgomp/testsuite/libgomp.oacc-c++/pr119692-1-1.C"
diff --git a/libgomp/testsuite/libgomp.c++/pr119692-1-1.C 
b/libgomp/testsuite/libgomp.c++/pr119692-1-1.C
new file mode 100644
index 000..1f59b151540
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/pr119692-1-1.C
@@ -0,0 +1,10 @@
+/* PR119692 "C++ 'typeinfo', 'vtable' vs. OpenACC, OpenMP 'target' offloading" 
*/
+
+/* { dg-additional-options -UDEFAULT }
+   Wrong code for offloading execution.
+   { dg-additional-options -foffload=disable } */
+/* { dg-additional-options -fdump-tree-gimple } */
+
+#include "../libgomp.oacc-c++/pr119692-1-1.C"
+
+/* { dg-final { scan-tree-dump-not {(?n)#pragma omp target .* 
map\(tofrom:_ZTI2C2 \[len: [0-9]+\] \[runtime_implicit\]\) map\(tofrom:_ZTI2C1 
\[len: [0-9]+\] \[runtime_implicit\]\) map\(tofrom:_ZTV2C1 \[len: [0-9]+\] 
\[runtime_implicit\]\)$} gimple { xfail *-*-* } } } */
diff --git a/libgomp/testsuite/libgomp.c++/pr119692-1-2.C 
b/libgomp/testsuite/libgomp.c++/pr119692-1-2.C
new file mode 100644
index 000..e7ac818435e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/pr119692-1-2.C
@@ -0,0 +1,11 @@
+/* PR119692 "C++ 'typeinfo', 'vtable' vs. OpenACC, OpenMP 'target' offloading" 
*/
+
+/* { dg-additional-options -DDEFAULT=defaultmap(none) }
+   Fails to compile.
+   { dg-do compile } */
+
+#include "pr119692-1-1.C"
+
+/* { dg-bogus {error: '_ZTV2C1' not specified in enclosing 'target'} PR119692 
{ xfail *-*-* } 0 }
+   { dg-bogus {error: '_ZTI2C2' not specified in enclosing 'target'} PR119692 
{ xfail *-*-* } 0 }
+   { dg-bogus {error: '_ZTI2C1' not specified in enclosing 'target'} PR119692 
{ xfail *-*-* } 0 } */
diff --git a/libgomp/testsuite/libgomp.c++/pr119692-1-3.C 
b/libgomp/testsuite/libgomp.c++/pr119692-1-3.C
new file mode 100644
index 000..733feb80043
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/pr119692-1-3.C
@@ -0,0 +1,10 @@
+/* PR119692 "C++ 'typeinfo', 'vtable' vs. OpenACC, OpenMP 'target' offloading" 
*/
+
+/* { dg-additional-options -DDEFAULT=defaul

[PUSHED 2/3] Add 'std::bad_cast' exception, caught test cases for GCN, nvptx target and OpenACC, OpenMP 'target' offloading

2025-04-14 Thread Thomas Schwinge
gcc/testsuite/
* g++.target/gcn/exceptions-bad_cast-2.C: New.
* g++.target/nvptx/exceptions-bad_cast-2.C: Likewise.
libgomp/
* testsuite/libgomp.c++/target-exceptions-bad_cast-2.C: New.
* 
testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-GCN.C: 
Likewise.
* 
testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-nvptx.C: 
Likewise.
* testsuite/libgomp.oacc-c++/exceptions-bad_cast-2.C: Likewise.
* testsuite/libgomp.oacc-c++/exceptions-bad_cast-2-offload-sorry-GCN.C: 
Likewise.
* 
testsuite/libgomp.oacc-c++/exceptions-bad_cast-2-offload-sorry-nvptx.C: 
Likewise.
---
 .../g++.target/gcn/exceptions-bad_cast-2.C| 12 +
 .../g++.target/nvptx/exceptions-bad_cast-2.C  | 12 +
 ...-exceptions-bad_cast-2-offload-sorry-GCN.C | 18 +++
 ...xceptions-bad_cast-2-offload-sorry-nvptx.C | 18 +++
 .../target-exceptions-bad_cast-2.C| 14 ++
 .../exceptions-bad_cast-2-offload-sorry-GCN.C | 17 +++
 ...xceptions-bad_cast-2-offload-sorry-nvptx.C | 19 
 .../libgomp.oacc-c++/exceptions-bad_cast-2.C  | 48 +++
 8 files changed, 158 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/gcn/exceptions-bad_cast-2.C
 create mode 100644 gcc/testsuite/g++.target/nvptx/exceptions-bad_cast-2.C
 create mode 100644 
libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-GCN.C
 create mode 100644 
libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-nvptx.C
 create mode 100644 libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2.C
 create mode 100644 
libgomp/testsuite/libgomp.oacc-c++/exceptions-bad_cast-2-offload-sorry-GCN.C
 create mode 100644 
libgomp/testsuite/libgomp.oacc-c++/exceptions-bad_cast-2-offload-sorry-nvptx.C
 create mode 100644 libgomp/testsuite/libgomp.oacc-c++/exceptions-bad_cast-2.C

diff --git a/gcc/testsuite/g++.target/gcn/exceptions-bad_cast-2.C 
b/gcc/testsuite/g++.target/gcn/exceptions-bad_cast-2.C
new file mode 100644
index 000..ffe9e19a281
--- /dev/null
+++ b/gcc/testsuite/g++.target/gcn/exceptions-bad_cast-2.C
@@ -0,0 +1,12 @@
+/* 'std::bad_cast' exception, caught.  */
+
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+/* { dg-additional-options -fexceptions } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+#include 
"../../../../libgomp/testsuite/libgomp.oacc-c++/exceptions-bad_cast-2.C"
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_bad_cast, } 1 
optimized } }
+   Compilation fails:
+   { dg-regexp {[^\r\n]+: In function 'int main\(\)':[\r\n]+(?:[^\r\n]+: 
sorry, unimplemented: exception handling not supported[\r\n]+)+} }
+   (Note, using 'dg-regexp' instead of 'dg-message', as the former runs before 
the auto-mark-UNSUPPORTED.)  */
diff --git a/gcc/testsuite/g++.target/nvptx/exceptions-bad_cast-2.C 
b/gcc/testsuite/g++.target/nvptx/exceptions-bad_cast-2.C
new file mode 100644
index 000..ffe9e19a281
--- /dev/null
+++ b/gcc/testsuite/g++.target/nvptx/exceptions-bad_cast-2.C
@@ -0,0 +1,12 @@
+/* 'std::bad_cast' exception, caught.  */
+
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+/* { dg-additional-options -fexceptions } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+#include 
"../../../../libgomp/testsuite/libgomp.oacc-c++/exceptions-bad_cast-2.C"
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_bad_cast, } 1 
optimized } }
+   Compilation fails:
+   { dg-regexp {[^\r\n]+: In function 'int main\(\)':[\r\n]+(?:[^\r\n]+: 
sorry, unimplemented: exception handling not supported[\r\n]+)+} }
+   (Note, using 'dg-regexp' instead of 'dg-message', as the former runs before 
the auto-mark-UNSUPPORTED.)  */
diff --git 
a/libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-GCN.C
 
b/libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-GCN.C
new file mode 100644
index 000..ed670a80fb6
--- /dev/null
+++ 
b/libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-GCN.C
@@ -0,0 +1,18 @@
+/* 'std::bad_cast' exception in OpenMP 'target' region, caught.  */
+
+/* As this test case involves an expected offload compilation failure, we have 
to handle each offload target individually.
+   { dg-do link { target offload_target_amdgcn } }
+   { dg-additional-options -foffload=amdgcn-amdhsa } */
+/* { dg-require-effective-target exceptions }
+   { dg-additional-options -fexceptions } */
+/* { dg-additional-options -fdump-tree-optimized-raw }
+   { dg-additional-options -foffload-options=-fdump-tree-optimized-raw } */
+
+#include "target-exceptions-bad_cast-2.C"
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_bad_cast, } 1 
optimized } }
+   { dg-final { only_for_offload_target amdgcn-amdhsa 
scan-offload-tree-dump-times {gimple_call <__cxa_bad_cast, } 1 op

[PUSHED] Add test cases for exception handling constructs in dead code for GCN, nvptx target and OpenMP 'target' offloading [PR118794]

2025-04-14 Thread Thomas Schwinge
PR target/118794
gcc/testsuite/
* g++.target/gcn/exceptions-pr118794-1.C: New.
* g++.target/nvptx/exceptions-pr118794-1.C: Likewise.
libgomp/
* testsuite/libgomp.c++/target-exceptions-pr118794-1.C: New.
* 
testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-GCN.C:
Likewise.
* 
testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-nvptx.C:
Likewise.
---
 .../g++.target/gcn/exceptions-pr118794-1.C| 16 +
 .../g++.target/nvptx/exceptions-pr118794-1.C  | 16 +
 ...-exceptions-pr118794-1-offload-sorry-GCN.C | 23 
 ...xceptions-pr118794-1-offload-sorry-nvptx.C | 23 
 .../target-exceptions-pr118794-1.C| 58 +++
 5 files changed, 136 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/gcn/exceptions-pr118794-1.C
 create mode 100644 gcc/testsuite/g++.target/nvptx/exceptions-pr118794-1.C
 create mode 100644 
libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-GCN.C
 create mode 100644 
libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-nvptx.C
 create mode 100644 libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1.C

diff --git a/gcc/testsuite/g++.target/gcn/exceptions-pr118794-1.C 
b/gcc/testsuite/g++.target/gcn/exceptions-pr118794-1.C
new file mode 100644
index 000..a7013791511
--- /dev/null
+++ b/gcc/testsuite/g++.target/gcn/exceptions-pr118794-1.C
@@ -0,0 +1,16 @@
+/* Exception handling constructs in dead code.  */
+
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+/* { dg-additional-options -fexceptions } */
+/* { dg-additional-options -O0 } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+#include 
"../../../../libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1.C"
+
+/* In this specific C++ arrangement, distilled from PR118794, GCC synthesizes
+   '__builtin_eh_pointer', '__builtin_unwind_resume' calls as dead code in 'f':
+   { dg-final { scan-tree-dump-times {gimple_call <__builtin_eh_pointer, } 1 
optimized } }
+   { dg-final { scan-tree-dump-times {gimple_call <__builtin_unwind_resume, } 
1 optimized } }
+   Given '-O0', compilation fails:
+   { dg-regexp {[^\r\n]+: In function 'void f\(\)':[\r\n]+(?:[^\r\n]+: sorry, 
unimplemented: exception handling not supported[\r\n]+)+} }
+   (Note, using 'dg-regexp' instead of 'dg-message', as the former runs before 
the auto-mark-UNSUPPORTED.)  */
diff --git a/gcc/testsuite/g++.target/nvptx/exceptions-pr118794-1.C 
b/gcc/testsuite/g++.target/nvptx/exceptions-pr118794-1.C
new file mode 100644
index 000..a7013791511
--- /dev/null
+++ b/gcc/testsuite/g++.target/nvptx/exceptions-pr118794-1.C
@@ -0,0 +1,16 @@
+/* Exception handling constructs in dead code.  */
+
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+/* { dg-additional-options -fexceptions } */
+/* { dg-additional-options -O0 } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+#include 
"../../../../libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1.C"
+
+/* In this specific C++ arrangement, distilled from PR118794, GCC synthesizes
+   '__builtin_eh_pointer', '__builtin_unwind_resume' calls as dead code in 'f':
+   { dg-final { scan-tree-dump-times {gimple_call <__builtin_eh_pointer, } 1 
optimized } }
+   { dg-final { scan-tree-dump-times {gimple_call <__builtin_unwind_resume, } 
1 optimized } }
+   Given '-O0', compilation fails:
+   { dg-regexp {[^\r\n]+: In function 'void f\(\)':[\r\n]+(?:[^\r\n]+: sorry, 
unimplemented: exception handling not supported[\r\n]+)+} }
+   (Note, using 'dg-regexp' instead of 'dg-message', as the former runs before 
the auto-mark-UNSUPPORTED.)  */
diff --git 
a/libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-GCN.C
 
b/libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-GCN.C
new file mode 100644
index 000..a588016210c
--- /dev/null
+++ 
b/libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-GCN.C
@@ -0,0 +1,23 @@
+/* Exception handling constructs in dead code.  */
+
+/* As this test case involves an expected offload compilation failure, we have 
to handle each offload target individually.
+   { dg-do link { target offload_target_amdgcn } }
+   { dg-additional-options -foffload=amdgcn-amdhsa } */
+/* { dg-require-effective-target exceptions }
+   { dg-additional-options -fexceptions } */
+/* { dg-additional-options -O0 } */
+/* { dg-additional-options -fdump-tree-optimized-raw }
+   { dg-additional-options -foffload-options=-fdump-tree-optimized-raw } */
+
+#include "target-exceptions-pr118794-1.C"
+
+/* In this specific C++ arrangement, distilled from PR118794, GCC synthesizes
+   '__builtin_eh_pointer', '__builtin_unwind_resume' calls as dead code in 'f':
+   { dg-final { scan-tree-dump-times {gimple_call <__built

[COMMITTED 05/19] gccrs: typecheck: Properly select methods when dealing with specialization

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check-expr.cc (is_default_fn): New.
(emit_ambiguous_resolution_error): New.
(handle_multiple_candidates): Properly handle multiple candidates in
the case of specialization.
(TypeCheckExpr::visit): Call `handle_multiple_candidates`.

gcc/testsuite/ChangeLog:

* rust/execute/torture/min_specialization2.rs: New test.
* rust/execute/torture/min_specialization3.rs: New test.
---
 .../typecheck/rust-hir-type-check-expr.cc | 129 ++
 .../execute/torture/min_specialization2.rs|  31 +
 .../execute/torture/min_specialization3.rs|  36 +
 3 files changed, 172 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/rust/execute/torture/min_specialization2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/min_specialization3.rs

diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 791795f3b0e..b2bcac065eb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -16,6 +16,8 @@
 // along with GCC; see the file COPYING3.  If not see
 // .
 
+#include "optional.h"
+#include "rust-hir-expr.h"
 #include "rust-system.h"
 #include "rust-tyty-call.h"
 #include "rust-hir-type-check-struct-field.h"
@@ -1154,6 +1156,94 @@ TypeCheckExpr::visit (HIR::FieldAccessExpr &expr)
   infered = lookup->get_field_type ();
 }
 
+bool
+is_default_fn (const MethodCandidate &candidate)
+{
+  if (candidate.candidate.is_impl_candidate ())
+{
+  auto *item = candidate.candidate.item.impl.impl_item;
+
+  if (item->get_impl_item_type () == HIR::ImplItem::FUNCTION)
+   {
+ auto &fn = static_cast (*item);
+
+ return fn.is_default ();
+   }
+}
+
+  return false;
+}
+
+void
+emit_ambiguous_resolution_error (HIR::MethodCallExpr &expr,
+std::set &candidates)
+{
+  rich_location r (line_table, expr.get_method_name ().get_locus ());
+  std::string rich_msg = "multiple "
++ expr.get_method_name ().get_segment ().as_string ()
++ " found";
+
+  // We have to filter out default candidates
+  for (auto &c : candidates)
+if (!is_default_fn (c))
+  r.add_range (c.candidate.locus);
+
+  r.add_fixit_replace (rich_msg.c_str ());
+
+  rust_error_at (r, ErrorCode::E0592, "duplicate definitions with name %qs",
+expr.get_method_name ().get_segment ().as_string ().c_str ());
+}
+
+// We are allowed to have multiple candidates if they are all specializable
+// functions or if all of them except one are specializable functions.
+// In the later case, we just return a valid candidate without erroring out
+// about ambiguity. If there are two or more specialized functions, then we
+// error out.
+//
+// FIXME: The first case is not handled at the moment, so we error out
+tl::optional
+handle_multiple_candidates (HIR::MethodCallExpr &expr,
+   std::set &candidates)
+{
+  auto all_default = true;
+  tl::optional found = tl::nullopt;
+
+  for (auto &c : candidates)
+{
+  if (!is_default_fn (c))
+   {
+ all_default = false;
+
+ // We haven't found a final candidate yet, so we can select
+ // this one. However, if we already have a candidate, then
+ // that means there are multiple non-default candidates - we
+ // must error out
+ if (!found)
+   {
+ found = c;
+   }
+ else
+   {
+ emit_ambiguous_resolution_error (expr, candidates);
+ return tl::nullopt;
+   }
+   }
+}
+
+  // None of the candidates were a non-default (specialized) function, so we
+  // error out
+  if (all_default)
+{
+  rust_sorry_at (expr.get_locus (),
+"cannot resolve method calls to non-specialized methods "
+"(all function candidates are %qs)",
+"default");
+  return tl::nullopt;
+}
+
+  return found;
+}
+
 void
 TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
 {
@@ -1181,34 +1271,25 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
   return;
 }
 
-  if (candidates.size () > 1)
-{
-  rich_location r (line_table, expr.get_method_name ().get_locus ());
-  std::string rich_msg
-   = "multiple " + expr.get_method_name ().get_segment ().as_string ()
- + " found";
+  tl::optional candidate = *candidates.begin ();
 
-  for (auto &c : candidates)
-   r.add_range (c.candidate.locus);
+  if (candidates.size () > 1)
+candidate = handle_multiple_candidates (expr, candidates);
 
-  r.add_fixit_replace (rich_msg.c_str ());
+  if (!candidate)
+return;
 
-  rust_error_at (
-   r, ErrorCode::E0592, "duplicate definitions with name %qs",
-   expr.get_method_na

Re: [PATCH v2] RISC-V: Do not lift up vsetvl into non-transparent blocks [PR119547].

2025-04-14 Thread Zhijin Zeng
LGTM. Thank you.

Zhijin Zeng.

> From: "Robin Dapp"
> Date:  Wed, Apr 9, 2025, 20:09
> Subject:  [PATCH v2] RISC-V: Do not lift up vsetvl into non-transparent 
> blocks [PR119547].
> To: "gcc-patches"
> Cc: , , , 
> , , , 
> , "Vineet Gupta"
> Hi,

> 
> when lifting up a vsetvl into a block we currently don't consider the

> block's transparency with respect to the vsetvl as in other parts of the

> pass.  This patch does not perform the lift when transparency is not

> guaranteed.

> 
> This condition is more restrictive than necessary as we can still

> perform a vsetvl lift if the conflicting register is only every used

> in vsetvls and no regular insns but given how late we are in the GCC 15

> cycle it seems better to defer this.  Therefore

> gcc.target/riscv/rvv/vsetvl/avl_single-68.c is XFAILed for now.

> 
> This issue was found in OpenCV where it manifests as a runtime error.

> Zhijin Zeng debugged PR119547 and provided an initial patch.

> 
> V2 now uses the transparency property rather than the manual approach before, 

> both because it is cleaner and also because it helps with the go ICE

> in PR119533.

> 
> Regtested on rv64gcv_zvl512b.

> 
> Regards

>  Robin

> 
> Reported-By: 曾治金 

> 
>         PR target/119547

> 
> gcc/ChangeLog:

> 
>         * config/riscv/riscv-vsetvl.cc 
> (pre_vsetvl::earliest_fuse_vsetvl_info):

>         Do not perform lift if block is not transparent.

> 
> gcc/testsuite/ChangeLog:

> 
>         * gcc.target/riscv/rvv/vsetvl/avl_single-68.c: xfail.

>         * g++.target/riscv/rvv/autovec/pr119547.C: New test.

>         * g++.target/riscv/rvv/autovec/pr119547-2.C: New test.

>         * gcc.target/riscv/rvv/vsetvl/vlmax_switch_vtype-10.c: Adjust.

> ---

>  gcc/config/riscv/riscv-vsetvl.cc              |  12 +

>  .../g++.target/riscv/rvv/autovec/pr119547-2.C | 212 ++

>  .../g++.target/riscv/rvv/autovec/pr119547.C   |  82 +++

>  .../riscv/rvv/vsetvl/avl_single-68.c          |   8 +-

>  .../riscv/rvv/vsetvl/vlmax_switch_vtype-10.c  |   4 +-

>  5 files changed, 315 insertions(+), 3 deletions(-)

>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/autovec/pr119547-2.C

>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/autovec/pr119547.C

> 
> diff --git a/gcc/config/riscv/riscv-vsetvl.cc 
> b/gcc/config/riscv/riscv-vsetvl.cc

> index 0ac2538f596..c4046bcc345 100644

> --- a/gcc/config/riscv/riscv-vsetvl.cc

> +++ b/gcc/config/riscv/riscv-vsetvl.cc

> @@ -3022,6 +3022,18 @@ pre_vsetvl::earliest_fuse_vsetvl_info (int iter)

>                    continue;

>                  }

>  

> +              /* We cannot lift a vsetvl into the source block if the block 
> is

> +                 not transparent WRT to it.

> +                 This is too restrictive for blocks where a register's use 
> only

> +                 feeds into vsetvls and no regular insns.  One example is the

> +                 test rvv/vsetvl/avl_single-68.c which is currently XFAILed 
> for

> +                 that reason.

> +                 In order to support this case we'd need to check the 
> vsetvl's

> +                 AVL operand's uses in the source block and make sure they 
> are

> +                 only used in other vsetvls.  */

> +              if (!bitmap_bit_p (m_transp[eg->src->index], expr_index))

> +                continue;

> +

>                if (dump_file && (dump_flags & TDF_DETAILS))

>                  {

>                    fprintf (dump_file,

> diff --git a/gcc/testsuite/g++.target/riscv/rvv/autovec/pr119547-2.C 
> b/gcc/testsuite/g++.target/riscv/rvv/autovec/pr119547-2.C

> new file mode 100644

> index 000..1200ae04a27

> --- /dev/null

> +++ b/gcc/testsuite/g++.target/riscv/rvv/autovec/pr119547-2.C

> @@ -0,0 +1,212 @@

> +/* { dg-do run } */

> +/* { dg-require-effective-target riscv_v_ok } */

> +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d 
> --param=logical-op-non-short-circuit=0" } */

> +

> +#include 

> +

> +using v_uint8 = vuint8m2_t;

> +using v_int8 = vint8m2_t;

> +using v_uint16 = vuint16m2_t;

> +using v_int16 = vint16m2_t;

> +using v_uint32 = vuint32m2_t;

> +using v_int32 = vint32m2_t;

> +using v_uint64 = vuint64m2_t;

> +using v_int64 = vint64m2_t;

> +using v_float32 = vfloat32m2_t;

> +using v_float64 = vfloat64m2_t;

> +

> +using uchar = unsigned char;

> +using schar = signed char;

> +using ushort = unsigned short;

> +using uint = unsigned int;

> +using uint64 = unsigned long int;

> +using int64 = long int;

> +

> +struct Size

> +{

> +  int width;

> +  int height;

> +};

> +

> +template  struct VTraits;

> +

> +template <> struct VTraits

> +{

> +  static inline int vlanes () { return __riscv_vsetvlmax_e32m1 (); }

> +  using lane_type = int32_t;

> +  static const int max_nlanes = 1024 / 32 * 2;

> +};

> +template <> struct VTraits

> +{

> +  static inline int vlanes () { return __riscv_vsetvlmax_e32m2 (); }

> +  using lane_type = int32_t;

> +  static const int 

Re: [PATCH] [testsuite] [ppc] disable -mpowerpc64 for various ilp32 asm-out checks

2025-04-14 Thread Peter Bergner
On 4/11/25 1:05 PM, Alexandre Oliva wrote:
> Multiple tests on ilp32 get TARGET_POWERPC64 enabled by -mdejagnu-cpu
> options, but the results they expect are only attained without
> enabling it, so disable it explicitly.
[snip]
> diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c 
> b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c
> index 4f2129f136b40..87c5c084a8e4e 100644
> --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c
> +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c
> @@ -1,6 +1,6 @@
>  /* { dg-do compile { target { powerpc*-*-* } } } */
>  /* { dg-skip-if "" { has_arch_ppc64 } } */
> -/* { dg-options "-mdejagnu-cpu=power9 -mvsx" } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mvsx -mno-powerpc64" } */
>  /* { dg-require-effective-target powerpc_vsx } */

But -mcpu= should not enable -mpowerpc64 by default for -m32 compiles.
It doesn't for Linux and I highly doubt it should for powerpc-elf builds.

bergner@perch:~/$ gcc -E -dM -m32 -mcpu=power9 empty.c | grep _ARCH_PPC64
bergner@perch:~/$ gcc -E -dM -m32 -mcpu=power9 -mpowerpc64 empty.c | grep 
_ARCH_PPC64
#define _ARCH_PPC64 1
bergner@perch:~/$ gcc-powerpc-elf -E -dM -m32 -mcpu=power9 empty.c | grep 
_ARCH_PPC64
#define _ARCH_PPC64 1
bergner@perch:~/$ gcc-powerpc-elf -E -dM -m32 empty.c | grep ARCH_PPC64
bergner@perch:~/$ gcc-powerpc-elf -E -dM -m32 -mcpu=603 empty.c | grep 
ARCH_PPC64
bergner@perch:~/$ 

...but here we can see that is does, when the -mcpu=CPU has 
OPTION_MASK_POWERPC64
as one of its masks.  That looks like a bug to me.  I'm not sure why atm we 
don't
see that happening on Linux when compiling with -m32.

I think if we fix this bug, then we won't need to modify the test cases
as you're doing here.

Peter





[PUSHED/14 5/6] match: Reject non-ssa name/min invariants in gimple_extract [PR116412]

2025-04-14 Thread Andrew Pinski
After the conversion for phiopt's conditional operand
to use maybe_push_res_to_seq, it was found that gimple_extract
will extract out from REALPART_EXPR/IMAGPART_EXPR/VCE and BIT_FIELD_REF,
a memory load. But that extraction was not needed as memory loads are not
simplified in match and simplify. So gimple_extract should return false
in those cases.

Changes since v1:
* Move the rejection to gimple_extract from factor_out_conditional_operation.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/116412

gcc/ChangeLog:

* gimple-match-exports.cc (gimple_extract): Return false if op0
was not a SSA name nor a min invariant for 
REALPART_EXPR/IMAGPART_EXPR/VCE
and BIT_FIELD_REF.

gcc/testsuite/ChangeLog:

* gcc.dg/torture/pr116412-1.c: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit c7b76a076cb2c6ded7ae208464019b04cb0531a2)
---
 gcc/gimple-match-exports.cc   | 6 ++
 gcc/testsuite/gcc.dg/torture/pr116412-1.c | 6 ++
 2 files changed, 12 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr116412-1.c

diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
index 1fe6c0e3883..d81f8bc40d6 100644
--- a/gcc/gimple-match-exports.cc
+++ b/gcc/gimple-match-exports.cc
@@ -732,6 +732,9 @@ gimple_extract (gimple *stmt, gimple_match_op *res_op,
|| code == VIEW_CONVERT_EXPR)
  {
tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+   /* op0 needs to be a SSA name or an min invariant. */
+   if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant 
(op0))
+ return false;
res_op->set_op (code, type, valueize_op (op0));
return true;
  }
@@ -739,6 +742,9 @@ gimple_extract (gimple *stmt, gimple_match_op *res_op,
  {
tree rhs1 = gimple_assign_rhs1 (stmt);
tree op0 = valueize_op (TREE_OPERAND (rhs1, 0));
+   /* op0 needs to be a SSA name or an min invariant. */
+   if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant 
(op0))
+ return false;
res_op->set_op (code, type, op0,
TREE_OPERAND (rhs1, 1),
TREE_OPERAND (rhs1, 2),
diff --git a/gcc/testsuite/gcc.dg/torture/pr116412-1.c 
b/gcc/testsuite/gcc.dg/torture/pr116412-1.c
new file mode 100644
index 000..3bc26ecd8b8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116412-1.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+double f(_Complex double a, _Complex double *b, int c)
+{
+  if (c) return __real__ a;
+  return __real__ *b;
+}
-- 
2.43.0



Re: [r15-9427 Regression] FAIL: gcc.dg/ipa/pr119530.c execution test on Linux/x86_64

2025-04-14 Thread Sam James
"haochen.jiang"  writes:

> On Linux/x86_64,
>
> de1c734a8ae034c92f485e7f58b7fcb1c921ecd2 is the first bad commit
> commit de1c734a8ae034c92f485e7f58b7fcb1c921ecd2
> Author: Martin Jambor 
> Date:   Mon Apr 14 14:21:15 2025 +0200
>
> ipa-cp: Make propagation of bits in IPA-CP aware of type conversions 
> (PR119318)
>
> caused
>
> FAIL: gcc.dg/ipa/pr119530.c execution test

Fixed by r15-9459-gebdf92b6067a35.

>
> with GCC configured with
>
> ../../gcc/configure
> --prefix=/export/users/haochenj/src/gcc-bisect/master/master/r15-9427/usr
> --enable-clocale=gnu --with-system-zlib --with-demangler-in-ld
> --with-fpmath=sse --enable-languages=c,c++,fortran --enable-cet
> --without-isl --enable-libmpx x86_64-linux --disable-bootstrap
>
> To reproduce:
>
> $ cd {build_dir}/gcc && make check 
> RUNTESTFLAGS="ipa.exp=gcc.dg/ipa/pr119530.c --target_board='unix{-m32}'"
> $ cd {build_dir}/gcc && make check 
> RUNTESTFLAGS="ipa.exp=gcc.dg/ipa/pr119530.c --target_board='unix{-m32\ 
> -march=cascadelake}'"
>
> (Please do not reply to this email, for question about this report, contact 
> me at haochen dot jiang at intel.com.)
> (If you met problems with cascadelake related, disabling AVX512F in command 
> line might save that.)
> (However, please make sure that there is no potential problems with AVX512.)


RE: [PATCH] libgcobol, v2: Handle long double as an alternate IEEE754 128b

2025-04-14 Thread Robert Dubner
I applied this patch.  It works on my local systems, and it passes the
cobolworx CI/CD pipelines.

It is okay for trunk.

> -Original Message-
> From: Jakub Jelinek 
> Sent: Thursday, April 10, 2025 12:37
> To: Rainer Orth 
> Cc: Iain Sandoe ; gcc-patches@gcc.gnu.org;
> i...@sandoe.co.uk; jklow...@cobolworx.com; rdub...@symas.com
> Subject: [PATCH] libgcobol, v2: Handle long double as an alternate
IEEE754
> 128b
> 
> On Wed, Apr 09, 2025 at 02:22:16PM +0200, Rainer Orth wrote:
> > > Here is what I'm testing as an incremental fix, so far OK on x86_64-
> darwin
> > > and powerpcle64 (GLIBC 2.34) .. others in progress.  Does it help
the
> > > Solaris cases?
> >
> > I'll give it a try.  Here's what I have (I believe it's more readable
in
> > some cases), but as I said something's not right yet (probably
something
> > very stupid).
> 
> Yes, most importantly
> 
> >  #if !defined (HAVE_STRFROMF128)
> > -# if !USE_QUADMATH
> > +static int
> > +strfromf128 (char *s, size_t n, const char *f, long double v)
> 
> this long double should have been GCOB_FP128.
> 
> Anyway, I think there should be consistency in what we use, so like
> libgcobol-fp.h specifies, IEEE quad long double should have highest
> priority, then _Float128 with *f128 APIs, then libquadmath.
> And when we decide to use say long double, we shouldn't mix that with
> strfromf128/strtof128.
> 
> Additionally, given that the *l vs. *f128 vs. *q API decision is done
> solely in libgcobol and not in the compiler (which is different from
> the Fortran case where compiled code emits say sinq or sinf128 calls),
> I think libgcobol.spec should only have -lquadmath in any form only in
> the case when using libquadmath for everything.  In the Fortran case
> it is for backwards compatibility purposes, if something has been
> compiled with older gfortran which used say sinq and link is done by
> gfortran which has been configured against new glibc with *f128, linking
> would fail otherwise.
> 
> So, here is an updated patch based on your patch, so far briefly
> tested on x86_64 with recent glibc (i.e. with the *f128 APIs).
> 
> 2025-04-10  Jakub Jelinek  
>   Rainer Orth  
> 
>   PR cobol/119244
>   * acinclude.m4 (LIBGCOBOL_CHECK_FLOAT128): Ensure
>   libgcob_cv_have_float128 is not yes on targets with IEEE quad
>   long double.  Don't check for --as-needed nor set LIBQUADSPEC
>   on targets which USE_IEC_60559.
>   * libgcobol-fp.h (FP128_FMT, strtofp128, strfromfp128): Define.
>   * intrinsic.cc (strtof128): Don't redefine.
>   (WEIRD_TRANSCENDENT_RETURN_VALUE): Use GCOB_FP128_LITERAL macro.
>   (__gg__numval_f): Use strtofp128 instead of strtof128.
>   * libgcobol.cc (strtof128): Don't redefine.
>   (format_for_display_internal): Use strfromfp128 instead of
>   strfromf128 or quadmath_snprintf and use FP128_FMT in the format
>   string.
>   (get_float128, __gg__compare_2, __gg__move, __gg__move_literala):
>   Use strtofp128 instead of strtof128.
>   * configure: Regenerate.
> 
> --- libgcobol/acinclude.m4.jj 2025-04-10 17:14:36.535278015 +0200
> +++ libgcobol/acinclude.m42025-04-10 17:33:56.012347476 +0200
> @@ -44,6 +44,10 @@ AC_DEFUN([LIBGCOBOL_CHECK_FLOAT128], [
>AC_CACHE_CHECK([whether we have a usable _Float128 type],
>   libgcob_cv_have_float128, [
> GCC_TRY_COMPILE_OR_LINK([
> +#if __LDBL_MANT_DIG__ == 113 && __LDBL_MIN_EXP__ == -16381
> +#error "long double is IEEE quad, no need for libquadmath"
> +#endif
> +
>  _Float128 foo (_Float128 x)
>  {
>   _Complex _Float128 z1, z2;
> @@ -90,32 +94,22 @@ AC_DEFUN([LIBGCOBOL_CHECK_FLOAT128], [
>  fi
>  AC_DEFINE(HAVE_FLOAT128, 1, [Define if target has usable _Float128
> and __float128 types.])
> 
> -dnl Check whether -Wl,--as-needed resp. -Wl,-zignore is supported
> -dnl
> -dnl Turn warnings into error to avoid testsuite breakage.  So
enable
> -dnl AC_LANG_WERROR, but there's currently (autoconf 2.64) no way to
> turn
> -dnl it off again.  As a workaround, save and restore werror flag
like
> -dnl AC_PATH_XTRA.
> -dnl Cf. http://gcc.gnu.org/ml/gcc-patches/2010-05/msg01889.html
> -
>
ac_xsave_[]_AC_LANG_ABBREV[]_werror_flag=$ac_[]_AC_LANG_ABBREV[]_werror_fl
> ag
> -AC_CACHE_CHECK([whether --as-needed/-z ignore works],
> -  [libgcob_cv_have_as_needed],
> -  [
> -  # Test for native Solaris options first.
> -  # No whitespace after -z to pass it through -Wl.
> -  libgcob_cv_as_needed_option="-zignore"
> -  libgcob_cv_no_as_needed_option="-zrecord"
> -  save_LDFLAGS="$LDFLAGS"
> -  LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -
> Wl,$libgcob_cv_no_as_needed_option"
> -  libgcob_cv_have_as_needed=no
> -  AC_LANG_WERROR
> -  AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
> -  [libgcob_cv_have_as_needed=yes],
> -  [libgcob_cv_have_as_needed=no])
> -  LDFLAGS="$save_LDFLAGS"
> - 

[PATCH] c++: prev declared hidden tmpl friend inst, cont [PR119807]

2025-04-14 Thread Patrick Palka
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
look OK for trunk and later 14?

-- >8 --

When remapping existing specializations of a hidden template friend from
a previous declaration to the new definition, we must remap only those
specializations that match this new definition, but currently we
remap all specializations since they're all contained in the
DECL_TEMPLATE_INSTANTIATIONS list of the most general template of f.

Concretely, in the first testcase below, we form two specializations of
the friend A::f, one with arguments {{0},{bool}} and another with
arguments {{1},{bool}}.  Later when instantiating B, we need to remap
these specializations.  During the B<0> instantiation we only want to
remap the first specialization, and during the B<1> instantiation only
the second specialization, but currently we remap both specializations
twice.

tsubst_friend_function needs to determine if an existing specialization
matches the shape of the new definition, which is tricky in general,
e.g.  the outer template parameters may not match up.  Fortunately we
don't have to reinvent the wheel here since is_specialization_of_friend
seems to do exactly what we need.  We can check this unconditionally,
but I think it's only necessary when dealing with existing
specializations formed from a class template scope previous declaration,
hence TMPL_ARGS_HAVE_MULTIPLE_LEVELS check.

PR c++/119807
PR c++/112288

gcc/cp/ChangeLog:

* pt.cc (tsubst_friend_function): Skip remapping an
existing specialization if it doesn't match the shape of
the new friend definition.

gcc/testsuite/ChangeLog:

* g++.dg/template/friend86.C: New test.
* g++.dg/template/friend87.C: New test.
---
 gcc/cp/pt.cc |  4 +++
 gcc/testsuite/g++.dg/template/friend86.C | 25 ++
 gcc/testsuite/g++.dg/template/friend87.C | 42 
 3 files changed, 71 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/template/friend86.C
 create mode 100644 gcc/testsuite/g++.dg/template/friend87.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b7060b4c5aa6..4349b19119b7 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11772,6 +11772,10 @@ tsubst_friend_function (tree decl, tree args)
  elt.args = DECL_TI_ARGS (spec);
  elt.spec = NULL_TREE;
 
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (DECL_TI_ARGS (spec))
+ && !is_specialization_of_friend (spec, new_template))
+   continue;
+
  decl_specializations->remove_elt (&elt);
 
  tree& spec_args = DECL_TI_ARGS (spec);
diff --git a/gcc/testsuite/g++.dg/template/friend86.C 
b/gcc/testsuite/g++.dg/template/friend86.C
new file mode 100644
index ..9e2c1afb351c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend86.C
@@ -0,0 +1,25 @@
+// PR c++/119807
+// { dg-do run }
+
+template
+struct A {
+  template friend int f(A, T);
+};
+
+template struct A<0>;
+template struct A<1>;
+
+int main() {
+  A<0> x;
+  A<1> y;
+  if (f(x, true) != 0) __builtin_abort();
+  if (f(y, true) != 1) __builtin_abort();
+}
+
+template
+struct B {
+  template friend int f(A, T) { return N; }
+};
+
+template struct B<0>;
+template struct B<1>;
diff --git a/gcc/testsuite/g++.dg/template/friend87.C 
b/gcc/testsuite/g++.dg/template/friend87.C
new file mode 100644
index ..94c0dfc52924
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend87.C
@@ -0,0 +1,42 @@
+// PR c++/119807
+// { dg-do compile { target c++20 } }
+
+using size_t = decltype(sizeof(0));
+
+template
+struct CounterReader {
+   template
+   friend auto counterFlag(CounterReader) noexcept;
+};
+
+template
+struct CounterWriter {
+   static constexpr size_t value = current;
+
+   template
+   friend auto counterFlag(CounterReader) noexcept {}
+};
+
+template
+[[nodiscard]] constexpr size_t counterAdvance() noexcept {
+   if constexpr (!mask) {
+   return CounterWriter::value;
+   } else if constexpr (requires { counterFlag(CounterReader()); }) {
+   return counterAdvance> 
1)>();
+   } 
+   else {
+   return counterAdvance> 1)>();
+   }
+}
+
+constexpr auto defaultCounterTag = [] {};
+
+template
+constexpr size_t counter() noexcept {
+   return counterAdvance();
+}
+
+int main() {
+   static_assert(counter() == 1);
+   static_assert(counter() == 2);
+}
-- 
2.49.0.221.g485f5f8636



Re: [PATCH] APX: Don't use red-zone with APX and no caller-saved registers

2025-04-14 Thread Hongtao Liu
On Mon, Apr 14, 2025 at 8:56 PM H.J. Lu  wrote:
>
> On Mon, Apr 14, 2025 at 2:39 AM Uros Bizjak  wrote:
> >
> > On Mon, Apr 14, 2025 at 8:54 AM Hongtao Liu  wrote:
> > >
> > > On Mon, Apr 14, 2025 at 7:36 AM H.J. Lu  wrote:
> > > >
> > > > Don't use red-zone when there are no caller-saved registers and APX is
> > > > enabled since 128-byte red-zone is too small for 31 GPRs.
> > > >
> > > > gcc/
> > > >
> > > > PR target/119784
> > > > * config/i386/i386.cc (ix86_using_red_zone): Don't use red-zone
> > > > with APX and no caller-saved registers.
> > > >
> > > > gcc/testsuite/
> > > >
> > > > PR target/119784
> > > > * gcc.target/i386/pr119784a.c: New test.
> > > > * gcc.target/i386/pr119784b.c: Likewise.
> > > >
> > > > Signed-off-by: H.J. Lu 
> > > > ---
> > > >  gcc/config/i386/i386.cc   |  6 ++
> > > >  gcc/testsuite/gcc.target/i386/pr119784a.c | 96 +++
> > > >  gcc/testsuite/gcc.target/i386/pr119784b.c | 87 
> > > >  3 files changed, 189 insertions(+)
> > > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr119784a.c
> > > >  create mode 100644 gcc/testsuite/gcc.target/i386/pr119784b.c
> > > >
> > > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> > > > index 4f8380c4a58..91af239d484 100644
> > > > --- a/gcc/config/i386/i386.cc
> > > > +++ b/gcc/config/i386/i386.cc
> > > > @@ -458,6 +458,9 @@ int ix86_arch_specified;
> > > > indirect thunk pushes the return address onto stack, destroying
> > > > red-zone.
> > > >
> > > > +   NB: Don't use red-zone for functions with no_caller_saved_registers
> > > > +   when APX is enabled since 128-byte red-zone is too small for 31 
> > > > GPRs.
> > > > +
> > > > TODO: If we can reserve the first 2 WORDs, for PUSH and, another
> > > > for CALL, in red-zone, we can allow local indirect jumps with
> > > > indirect thunk.  */
> > > > @@ -467,6 +470,9 @@ ix86_using_red_zone (void)
> > > >  {
> > > >return (TARGET_RED_ZONE
> > > >   && !TARGET_64BIT_MS_ABI
> > > > + && (!TARGET_APX_F
> > > Could we use !TARGET_APX_EGPR, it's more clear.
>
> Fixed.Here is the patch I am checking in.   OK for backport to
> release branches?
Sure.
>
> Thanks.
>
> > > Others LGTM, but please wait for a while in case Uros has a different 
> > > opinion.
> >
> > LGTM too.
> >
> > Thanks,
> > Uros.
> >
> > > > + || (cfun->machine->call_saved_registers
> > > > + != TYPE_NO_CALLER_SAVED_REGISTERS))
> > > >   && (!cfun->machine->has_local_indirect_jump
> > > >   || cfun->machine->indirect_branch_type == 
> > > > indirect_branch_keep));
> > > >  }
> > > > diff --git a/gcc/testsuite/gcc.target/i386/pr119784a.c 
> > > > b/gcc/testsuite/gcc.target/i386/pr119784a.c
> > > > new file mode 100644
> > > > index 000..8a119d4cc1f
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.target/i386/pr119784a.c
> > > > @@ -0,0 +1,96 @@
> > > > +/* { dg-do compile { target { *-*-linux* && lp64 } } } */
> > > > +/* { dg-options "-O2 -fno-pic -mtune=generic -mgeneral-regs-only 
> > > > -mapxf -mtune-ctrl=prologue_using_move,epilogue_using_move" } */
> > > > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > > > +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } 
> > > > {^\t?\.}  } } */
> > > > +
> > > > +/* start must save and restore all caller saved registers.  */
> > > > +
> > > > +/*
> > > > +**start:
> > > > +**.LFB[0-9]+:
> > > > +** .cfi_startproc
> > > > +** subq\$248, %rsp
> > > > +**...
> > > > +** movq%rax, \(%rsp\)
> > > > +** movq%rdx, 8\(%rsp\)
> > > > +** movq%rcx, 16\(%rsp\)
> > > > +** movq%rbx, 24\(%rsp\)
> > > > +** movq%rsi, 32\(%rsp\)
> > > > +** movq%rdi, 40\(%rsp\)
> > > > +**...
> > > > +** movq%rbp, 48\(%rsp\)
> > > > +** movq%r8, 56\(%rsp\)
> > > > +** movq%r9, 64\(%rsp\)
> > > > +** movq%r10, 72\(%rsp\)
> > > > +** movq%r11, 80\(%rsp\)
> > > > +** movq%r12, 88\(%rsp\)
> > > > +** movq%r13, 96\(%rsp\)
> > > > +** movq%r14, 104\(%rsp\)
> > > > +** movq%r15, 112\(%rsp\)
> > > > +** movq%r16, 120\(%rsp\)
> > > > +** movq%r17, 128\(%rsp\)
> > > > +** movq%r18, 136\(%rsp\)
> > > > +** movq%r19, 144\(%rsp\)
> > > > +** movq%r20, 152\(%rsp\)
> > > > +** movq%r21, 160\(%rsp\)
> > > > +** movq%r22, 168\(%rsp\)
> > > > +** movq%r23, 176\(%rsp\)
> > > > +** movq%r24, 184\(%rsp\)
> > > > +** movq%r25, 192\(%rsp\)
> > > > +** movq%r26, 200\(%rsp\)
> > > > +** movq%r27, 208\(%rsp\)
> > > > +** movq%r28, 216\(%rsp\)
> > > > +** movq%r29, 224\(%rsp\)
> > > > +** movq%r30, 232\(%rsp\)
> > > > +** movq%r31, 240\(%rsp\)
> > > > +**...
> > > > +** call\*code\(%rip\)
> > > > +** movq

[COMMITTED] Doc: clarify -march=pentiumpro has no MMX support [PR42683]

2025-04-14 Thread Sandra Loosemore
gcc/ChangeLog
PR target/42683
* doc/invoke.texi (x86 Options): Clarify that -march=pentiumpro
doesn't include MMX.
---
 gcc/doc/invoke.texi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 67155eeeda7..1f7657b72b7 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -34872,7 +34872,7 @@ Intel Lakemont MCU, based on Intel Pentium CPU.
 Intel Pentium MMX CPU, based on Pentium core with MMX instruction set support.
 
 @item pentiumpro
-Intel Pentium Pro CPU@.
+Intel Pentium Pro CPU with no MMX support.
 
 @item i686
 When used with @option{-march}, the Pentium Pro
-- 
2.34.1



Re: RISC-V: revert pr114194 tests on gcc-14 [PR118601]

2025-04-14 Thread Kito Cheng
LGTM, thanks :)

Alexandre Oliva  於 2025年4月15日 週二 12:25 寫道:

>
> And here's another that came up more recently:
>
> The gcc-14 backport that split the pr114194 testcase for rv32 and rv64
> would only generate the expected rv32 sequence if commit
> 6b315907c0353f71169a7555e653d29a981fef67 had also been backported, but
> it wasn't.  Without it, we get the same code as before on both rv32
> and rv64, so revert to the original test.
>
> Also tested on riscv64-elf and riscv32-elf on x86_64-linux-gnu.
> Ok for gcc-14?
>
>
> for  gcc/testsuite/ChangeLog
>
> PR target/118601
> * gcc.target/riscv/rvv/xtheadvector/pr114194.c: Restore.
> * gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c: Remove.
> * gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c: Likewise.
> ---
>  .../riscv/rvv/xtheadvector/pr114194-rv32.c |   51
> --
>  .../riscv/rvv/xtheadvector/pr114194-rv64.c |   55
> 
>  .../gcc.target/riscv/rvv/xtheadvector/pr114194.c   |   56
> 
>  3 files changed, 56 insertions(+), 106 deletions(-)
>  delete mode 100644
> gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c
>  delete mode 100644
> gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c
>  create mode 100644
> gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194.c
>
> diff --git
> a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c
> b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c
> deleted file mode 100644
> index 0bee5ec33de83..0
> --- a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c
> +++ /dev/null
> @@ -1,51 +0,0 @@
> -/* { dg-do compile { target rv32 } } */
> -/* { dg-options "-march=rv32gc_xtheadvector -O2" } */
> -/* { dg-final { check-function-bodies "**" "" } } */
> -
> -/*
> -** foo0_1:
> -** sb\tzero,0\([a-x0-9]+\)
> -** ret
> -*/
> -void foo0_1 (void *p)
> -{
> -  __builtin_memset (p, 0, 1);
> -}
> -
> -/*
> -** foo0_7:
> -** li\t[a-x0-9]+,7
> -** th.vsetvli\tzero,[a-x0-9]+,e8,m1
> -** th\.vmv\.v\.i\tv[0-9],0
> -** th\.vse\.v\tv[0-9]+,0\([a-x0-9]+\)
> -** ret
> -*/
> -void foo0_7 (void *p)
> -{
> -  __builtin_memset (p, 0, 7);
> -}
> -
> -/*
> -** foo1_1:
> -** li\t[a-x0-9]+,1
> -** sb\t[a-x0-9]+,0\([a-x0-9]+\)
> -** ret
> -*/
> -void foo1_1 (void *p)
> -{
> -  __builtin_memset (p, 1, 1);
> -}
> -
> -/*
> -** foo1_5:
> -** li\t[a-x0-9]+,5
> -** th.vsetvli\tzero,[a-x0-9]+,e8,m1
> -** th\.vmv\.v\.i\tv[0-9],1
> -** th\.vse\.v\tv[0-9]+,0\([a-x0-9]+\)
> -** ret
> -*/
> -
> -void foo1_5 (void *p)
> -{
> -  __builtin_memset (p, 1, 5);
> -}
> diff --git
> a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c
> b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c
> deleted file mode 100644
> index 84333c1cf5a7c..0
> --- a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c
> +++ /dev/null
> @@ -1,55 +0,0 @@
> -/* { dg-do compile { target rv64 } } */
> -/* { dg-options "-march=rv64gc_xtheadvector -O2" } */
> -/* { dg-final { check-function-bodies "**" "" } } */
> -
> -/*
> -** foo0_1:
> -** sb\tzero,0\([a-x0-9]+\)
> -** ret
> -*/
> -void foo0_1 (void *p)
> -{
> -  __builtin_memset (p, 0, 1);
> -}
> -
> -/*
> -** foo0_7:
> -** sb\tzero,0\([a-x0-9]+\)
> -** sb\tzero,1\([a-x0-9]+\)
> -** sb\tzero,2\([a-x0-9]+\)
> -** sb\tzero,3\([a-x0-9]+\)
> -** sb\tzero,4\([a-x0-9]+\)
> -** sb\tzero,5\([a-x0-9]+\)
> -** sb\tzero,6\([a-x0-9]+\)
> -** ret
> -*/
> -void foo0_7 (void *p)
> -{
> -  __builtin_memset (p, 0, 7);
> -}
> -
> -/*
> -** foo1_1:
> -** li\t[a-x0-9]+,1
> -** sb\t[a-x0-9]+,0\([a-x0-9]+\)
> -** ret
> -*/
> -void foo1_1 (void *p)
> -{
> -  __builtin_memset (p, 1, 1);
> -}
> -
> -/*
> -** foo1_5:
> -** li\t[a-x0-9]+,1
> -** sb\t[a-x0-9]+,0\([a-x0-9]+\)
> -** sb\t[a-x0-9]+,1\([a-x0-9]+\)
> -** sb\t[a-x0-9]+,2\([a-x0-9]+\)
> -** sb\t[a-x0-9]+,3\([a-x0-9]+\)
> -** sb\t[a-x0-9]+,4\([a-x0-9]+\)
> -** ret
> -*/
> -void foo1_5 (void *p)
> -{
> -  __builtin_memset (p, 1, 5);
> -}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194.c
> b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194.c
> new file mode 100644
> index 0..2e53a7ecc3e71
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194.c
> @@ -0,0 +1,56 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv32gc_xtheadvector -O2" { target { rv32 } } } */
> +/* { dg-options "-march=rv64gc_xtheadvector -O2" { target { rv64 } } } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +/*
> +** foo0_1:
> +** sb\tzero,0\([a-x0-9]+\)
> +** ret
> +*/
> +void foo0_1 (void *p)
> +{
> +  __builtin_memset (p, 0, 1);
> +}
> +
> +/*
> +** foo0_7:
> +** sb\tzero,0\([a-x0-9]+\)
> +** sb\tzero,1\([a-x0-9]+\)
> +** sb\tzero,2\([a-x0-9]+\)
> +** sb\tzero,3\

Re: [PATCH] RISC-V: Minimal support for ssnpm, smnpm and smmpm extensions.

2025-04-14 Thread chendongyan

This patch support ssnpm, smnpm, smmpm, sspm and supm extensions[1].
To enable GCC to recognize and process ssnpm, smnpm, smmpm, sspm and 
supm extensions correctly at compile time.


[1] 
https://github.com/riscv/riscv-j-extension/blob/master/zjpm/instructions.adoc


Changes for v2:
- Add the sspm and supm extensions.
- Add the check_conflict_ext function to check the compatibility of 
ssnpm, smnpm, smmpm, sspm and supm extensions.

- Add the test cases for ssnpm, smnpm, smmpm, sspm and supm extensions.

gcc/ChangeLog:

    * common/config/riscv/riscv-common.cc 
(riscv_subset_list::check_conflict_ext): New extension.

    * config/riscv/riscv.opt: Ditto.

gcc/testsuite/ChangeLog:

    * gcc.target/riscv/arch-45.c: New test.
    * gcc.target/riscv/arch-46.c: New test.

---
 gcc/common/config/riscv/riscv-common.cc  | 36 
 gcc/config/riscv/riscv.opt   | 19 +
 gcc/testsuite/gcc.target/riscv/arch-45.c |  5 
 gcc/testsuite/gcc.target/riscv/arch-46.c | 10 +++
 4 files changed, 70 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-45.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-46.c

diff --git a/gcc/common/config/riscv/riscv-common.cc 
b/gcc/common/config/riscv/riscv-common.cc

index b34409adf39c..33b2b3c5a191 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -227,6 +227,10 @@ static const riscv_implied_info_t 
riscv_implied_info[] =

   {"ssstateen", "zicsr"},
   {"sstc", "zicsr"},

+  {"ssnpm", "zicsr"},
+  {"smnpm", "zicsr"},
+  {"smmpm", "zicsr"},
+
   {"xsfvcp", "zve32x"},

   {NULL, NULL}
@@ -409,6 +413,12 @@ static const struct riscv_ext_version 
riscv_ext_version_table[] =

   {"ssstateen", ISA_SPEC_CLASS_NONE, 1, 0},
   {"sstc",  ISA_SPEC_CLASS_NONE, 1, 0},

+  {"ssnpm", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"smnpm", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"smmpm", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"sspm",  ISA_SPEC_CLASS_NONE, 1, 0},
+  {"supm",  ISA_SPEC_CLASS_NONE, 1, 0},
+
   {"svinval", ISA_SPEC_CLASS_NONE, 1, 0},
   {"svnapot", ISA_SPEC_CLASS_NONE, 1, 0},
   {"svpbmt",  ISA_SPEC_CLASS_NONE, 1, 0},
@@ -1309,6 +1319,26 @@ riscv_subset_list::check_conflict_ext ()
 error_at (m_loc, "%<-march=%s%>: zcf extension supports in rv32 only",
   m_arch);

+  if (lookup ("ssnpm") && m_xlen == 32)
+    error_at (m_loc, "%<-march=%s%>: ssnpm extension supports in rv64 
only",

+  m_arch);
+
+  if (lookup ("smnpm") && m_xlen == 32)
+    error_at (m_loc, "%<-march=%s%>: smnpm extension supports in rv64 
only",

+  m_arch);
+
+  if (lookup ("smmpm") && m_xlen == 32)
+    error_at (m_loc, "%<-march=%s%>: smmpm extension supports in rv64 
only",

+  m_arch);
+
+  if (lookup ("sspm") && m_xlen == 32)
+    error_at (m_loc, "%<-march=%s%>: sspm extension supports in rv64 only",
+  m_arch);
+
+  if (lookup ("supm") && m_xlen == 32)
+    error_at (m_loc, "%<-march=%s%>: supm extension supports in rv64 only",
+  m_arch);
+
   if (lookup ("zfinx") && lookup ("f"))
 error_at (m_loc,
   "%<-march=%s%>: z*inx conflicts with floating-point "
@@ -1736,6 +1766,12 @@ static const riscv_ext_flag_table_t 
riscv_ext_flag_table[] =

   RISCV_EXT_FLAG_ENTRY ("svnapot", x_riscv_sv_subext, MASK_SVNAPOT),
   RISCV_EXT_FLAG_ENTRY ("svvptc", x_riscv_sv_subext, MASK_SVVPTC),

+  RISCV_EXT_FLAG_ENTRY ("ssnpm", x_riscv_ss_subext, MASK_SSNPM),
+  RISCV_EXT_FLAG_ENTRY ("smnpm", x_riscv_sm_subext, MASK_SMNPM),
+  RISCV_EXT_FLAG_ENTRY ("smmpm", x_riscv_sm_subext, MASK_SMMPM),
+  RISCV_EXT_FLAG_ENTRY ("sspm",  x_riscv_ss_subext, MASK_SSPM),
+  RISCV_EXT_FLAG_ENTRY ("supm",  x_riscv_su_subext, MASK_SUPM),
+
   RISCV_EXT_FLAG_ENTRY ("ztso", x_riscv_ztso_subext, MASK_ZTSO),

   RISCV_EXT_FLAG_ENTRY ("xcvmac",  x_riscv_xcv_subext, MASK_XCVMAC),
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 7515c8ea13dd..cec866350b64 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -472,6 +472,25 @@ Mask(SVNAPOT) Var(riscv_sv_subext)

 Mask(SVVPTC) Var(riscv_sv_subext)

+TargetVariable
+int riscv_ss_subext
+
+Mask(SSNPM) Var(riscv_ss_subext)
+
+Mask(SSPM) Var(riscv_ss_subext)
+
+TargetVariable
+int riscv_sm_subext
+
+Mask(SMNPM) Var(riscv_sm_subext)
+
+Mask(SMMPM) Var(riscv_sm_subext)
+
+TargetVariable
+int riscv_su_subext
+
+Mask(SUPM) Var(riscv_su_subext)
+
 TargetVariable
 int riscv_ztso_subext

diff --git a/gcc/testsuite/gcc.target/riscv/arch-45.c 
b/gcc/testsuite/gcc.target/riscv/arch-45.c

new file mode 100644
index ..8f95737b248f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-45.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_ssnpm_smnpm_smmpm_sspm_supm -mabi=lp64" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-46.c 
b/gcc/testsuite/gcc.target/riscv/arch-46.c

new file mode 100644
index ..fb2bdf72597f
--- /dev/null
+

Re: [PATCH] c++: Prune lambda captures from more places [PR119755]

2025-04-14 Thread Nathaniel Shead
On Mon, Apr 14, 2025 at 05:33:05PM -0400, Jason Merrill wrote:
> On 4/13/25 6:32 AM, Nathaniel Shead wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> > 
> > -- >8 --
> > 
> > Currently, pruned lambda captures are still leftover in the function's
> > BLOCK and topmost BIND_EXPR; this doesn't cause any issues for normal
> > compilation, but does break modules streaming as we try to reconstruct a
> > FIELD_DECL that no longer exists on the type itself.
> > 
> > PR c++/119755
> > 
> > gcc/cp/ChangeLog:
> > 
> > * lambda.cc (prune_lambda_captures): Remove pruned capture from
> > function's BLOCK_VARS and BIND_EXPR_VARS.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/modules/lambda-10_a.H: New test.
> > * g++.dg/modules/lambda-10_b.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >   gcc/cp/lambda.cc   | 22 ++
> >   gcc/testsuite/g++.dg/modules/lambda-10_a.H | 17 +
> >   gcc/testsuite/g++.dg/modules/lambda-10_b.C |  7 +++
> >   3 files changed, 46 insertions(+)
> >   create mode 100644 gcc/testsuite/g++.dg/modules/lambda-10_a.H
> >   create mode 100644 gcc/testsuite/g++.dg/modules/lambda-10_b.C
> > 
> > diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
> > index f0a54b60275..d01bb04cd32 100644
> > --- a/gcc/cp/lambda.cc
> > +++ b/gcc/cp/lambda.cc
> > @@ -1858,6 +1858,14 @@ prune_lambda_captures (tree body)
> > cp_walk_tree_without_duplicates (&body, mark_const_cap_r, &const_vars);
> > +  tree bind_expr = expr_single (DECL_SAVED_TREE (lambda_function (lam)));
> > +  gcc_assert (bind_expr
> > + && (TREE_CODE (bind_expr) == BIND_EXPR
> > + /* FIXME: In a noexcept lambda we never prune captures
> > +(PR119764); when we do we need to handle this case
> > +for modules streaming.  */
> 
> The attached patch seems to fix that, with the result that your patch
> crashes.
> 

Thanks.  And yup, crashing was deliberate here as I wasn't 100% sure
what the tree would look like for this case after an appropriate fix.

One quick question about your patch, since it could in theory affect ABI
(the size of the lambdas change) should the pruning of such lambdas be
dependent on an ABI version check?

Otherwise here's an updated patch that relies on your patch.
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk along
with yours?  (Or if the potential ABI concerns mean that your change
isn't appropriate for GCC15, would the old version of my patch still be
OK for GCC15 to get 'import std' working again for C++26?)

-- >8 --

Currently, pruned lambda captures are still leftover in the function's
BLOCK and topmost BIND_EXPR; this doesn't cause any issues for normal
compilation, but does break modules streaming as we try to reconstruct a
FIELD_DECL that no longer exists on the type itself.

PR c++/119755

gcc/cp/ChangeLog:

* lambda.cc (prune_lambda_captures): Remove pruned capture from
function's BLOCK_VARS and BIND_EXPR_VARS.

gcc/testsuite/ChangeLog:

* g++.dg/modules/lambda-10_a.H: New test.
* g++.dg/modules/lambda-10_b.C: New test.

Signed-off-by: Nathaniel Shead 
Reviewed-by: Jason Merrill 
---
 gcc/cp/lambda.cc   | 19 +++
 gcc/testsuite/g++.dg/modules/lambda-10_a.H | 17 +
 gcc/testsuite/g++.dg/modules/lambda-10_b.C |  7 +++
 3 files changed, 43 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/modules/lambda-10_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/lambda-10_b.C

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index c6308b941d3..7bb88a900d5 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -1862,6 +1862,11 @@ prune_lambda_captures (tree body)
 
   cp_walk_tree_without_duplicates (&body, mark_const_cap_r, &const_vars);
 
+  tree bind_expr = expr_single (DECL_SAVED_TREE (lambda_function (lam)));
+  if (bind_expr && TREE_CODE (bind_expr) == MUST_NOT_THROW_EXPR)
+bind_expr = expr_single (TREE_OPERAND (bind_expr, 0));
+  gcc_assert (bind_expr && TREE_CODE (bind_expr) == BIND_EXPR);
+
   tree *fieldp = &TYPE_FIELDS (LAMBDA_EXPR_CLOSURE (lam));
   for (tree *capp = &LAMBDA_EXPR_CAPTURE_LIST (lam); *capp; )
 {
@@ -1883,6 +1888,20 @@ prune_lambda_captures (tree body)
fieldp = &DECL_CHAIN (*fieldp);
  *fieldp = DECL_CHAIN (*fieldp);
 
+ /* And out of the bindings for the function.  */
+ tree *blockp = &BLOCK_VARS (current_binding_level->blocks);
+ while (*blockp != DECL_EXPR_DECL (**use))
+   blockp = &DECL_CHAIN (*blockp);
+ *blockp = DECL_CHAIN (*blockp);
+
+ /* And maybe out of the vars declared in the containing
+BIND_EXPR, if it's listed there.  */
+ tree *bindp = &BIND_EXPR_VARS (bind_expr);
+ while (*bindp && *bindp != DECL_EXPR_DECL (**use))
+   bindp = &

[pushed] c++: shortcut constexpr vector ctor [PR113835]

2025-04-14 Thread Jason Merrill
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Since std::vector became usable in constant evaluation in C++20, a vector
variable with static storage duration might be manifestly
constant-evaluated, so we properly try to constant-evaluate its initializer.
But it can never succeed since the result will always refer to the result of
operator new, so trying is a waste of time.  Potentially a large waste of
time for a large vector, as in the testcase in the PR.

So, let's recognize this case and skip trying constant-evaluation.  I do
this only for the case of an integer argument, as that's the case that's
easy to write but slow to (fail to) evaluate.

In the test, I use dg-timeout-factor to lower the default timeout from 300
seconds to 15; on my laptop, compilation without the patch takes about 20
seconds versus about 2 with the patch.

PR c++/113835

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_outermost_constant_expr): Bail out early
for std::vector(N).

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constexpr-vector1.C: New test.
---
 gcc/cp/constexpr.cc| 9 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C | 8 
 2 files changed, 17 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 7e375823d64..dc59f59aa3f 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9127,6 +9127,15 @@ cxx_eval_outermost_constant_expr (tree t, bool 
allow_non_constant,
   tree fndecl = cp_get_callee_fndecl_nofold (x);
   if (fndecl && DECL_IMMEDIATE_FUNCTION_P (fndecl))
is_consteval = true;
+  /* Don't try to evaluate a std::vector constructor taking an integer, it
+will fail in the 'if (heap_var)' block below after doing all the work
+(c++/113835).  This will need adjustment if P3554 is accepted.  Note
+that evaluation of e.g. the vector default constructor can succeed, so
+we don't shortcut all vector constructors.  */
+  if (fndecl && DECL_CONSTRUCTOR_P (fndecl) && allow_non_constant
+ && is_std_class (type, "vector") && call_expr_nargs (x) > 1
+ && TREE_CODE (TREE_TYPE (get_nth_callarg (x, 1))) == INTEGER_TYPE)
+   return t;
 }
   if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
 {
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C 
b/gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C
new file mode 100644
index 000..196c6ec51fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-vector1.C
@@ -0,0 +1,8 @@
+// PR c++/113835
+// { dg-timeout-factor 0.05 }
+// { dg-do compile { target c++20_only } }
+
+#include 
+const std::size_t N = 1'000'000;
+std::vector x(N);
+int main() {}

base-commit: fa58ff249a0e63a721ccb6d770c86523d84a212a
-- 
2.49.0



[PATCH] combine: Correct comment about combine_validate_cost

2025-04-14 Thread Hans-Peter Nilsson
Noticed while investigating a regression for cris-elf with
r15-9239-g4d7a634f6d4102 "combine: Allow 2->2 combinations,
but with a tweak [PR116398]" (to-be-reported).

The comment was introduced when breaking out the
combine_validate_cost function, in r0-59417-g64b8935d4809f3.

I thought about wordsmithing to keep the "polarity" of the
statement, but "are equal to or cheaper than" didn't read
well.

Ok to commit?

-- >8 --
The *code* has been the same since forever, but this
comment, at a critical path, is misleading: if the new cost
is the same (like, when doing an identity replacement), then
combine_validate_cost returns true.

* combine.cc (try_combine): Correct comment about
combine_validate_cost.
---
 gcc/combine.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/combine.cc b/gcc/combine.cc
index 5f085187cfef..c2c1d50ca49f 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -4129,8 +4129,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, 
rtx_insn *i0,
}
 }
 
-  /* Only allow this combination if insn_cost reports that the
- replacement instructions are cheaper than the originals.  */
+  /* Reject this combination if insn_cost reports that the replacement
+ instructions are more expensive than the originals.  */
   if (!combine_validate_cost (i0, i1, i2, i3, newpat, newi2pat, other_pat))
 {
   undo_all ();
-- 
2.30.2



RISC-V: adjust testcase for gcc-14 [PR118182]

2025-04-14 Thread Alexandre Oliva
On Apr 14, 2025, Jeff Law  wrote:

> No strong opinion.  I'd lean towards xfail or twiddling the test since
> that's obviously super-save WRT codegen on the gcc-14 release branch.

Twiddling it is, then (pending approval ;-)

The pr118182-2.c testcase backported from gcc-15 depended on the late
combine pass after register allocation to substitute the zero constant
into the pred_broadcast to get to the expected vmv.s.x instruction.
Without that pass, we get a mfmv.s.f instead.  Expect that on gcc-14.

Tested both riscv64-elf and riscv32-elf on x86_64-linux-gnu.
Ok for gcc-14?


for  gcc/testsuite/ChangeLog

PR target/118182
* gcc.target/riscv/rvv/autovec/pr118182-2.c: Adjust.
---
 .../gcc.target/riscv/rvv/autovec/pr118182-2.c  |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118182-2.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118182-2.c
index 619d757a14fa7..0e334f5991510 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118182-2.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr118182-2.c
@@ -9,7 +9,7 @@
 **   ...
 **   vsetvli   [ast][0-9]+,zero,.*
 **   ...
-**   vmv.s.x   .*
+**   vfmv.s.f  .*
 **   ...
 **   vfredusum.vs  .*
 **   ...


-- 
Alexandre Oliva, happy hackerhttps://blog.lx.oliva.nom.br/
Free Software Activist FSFLA co-founder GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity.
Excluding neuro-others for not behaving ""normal"" is *not* inclusive!


[COMMITTED] Doc: always_inline attribute vs multiple TUs and LTO [PR113203]

2025-04-14 Thread Sandra Loosemore
gcc/ChangeLog
PR ipa/113203
* doc/extend.texi (Common Function Attributes): Explain how to
use always_inline in programs that have multiple translation
units, and that LTO inlining additionally needs optimization
enabled.
---
 gcc/doc/extend.texi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ae3357f83bf..d5fb2316cfd 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1933,6 +1933,13 @@ Note that if such a function is called indirectly the 
compiler may
 or may not inline it depending on optimization level and a failure
 to inline an indirect call may or may not be diagnosed.
 
+If you need to use the inlined function in multiple translation units,
+you should put the @code{always_inline} attribute on a function
+definition in a header file that is included in all translation units
+where the function is used.  Link-time optimization can inline
+functions across translation units, but only if an optimization level
+that normally enables inlining is additionally specified.
+
 @cindex @code{artificial} function attribute
 @item artificial
 This attribute is useful for small inline wrappers that if possible
-- 
2.34.1



RISC-V: revert pr114194 tests on gcc-14 [PR118601]

2025-04-14 Thread Alexandre Oliva


And here's another that came up more recently:

The gcc-14 backport that split the pr114194 testcase for rv32 and rv64
would only generate the expected rv32 sequence if commit
6b315907c0353f71169a7555e653d29a981fef67 had also been backported, but
it wasn't.  Without it, we get the same code as before on both rv32
and rv64, so revert to the original test.

Also tested on riscv64-elf and riscv32-elf on x86_64-linux-gnu.
Ok for gcc-14?


for  gcc/testsuite/ChangeLog

PR target/118601
* gcc.target/riscv/rvv/xtheadvector/pr114194.c: Restore.
* gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c: Remove.
* gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c: Likewise.
---
 .../riscv/rvv/xtheadvector/pr114194-rv32.c |   51 --
 .../riscv/rvv/xtheadvector/pr114194-rv64.c |   55 
 .../gcc.target/riscv/rvv/xtheadvector/pr114194.c   |   56 
 3 files changed, 56 insertions(+), 106 deletions(-)
 delete mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c
 delete mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194.c

diff --git a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c 
b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c
deleted file mode 100644
index 0bee5ec33de83..0
--- a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv32.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* { dg-do compile { target rv32 } } */
-/* { dg-options "-march=rv32gc_xtheadvector -O2" } */
-/* { dg-final { check-function-bodies "**" "" } } */
-
-/*
-** foo0_1:
-** sb\tzero,0\([a-x0-9]+\)
-** ret
-*/
-void foo0_1 (void *p)
-{
-  __builtin_memset (p, 0, 1);
-}
-
-/*
-** foo0_7:
-** li\t[a-x0-9]+,7
-** th.vsetvli\tzero,[a-x0-9]+,e8,m1
-** th\.vmv\.v\.i\tv[0-9],0
-** th\.vse\.v\tv[0-9]+,0\([a-x0-9]+\)
-** ret
-*/
-void foo0_7 (void *p)
-{
-  __builtin_memset (p, 0, 7);
-}
-
-/*
-** foo1_1:
-** li\t[a-x0-9]+,1
-** sb\t[a-x0-9]+,0\([a-x0-9]+\)
-** ret
-*/
-void foo1_1 (void *p)
-{
-  __builtin_memset (p, 1, 1);
-}
-
-/*
-** foo1_5:
-** li\t[a-x0-9]+,5
-** th.vsetvli\tzero,[a-x0-9]+,e8,m1
-** th\.vmv\.v\.i\tv[0-9],1
-** th\.vse\.v\tv[0-9]+,0\([a-x0-9]+\)
-** ret
-*/
-
-void foo1_5 (void *p)
-{
-  __builtin_memset (p, 1, 5);
-}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c 
b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c
deleted file mode 100644
index 84333c1cf5a7c..0
--- a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194-rv64.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* { dg-do compile { target rv64 } } */
-/* { dg-options "-march=rv64gc_xtheadvector -O2" } */
-/* { dg-final { check-function-bodies "**" "" } } */
-
-/*
-** foo0_1:
-** sb\tzero,0\([a-x0-9]+\)
-** ret
-*/
-void foo0_1 (void *p)
-{
-  __builtin_memset (p, 0, 1);
-}
-
-/*
-** foo0_7:
-** sb\tzero,0\([a-x0-9]+\)
-** sb\tzero,1\([a-x0-9]+\)
-** sb\tzero,2\([a-x0-9]+\)
-** sb\tzero,3\([a-x0-9]+\)
-** sb\tzero,4\([a-x0-9]+\)
-** sb\tzero,5\([a-x0-9]+\)
-** sb\tzero,6\([a-x0-9]+\)
-** ret
-*/
-void foo0_7 (void *p)
-{
-  __builtin_memset (p, 0, 7);
-}
-
-/*
-** foo1_1:
-** li\t[a-x0-9]+,1
-** sb\t[a-x0-9]+,0\([a-x0-9]+\)
-** ret
-*/
-void foo1_1 (void *p)
-{
-  __builtin_memset (p, 1, 1);
-}
-
-/*
-** foo1_5:
-** li\t[a-x0-9]+,1
-** sb\t[a-x0-9]+,0\([a-x0-9]+\)
-** sb\t[a-x0-9]+,1\([a-x0-9]+\)
-** sb\t[a-x0-9]+,2\([a-x0-9]+\)
-** sb\t[a-x0-9]+,3\([a-x0-9]+\)
-** sb\t[a-x0-9]+,4\([a-x0-9]+\)
-** ret
-*/
-void foo1_5 (void *p)
-{
-  __builtin_memset (p, 1, 5);
-}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194.c 
b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194.c
new file mode 100644
index 0..2e53a7ecc3e71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr114194.c
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadvector -O2" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadvector -O2" { target { rv64 } } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo0_1:
+** sb\tzero,0\([a-x0-9]+\)
+** ret
+*/
+void foo0_1 (void *p)
+{
+  __builtin_memset (p, 0, 1);
+}
+
+/*
+** foo0_7:
+** sb\tzero,0\([a-x0-9]+\)
+** sb\tzero,1\([a-x0-9]+\)
+** sb\tzero,2\([a-x0-9]+\)
+** sb\tzero,3\([a-x0-9]+\)
+** sb\tzero,4\([a-x0-9]+\)
+** sb\tzero,5\([a-x0-9]+\)
+** sb\tzero,6\([a-x0-9]+\)
+** ret
+*/
+void foo0_7 (void *p)
+{
+  __builtin_memset (p, 0, 7);
+}
+
+/*
+** foo1_1:
+** li\t[a-x0-9]+,1
+** sb\t[a-x0-9]+,0\([a-x0-9]+\)
+** ret
+*/
+void foo1_1 (void *p)
+{
+  __builtin_memset (p, 1, 1);
+}
+
+/*
+** foo1_5:
+** li\t[a-x0-9]+,1
+** sb\t[a-x0-9]+,0\([a-x0-9]+

[PUSHED] GCN, nvptx: Support '-mfake-exceptions', and use it for offloading compilation [PR118794]

2025-04-14 Thread Thomas Schwinge
With '-mfake-exceptions' enabled, the user-visible behavior in presence of
exception handling constructs changes such that the compile-time
'sorry, unimplemented: exception handling not supported' is skipped, code
generation proceeds, and instead, exception handling constructs 'abort' at
run time.  (..., or don't, if they're in dead code.)

PR target/118794
gcc/
* config/gcn/gcn.opt (-mfake-exceptions): Support.
* config/nvptx/nvptx.opt (-mfake-exceptions): Likewise.
* config/gcn/gcn.md (define_expand "exception_receiver"): Use it.
* config/nvptx/nvptx.md (define_expand "exception_receiver"):
Likewise.
* config/gcn/mkoffload.cc (main): Set it.
* config/nvptx/mkoffload.cc (main): Likewise.
* config/nvptx/nvptx.cc (nvptx_assemble_integer)
: Special handling for
'SYMBOL_REF's.
* except.cc (expand_dw2_landing_pad_for_region): Don't generate
bogus code for (default)
'#define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM'.
libgcc/
* config/gcn/unwind-gcn.c (_Unwind_Resume): New.
* config/nvptx/unwind-nvptx.c (_Unwind_Resume): Likewise.
gcc/testsuite/
* g++.target/gcn/exceptions-bad_cast-2.C: Set
'-mno-fake-exceptions'.
* g++.target/gcn/exceptions-pr118794-1.C: Likewise.
* g++.target/gcn/exceptions-throw-2.C: Likewise.
* g++.target/nvptx/exceptions-bad_cast-2.C: Likewise.
* g++.target/nvptx/exceptions-pr118794-1.C: Likewise.
* g++.target/nvptx/exceptions-throw-2.C: Likewise.
* g++.target/gcn/exceptions-bad_cast-2_-mfake-exceptions.C: New.
* g++.target/gcn/exceptions-pr118794-1_-mfake-exceptions.C:
Likewise.
* g++.target/gcn/exceptions-throw-2_-mfake-exceptions.C: Likewise.
* g++.target/nvptx/exceptions-bad_cast-2_-mfake-exceptions.C:
Likewise.
* g++.target/nvptx/exceptions-pr118794-1_-mfake-exceptions.C:
Likewise.
* g++.target/nvptx/exceptions-throw-2_-mfake-exceptions.C:
Likewise.
libgomp/
* 
testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-GCN.C:
Set '-foffload-options=-mno-fake-exceptions'.
* 
testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-nvptx.C:
Likewise.
* 
testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-GCN.C:
Likewise.
* 
testsuite/libgomp.c++/target-exceptions-pr118794-1-offload-sorry-nvptx.C:
Likewise.
* testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-GCN.C:
Likewise.
* testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-nvptx.C:
Likewise.
* testsuite/libgomp.oacc-c++/exceptions-bad_cast-2-offload-sorry-GCN.C:
Likewise.
* 
testsuite/libgomp.oacc-c++/exceptions-bad_cast-2-offload-sorry-nvptx.C:
Likewise.
* testsuite/libgomp.oacc-c++/exceptions-throw-2-offload-sorry-GCN.C:
Likewise.
* testsuite/libgomp.oacc-c++/exceptions-throw-2-offload-sorry-nvptx.C:
Likewise.
* testsuite/libgomp.c++/target-exceptions-bad_cast-2.C: Adjust.
* testsuite/libgomp.c++/target-exceptions-pr118794-1.C: Likewise.
* testsuite/libgomp.c++/target-exceptions-throw-2.C: Likewise.
* testsuite/libgomp.oacc-c++/exceptions-bad_cast-2.C: Likewise.
* testsuite/libgomp.oacc-c++/exceptions-throw-2.C: Likewise.
* testsuite/libgomp.c++/target-exceptions-throw-2-O0.C: New.
---
 gcc/config/gcn/gcn.md |  4 ++-
 gcc/config/gcn/gcn.opt|  8 +
 gcc/config/gcn/mkoffload.cc   |  3 ++
 gcc/config/nvptx/mkoffload.cc |  3 ++
 gcc/config/nvptx/nvptx.cc | 20 -
 gcc/config/nvptx/nvptx.md |  4 ++-
 gcc/config/nvptx/nvptx.opt|  8 +
 gcc/except.cc | 24 +++
 .../g++.target/gcn/exceptions-bad_cast-2.C|  1 +
 .../exceptions-bad_cast-2_-mfake-exceptions.C | 18 +++
 .../g++.target/gcn/exceptions-pr118794-1.C|  1 +
 .../exceptions-pr118794-1_-mfake-exceptions.C | 16 ++
 .../g++.target/gcn/exceptions-throw-2.C   |  1 +
 .../exceptions-throw-2_-mfake-exceptions.C| 19 
 .../g++.target/nvptx/exceptions-bad_cast-2.C  |  1 +
 .../exceptions-bad_cast-2_-mfake-exceptions.C | 19 
 .../g++.target/nvptx/exceptions-pr118794-1.C  |  1 +
 .../exceptions-pr118794-1_-mfake-exceptions.C | 16 ++
 .../g++.target/nvptx/exceptions-throw-2.C |  1 +
 .../exceptions-throw-2_-mfake-exceptions.C| 19 
 libgcc/config/gcn/unwind-gcn.c|  6 
 libgcc/config/nvptx/unwind-nvptx.c|  6 
 ...-exceptions-bad_cast-2-offload-sorry-GCN.C |  5 ++--
 ...xceptions-bad_cast-2-offload-sorry-nvptx.C |  5 ++--
 .../target-exceptions-b

[PUSHED 2/3] Add 'throw', caught test cases for GCN, nvptx target and OpenACC, OpenMP 'target' offloading

2025-04-14 Thread Thomas Schwinge
gcc/testsuite/
* g++.target/gcn/exceptions-throw-2.C: New.
* g++.target/nvptx/exceptions-throw-2.C: Likewise.
libgomp/
* testsuite/libgomp.c++/target-exceptions-throw-2.C: New.
* testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-GCN.C: 
Likewise.
* 
testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-nvptx.C: Likewise.
* testsuite/libgomp.oacc-c++/exceptions-throw-2.C: Likewise.
* testsuite/libgomp.oacc-c++/exceptions-throw-2-offload-sorry-GCN.C: 
Likewise.
* testsuite/libgomp.oacc-c++/exceptions-throw-2-offload-sorry-nvptx.C: 
Likewise.
---
 .../g++.target/gcn/exceptions-throw-2.C   | 13 +++
 .../g++.target/nvptx/exceptions-throw-2.C | 13 +++
 ...get-exceptions-throw-2-offload-sorry-GCN.C | 20 ++
 ...t-exceptions-throw-2-offload-sorry-nvptx.C | 20 ++
 .../libgomp.c++/target-exceptions-throw-2.C   | 15 +++
 .../exceptions-throw-2-offload-sorry-GCN.C| 19 +
 .../exceptions-throw-2-offload-sorry-nvptx.C  | 21 ++
 .../libgomp.oacc-c++/exceptions-throw-2.C | 39 +++
 8 files changed, 160 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/gcn/exceptions-throw-2.C
 create mode 100644 gcc/testsuite/g++.target/nvptx/exceptions-throw-2.C
 create mode 100644 
libgomp/testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-GCN.C
 create mode 100644 
libgomp/testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-nvptx.C
 create mode 100644 libgomp/testsuite/libgomp.c++/target-exceptions-throw-2.C
 create mode 100644 
libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-2-offload-sorry-GCN.C
 create mode 100644 
libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-2-offload-sorry-nvptx.C
 create mode 100644 libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-2.C

diff --git a/gcc/testsuite/g++.target/gcn/exceptions-throw-2.C 
b/gcc/testsuite/g++.target/gcn/exceptions-throw-2.C
new file mode 100644
index 000..0ae64eebd47
--- /dev/null
+++ b/gcc/testsuite/g++.target/gcn/exceptions-throw-2.C
@@ -0,0 +1,13 @@
+/* 'throw', caught.  */
+
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+/* { dg-additional-options -fexceptions } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+#include "../../../../libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-2.C"
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_allocate_exception, } 
1 optimized } }
+   { dg-final { scan-tree-dump-times {gimple_call <__cxa_throw, } 1 optimized 
} }
+   Compilation fails:
+   { dg-regexp {[^\r\n]+: In function 'int main\(\)':[\r\n]+(?:[^\r\n]+: 
sorry, unimplemented: exception handling not supported[\r\n]+)+} }
+   (Note, using 'dg-regexp' instead of 'dg-message', as the former runs before 
the auto-mark-UNSUPPORTED.)  */
diff --git a/gcc/testsuite/g++.target/nvptx/exceptions-throw-2.C 
b/gcc/testsuite/g++.target/nvptx/exceptions-throw-2.C
new file mode 100644
index 000..0ae64eebd47
--- /dev/null
+++ b/gcc/testsuite/g++.target/nvptx/exceptions-throw-2.C
@@ -0,0 +1,13 @@
+/* 'throw', caught.  */
+
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+/* { dg-additional-options -fexceptions } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+#include "../../../../libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-2.C"
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_allocate_exception, } 
1 optimized } }
+   { dg-final { scan-tree-dump-times {gimple_call <__cxa_throw, } 1 optimized 
} }
+   Compilation fails:
+   { dg-regexp {[^\r\n]+: In function 'int main\(\)':[\r\n]+(?:[^\r\n]+: 
sorry, unimplemented: exception handling not supported[\r\n]+)+} }
+   (Note, using 'dg-regexp' instead of 'dg-message', as the former runs before 
the auto-mark-UNSUPPORTED.)  */
diff --git 
a/libgomp/testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-GCN.C 
b/libgomp/testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-GCN.C
new file mode 100644
index 000..484e3f8bd33
--- /dev/null
+++ 
b/libgomp/testsuite/libgomp.c++/target-exceptions-throw-2-offload-sorry-GCN.C
@@ -0,0 +1,20 @@
+/* 'throw' in OpenMP 'target' region, caught.  */
+
+/* As this test case involves an expected offload compilation failure, we have 
to handle each offload target individually.
+   { dg-do link { target offload_target_amdgcn } }
+   { dg-additional-options -foffload=amdgcn-amdhsa } */
+/* { dg-require-effective-target exceptions }
+   { dg-additional-options -fexceptions } */
+/* { dg-additional-options -fdump-tree-optimized-raw }
+   { dg-additional-options -foffload-options=-fdump-tree-optimized-raw } */
+
+#include "target-exceptions-throw-2.C"
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_allocate_exception, } 
1 optimized } }
+   { dg-final { scan-tree-dump-times {gimple_call <

[PUSHED14 2/2] phiopt: Reset the number of iterations information of a loop when changing an exit from the loop [PR117243]

2025-04-14 Thread Andrew Pinski
After r12-5300-gf98f373dd822b3, phiopt could get the following bb structure:
  |
middle-bb -|
  ||
  |   ||   |
phi<1, 2>  |   |
cond   |   |
  ||   |
  |+---|

Which was considered 2 loops. The inner loop had esimtate of upper_bound to be 
8,
due to the original `for (b = 0; b <= 7; b++)`. The outer loop was already an
infinite one.
So phiopt would come along and change the condition to be unconditionally true,
we change the inner loop to being an infinite one but don't reset the estimate
on the loop and cleanup cfg comes along and changes it into one loop but also
does not reset the estimate of the loop. Then the loop unrolling uses the old 
estimate
and decides to add an unreachable there.o
So the fix is when phiopt changes an exit to a loop, reset the estimates, 
similar to
how cleanupcfg does it when merging some basic blocks.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/117243
PR tree-optimization/116749

gcc/ChangeLog:

* tree-ssa-phiopt.cc (replace_phi_edge_with_variable): Reset loop
estimates if the cond_block was an exit to a loop.

gcc/testsuite/ChangeLog:

* gcc.dg/torture/pr117243-1.c: New test.
* gcc.dg/torture/pr117243-2.c: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit b7c69cc072ef0da36439ebc55c513b48e68391b7)
---
 gcc/testsuite/gcc.dg/torture/pr117243-1.c | 30 
 gcc/testsuite/gcc.dg/torture/pr117243-2.c | 34 +++
 gcc/tree-ssa-phiopt.cc| 11 
 3 files changed, 75 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-2.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr117243-1.c 
b/gcc/testsuite/gcc.dg/torture/pr117243-1.c
new file mode 100644
index 000..c4bbc31467c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117243-1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+/* PR tree-optimization/117243 */
+/* foo should be an infinite but sometimes it gets optimized incorrectly into
+   an __builtin_unreachable(); which is not valid.  */
+void
+foo (unsigned int a, unsigned char b)
+{
+  lbl:
+  for (b = 0; b <= 7; b++)
+{
+  unsigned char c[1][1];
+  int i, j;
+  for (i = 0; i < 1; i++)
+for (j = 0; j < 1; j++)
+  c[i][j] = 1;
+  if (b)
+   goto lbl;
+}
+}
+
+int
+main ()
+{
+  foo (1, 2);
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_unreachable " "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr117243-2.c 
b/gcc/testsuite/gcc.dg/torture/pr117243-2.c
new file mode 100644
index 000..d9b0d3eeb98
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117243-2.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-tree-ch -fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+/* PR tree-optimization/117243 */
+/* PR tree-optimization/116749 */
+
+/* main1 should be an infinite but sometimes it gets optimized incorrectly into
+   an __builtin_unreachable(); which is not valid.  */
+int main1 (void)
+{
+int g=0;
+int l1[1];
+int *l2 = &g;
+int i;
+for (i=0; i<1; i++)
+l1[i] = (1);
+for (g=0; g; ++g)
+{
+int *l3[1] = {&l1[0]};
+}
+*l2 = *l1;
+b:
+for (i=0; i<2; ++i)
+{ 
+if (i)
+goto b;
+if (g)
+continue;
+}
+return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_unreachable " "optimized"} } */
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 14bb8442a39..b8c5cc0e0d3 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "tree-ssa-propagate.h"
 #include "tree-ssa-dce.h"
+#include "tree-ssa-loop-niter.h"
 
 /* Return the singleton PHI in the SEQ of PHIs for edges E0 and E1. */
 
@@ -159,6 +160,16 @@ replace_phi_edge_with_variable (basic_block cond_block,
   else
 gcc_unreachable ();
 
+  /* If we are removing the cond on a loop exit,
+ reset number of iteration information of the loop. */
+  if (loop_exits_from_bb_p (cond_block->loop_father, cond_block))
+{
+  auto loop = cond_block->loop_father;
+  free_numbers_of_iterations_estimates (loop);
+  loop->any_upper_bound = false;
+  loop->any_likely_upper_bound = false;
+}
+
   if (edge_to_remove && EDGE_COUNT (edge_to_remove->dest->preds) == 1)
 {
   e->flags |= EDGE_FALLTHRU;
-- 
2.43.0



[PUSHED/14 0/2] A few backports to GCC 14

2025-04-14 Thread Andrew Pinski
These 2 had simple resolvable conflicts when backporting.
In the case of value_replacement, there was some minor code
movement in value_replacement which needed to be resolved.
In the case of PR117243, there was an extra include that was not on
the branch.

Andrew Pinski (2):
  phiopt: Fix value_replacement for middle bb having phi nodes
[PR118922]
  phiopt: Reset the number of iterations information of a loop when
changing an exit from the loop [PR117243]

 gcc/testsuite/gcc.dg/torture/pr117243-1.c | 30 
 gcc/testsuite/gcc.dg/torture/pr117243-2.c | 34 ++
 gcc/testsuite/gcc.dg/torture/pr118922-1.c | 57 +++
 gcc/tree-ssa-phiopt.cc| 15 ++
 4 files changed, 136 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-2.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr118922-1.c

-- 
2.43.0



[PUSHED14 1/2] phiopt: Fix value_replacement for middle bb having phi nodes [PR118922]

2025-04-14 Thread Andrew Pinski
After r12-5300-gf98f373dd822b3, value_replacement would be able to look at the
following cfg structure:
```
   [local count: 1014686024]:
  if (h_6 != 0)
goto ; [94.50%]
  else
goto ; [5.50%]

   [local count: 114863530]:
  # h_6 = PHI <0(4), 1(5)>

   [local count: 1073741824]:
  # f_8 = PHI <0(5), h_6(6)>
  _9 = f_8 ^ 1;
  a.0_10 = a;
  _11 = _9 + a.0_10;
  if (_11 != -117)
goto ; [94.50%]
  else
goto ; [5.50%]
```

value_replacement would incorrectly think the middle bb (6) was empty and so it 
decides
to remove condition in bb5 and replacing it with 0 as the function thought it 
was `h_6 ? 0 : h_6`.
But since the there is an incoming phi node to bb6 defining h_6 that is 
incorrect.

The fix is to check if there is phi nodes in the middle bb and set 
empty_or_with_defined_p to false.
This was not needed before r12-5300-gf98f373dd822b3 because the phi would have 
been dead otherwise due to
other checks.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/118922

gcc/ChangeLog:

* tree-ssa-phiopt.cc (value_replacement): Set empty_or_with_defined_p
to false when there is phi nodes for the middle bb.

gcc/testsuite/ChangeLog:

* gcc.dg/torture/pr118922-1.c: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit 7232c005afb5002cdfd0a2dbd0e8b8f2d80250ce)
---
 gcc/testsuite/gcc.dg/torture/pr118922-1.c | 57 +++
 gcc/tree-ssa-phiopt.cc|  4 ++
 2 files changed, 61 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr118922-1.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr118922-1.c 
b/gcc/testsuite/gcc.dg/torture/pr118922-1.c
new file mode 100644
index 000..27e8c78c0e4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr118922-1.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+/* PR tree-optimization/118922 */
+
+/* Phi-opt would convert:
+   [local count: 1014686024]:
+  if (h_6 != 0)
+goto ; [94.50%]
+  else
+goto ; [5.50%]
+
+   [local count: 114863530]:
+  # h_6 = PHI <0(4), 1(5)>
+
+   [local count: 1073741824]:
+  # f_8 = PHI <0(5), h_6(6)>
+  _9 = f_8 ^ 1;
+  a.0_10 = a;
+  _11 = _9 + a.0_10;
+  if (_11 != -117)
+goto ; [94.50%]
+  else
+goto ; [5.50%]
+
+into:
+
+   [local count: 59055799]:
+  c = d_3;
+
+   [local count: 1073741824]:
+  # f_8 = PHI <0(5), 0(4)>
+  _9 = f_8 ^ 1;
+  a.0_10 = a;
+  _11 = _9 + a.0_10;
+  if (_11 != -117)
+goto ; [94.50%]
+  else
+goto ; [5.50%]
+
+as it thought the middle bb was empty as there was only a phi node there. */
+
+
+int a = -117, b, c, e;
+void g(int h) {
+  int f = 0;
+  while (!f + a - -117) {
+f = h == 0;
+if (h == 0)
+  h = 1;
+  }
+}
+int main() {
+  int d = 8;
+  for (; e;)
+d = 0;
+  c = d;
+  g(0);
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index fa8dc2c8a4e..14bb8442a39 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -1195,6 +1195,10 @@ value_replacement (basic_block cond_bb, basic_block 
middle_bb,
empty_or_with_defined_p = false;
 }
 
+  /* The middle bb is not empty if there are any phi nodes. */
+  if (phi_nodes (middle_bb))
+empty_or_with_defined_p = false;
+
   gcond *cond = as_a  (*gsi_last_bb (cond_bb));
   code = gimple_cond_code (cond);
 
-- 
2.43.0



Re: [PATCH] [testsuite] [ppc] compile [PR112822] with -mvsx

2025-04-14 Thread Alexandre Oliva
On Apr 14, 2025, Peter Bergner  wrote:

> This is an architecture independent test case, so I'm surprised this
> doesn't FAIL on non-powerpc targets since they don't know anything
> about altivec.

AFAICT we ignore attributes we don't know about.

I'd think the following fix should help them too.

I considered doing something like that, but I don't know whether the
modified test would trigger the original ICE.  It seemed fragile, and
the change could sort of invalidate the regression test.

I won't stand against this testcase modification, I'm just sharing the
reasons why I didn't take this path.

-- 
Alexandre Oliva, happy hackerhttps://blog.lx.oliva.nom.br/
Free Software Activist FSFLA co-founder GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity.
Excluding neuro-others for not behaving ""normal"" is *not* inclusive!


Re: [PATCH] [testsuite] [ppc] block-cmp-8 should require powerpc64

2025-04-14 Thread Alexandre Oliva
On Apr 14, 2025, Peter Bergner  wrote:

> That said, I hate the name "powerpc64" and it should probably be
> renamed to "powerpc64_hw" to be more clear about what it's testing.

Yeah, that would make sense.

> That said, that should be done in a separate patch.

*nod*.  Do you mean you're going to make that change, that I should, or
that you hope someone else will?  I'd rather avoid duplication, and this
is likely a somewhat involved change, since the string powerpc64 appears
all over gcc/testsuite/, with various meanings other than a dejagnu
effective target.

-- 
Alexandre Oliva, happy hackerhttps://blog.lx.oliva.nom.br/
Free Software Activist FSFLA co-founder GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity.
Excluding neuro-others for not behaving ""normal"" is *not* inclusive!


[PUSHED/13 1/4] vec-lowering: Fix ABSU lowering [PR111285]

2025-04-14 Thread Andrew Pinski
ABSU_EXPR lowering incorrectly used the resulting type
for the new expression but in the case of ABSU the resulting
type is an unsigned type and with ABSU is folded away. The fix
is to use a signed type for the expression instead.

Bootstrapped and tested on x86_64-linux-gnu.

PR middle-end/111285

gcc/ChangeLog:

* tree-vect-generic.cc (do_unop): Use a signed type for the
operand if the operation was ABSU_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/torture/vect-absu-1.C: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit ad0084337e901ddaedd48c14e7a5dad9fc2a093e)
(cherry picked from commit 8ee9d7b26342b96f462ebafa1304a26d83b4e833)
---
 gcc/testsuite/g++.dg/torture/vect-absu-1.C | 29 ++
 gcc/tree-vect-generic.cc   | 10 +++-
 2 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/vect-absu-1.C

diff --git a/gcc/testsuite/g++.dg/torture/vect-absu-1.C 
b/gcc/testsuite/g++.dg/torture/vect-absu-1.C
new file mode 100644
index 000..0b2035f638f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/vect-absu-1.C
@@ -0,0 +1,29 @@
+// { dg-do run }
+// PR middle-end/111285
+
+// The lowering of vect absu was done incorrectly
+
+#define vect1 __attribute__((vector_size(sizeof(int
+
+#define negabs(a) a < 0 ? a : -a
+
+__attribute__((noinline))
+int s(int a)
+{
+  return negabs(a);
+}
+__attribute__((noinline))
+vect1 int v(vect1 int a)
+{
+  return negabs(a);
+}
+
+int main(void)
+{
+for(int i = -10; i < 10; i++)
+{
+  vect1 int t = {i};
+  if (v(t)[0] != s(i))
+__builtin_abort();
+}
+}
diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc
index 6e74bf05be2..0b85a54a4ce 100644
--- a/gcc/tree-vect-generic.cc
+++ b/gcc/tree-vect-generic.cc
@@ -193,7 +193,15 @@ do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree 
a,
 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
 enum tree_code code, tree type ATTRIBUTE_UNUSED)
 {
-  a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
+  tree rhs_type = inner_type;
+
+  /* For ABSU_EXPR, use the signed type for the rhs if the rhs was signed. */
+  if (code == ABSU_EXPR
+  && ANY_INTEGRAL_TYPE_P (TREE_TYPE (a))
+  && !TYPE_UNSIGNED (TREE_TYPE (a)))
+rhs_type = signed_type_for (rhs_type);
+
+  a = tree_vec_extract (gsi, rhs_type, a, bitsize, bitpos);
   return gimplify_build1 (gsi, code, inner_type, a);
 }
 
-- 
2.43.0



[PUSHED/13 2/4] backprop: Fix deleting of a phi node [PR116922]

2025-04-14 Thread Andrew Pinski
The problem here is remove_unused_var is called on a name that is
defined by a phi node but it deletes it like removing a normal statement.
remove_phi_node should be called rather than gsi_remove for phinodes.

Note there is a possibility of using simple_dce_from_worklist instead
but that is for another day.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/116922

gcc/ChangeLog:

* gimple-ssa-backprop.cc (remove_unused_var): Handle phi
nodes correctly.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Andrew Pinski 
(cherry picked from commit cea87c84eacdb422caeada734ba5138c994d7022)
(cherry picked from commit aaef5d6409742574c2ff6acbc75a2a0f597ce8a3)
---
 gcc/gimple-ssa-backprop.cc  | 10 --
 gcc/testsuite/gcc.dg/torture/pr116922.c | 19 +++
 2 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr116922.c

diff --git a/gcc/gimple-ssa-backprop.cc b/gcc/gimple-ssa-backprop.cc
index dcb15ed4f61..d82ad293884 100644
--- a/gcc/gimple-ssa-backprop.cc
+++ b/gcc/gimple-ssa-backprop.cc
@@ -663,8 +663,14 @@ remove_unused_var (tree var)
   print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
 }
   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
-  gsi_remove (&gsi, true);
-  release_defs (stmt);
+  if (gimple_code (stmt) == GIMPLE_PHI)
+remove_phi_node (&gsi, true);
+  else
+{
+  unlink_stmt_vdef (stmt);
+  gsi_remove (&gsi, true);
+  release_defs (stmt);
+}
 }
 
 /* Note that we're replacing OLD_RHS with NEW_RHS in STMT.  */
diff --git a/gcc/testsuite/gcc.dg/torture/pr116922.c 
b/gcc/testsuite/gcc.dg/torture/pr116922.c
new file mode 100644
index 000..0fcf912930f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116922.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-ffast-math" } */
+/* PR tree-optimization/116922 */
+
+
+static int g;
+
+void
+foo (int c, double v, double *r)
+{
+b:
+  do
+v /= g - v;
+  while (c);
+  *r = v;
+
+  double x;
+  foo (5, (double)0, &x);
+}
-- 
2.43.0



[PUSHED/13 0/4] Backported patches to gcc 13

2025-04-14 Thread Andrew Pinski
Just a set of 4 patches backported from the trunk via 14 branch
to the GCC 13 release branch. These all fix regressions.

Andrew Pinski (4):
  vec-lowering: Fix ABSU lowering [PR111285]
  backprop: Fix deleting of a phi node [PR116922]
  phiopt: Reset the number of iterations information of a loop when
changing an exit from the loop [PR117243]
  phiopt: Fix value_replacement for middle bb having phi nodes
[PR118922]

 gcc/gimple-ssa-backprop.cc | 10 +++-
 gcc/testsuite/g++.dg/torture/vect-absu-1.C | 29 +++
 gcc/testsuite/gcc.dg/torture/pr116922.c| 19 
 gcc/testsuite/gcc.dg/torture/pr117243-1.c  | 30 
 gcc/testsuite/gcc.dg/torture/pr117243-2.c  | 34 +
 gcc/testsuite/gcc.dg/torture/pr118922-1.c  | 57 ++
 gcc/tree-ssa-phiopt.cc | 15 ++
 gcc/tree-vect-generic.cc   | 10 +++-
 8 files changed, 201 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/vect-absu-1.C
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr116922.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-2.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr118922-1.c

-- 
2.43.0



[PUSHED/13 3/4] phiopt: Reset the number of iterations information of a loop when changing an exit from the loop [PR117243]

2025-04-14 Thread Andrew Pinski
After r12-5300-gf98f373dd822b3, phiopt could get the following bb structure:
  |
middle-bb -|
  ||
  |   ||   |
phi<1, 2>  |   |
cond   |   |
  ||   |
  |+---|

Which was considered 2 loops. The inner loop had esimtate of upper_bound to be 
8,
due to the original `for (b = 0; b <= 7; b++)`. The outer loop was already an
infinite one.
So phiopt would come along and change the condition to be unconditionally true,
we change the inner loop to being an infinite one but don't reset the estimate
on the loop and cleanup cfg comes along and changes it into one loop but also
does not reset the estimate of the loop. Then the loop unrolling uses the old 
estimate
and decides to add an unreachable there.o
So the fix is when phiopt changes an exit to a loop, reset the estimates, 
similar to
how cleanupcfg does it when merging some basic blocks.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/117243
PR tree-optimization/116749

gcc/ChangeLog:

* tree-ssa-phiopt.cc (replace_phi_edge_with_variable): Reset loop
estimates if the cond_block was an exit to a loop.

gcc/testsuite/ChangeLog:

* gcc.dg/torture/pr117243-1.c: New test.
* gcc.dg/torture/pr117243-2.c: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit b7c69cc072ef0da36439ebc55c513b48e68391b7)
(cherry picked from commit 6f0d80202b62ae48381d9ec7488522199cb7922a)
---
 gcc/testsuite/gcc.dg/torture/pr117243-1.c | 30 
 gcc/testsuite/gcc.dg/torture/pr117243-2.c | 34 +++
 gcc/tree-ssa-phiopt.cc| 11 
 3 files changed, 75 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-2.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr117243-1.c 
b/gcc/testsuite/gcc.dg/torture/pr117243-1.c
new file mode 100644
index 000..c4bbc31467c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117243-1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+/* PR tree-optimization/117243 */
+/* foo should be an infinite but sometimes it gets optimized incorrectly into
+   an __builtin_unreachable(); which is not valid.  */
+void
+foo (unsigned int a, unsigned char b)
+{
+  lbl:
+  for (b = 0; b <= 7; b++)
+{
+  unsigned char c[1][1];
+  int i, j;
+  for (i = 0; i < 1; i++)
+for (j = 0; j < 1; j++)
+  c[i][j] = 1;
+  if (b)
+   goto lbl;
+}
+}
+
+int
+main ()
+{
+  foo (1, 2);
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_unreachable " "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr117243-2.c 
b/gcc/testsuite/gcc.dg/torture/pr117243-2.c
new file mode 100644
index 000..d9b0d3eeb98
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117243-2.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-tree-ch -fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+/* PR tree-optimization/117243 */
+/* PR tree-optimization/116749 */
+
+/* main1 should be an infinite but sometimes it gets optimized incorrectly into
+   an __builtin_unreachable(); which is not valid.  */
+int main1 (void)
+{
+int g=0;
+int l1[1];
+int *l2 = &g;
+int i;
+for (i=0; i<1; i++)
+l1[i] = (1);
+for (g=0; g; ++g)
+{
+int *l3[1] = {&l1[0]};
+}
+*l2 = *l1;
+b:
+for (i=0; i<2; ++i)
+{ 
+if (i)
+goto b;
+if (g)
+continue;
+}
+return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_unreachable " "optimized"} } */
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 06b099d517f..9856d3e139e 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "tree-ssa-propagate.h"
 #include "tree-ssa-dce.h"
+#include "tree-ssa-loop-niter.h"
 
 static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
 static bool two_value_replacement (basic_block, basic_block, edge, gphi *,
@@ -455,6 +456,16 @@ replace_phi_edge_with_variable (basic_block cond_block,
   else
 gcc_unreachable ();
 
+  /* If we are removing the cond on a loop exit,
+ reset number of iteration information of the loop. */
+  if (loop_exits_from_bb_p (cond_block->loop_father, cond_block))
+{
+  auto loop = cond_block->loop_father;
+  free_numbers_of_iterations_estimates (loop);
+  loop->any_upper_bound = false;
+  loop->any_likely_upper_bound = false;
+}
+
   if (edge_to_remove && EDGE_COUNT (edge_to_remove->dest->preds) == 1)
 {
   e->flags |= EDGE_FALLTHRU;
-- 
2.43.0



[PUSHED/13 4/4] phiopt: Fix value_replacement for middle bb having phi nodes [PR118922]

2025-04-14 Thread Andrew Pinski
After r12-5300-gf98f373dd822b3, value_replacement would be able to look at the
following cfg structure:
```
   [local count: 1014686024]:
  if (h_6 != 0)
goto ; [94.50%]
  else
goto ; [5.50%]

   [local count: 114863530]:
  # h_6 = PHI <0(4), 1(5)>

   [local count: 1073741824]:
  # f_8 = PHI <0(5), h_6(6)>
  _9 = f_8 ^ 1;
  a.0_10 = a;
  _11 = _9 + a.0_10;
  if (_11 != -117)
goto ; [94.50%]
  else
goto ; [5.50%]
```

value_replacement would incorrectly think the middle bb (6) was empty and so it 
decides
to remove condition in bb5 and replacing it with 0 as the function thought it 
was `h_6 ? 0 : h_6`.
But since the there is an incoming phi node to bb6 defining h_6 that is 
incorrect.

The fix is to check if there is phi nodes in the middle bb and set 
empty_or_with_defined_p to false.
This was not needed before r12-5300-gf98f373dd822b3 because the phi would have 
been dead otherwise due to
other checks.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/118922

gcc/ChangeLog:

* tree-ssa-phiopt.cc (value_replacement): Set empty_or_with_defined_p
to false when there is phi nodes for the middle bb.

gcc/testsuite/ChangeLog:

* gcc.dg/torture/pr118922-1.c: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit 7232c005afb5002cdfd0a2dbd0e8b8f2d80250ce)
(cherry picked from commit 0d931663498d2f95fb7ea0ae0ef8473f88eed26a)
---
 gcc/testsuite/gcc.dg/torture/pr118922-1.c | 57 +++
 gcc/tree-ssa-phiopt.cc|  4 ++
 2 files changed, 61 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr118922-1.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr118922-1.c 
b/gcc/testsuite/gcc.dg/torture/pr118922-1.c
new file mode 100644
index 000..27e8c78c0e4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr118922-1.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+/* PR tree-optimization/118922 */
+
+/* Phi-opt would convert:
+   [local count: 1014686024]:
+  if (h_6 != 0)
+goto ; [94.50%]
+  else
+goto ; [5.50%]
+
+   [local count: 114863530]:
+  # h_6 = PHI <0(4), 1(5)>
+
+   [local count: 1073741824]:
+  # f_8 = PHI <0(5), h_6(6)>
+  _9 = f_8 ^ 1;
+  a.0_10 = a;
+  _11 = _9 + a.0_10;
+  if (_11 != -117)
+goto ; [94.50%]
+  else
+goto ; [5.50%]
+
+into:
+
+   [local count: 59055799]:
+  c = d_3;
+
+   [local count: 1073741824]:
+  # f_8 = PHI <0(5), 0(4)>
+  _9 = f_8 ^ 1;
+  a.0_10 = a;
+  _11 = _9 + a.0_10;
+  if (_11 != -117)
+goto ; [94.50%]
+  else
+goto ; [5.50%]
+
+as it thought the middle bb was empty as there was only a phi node there. */
+
+
+int a = -117, b, c, e;
+void g(int h) {
+  int f = 0;
+  while (!f + a - -117) {
+f = h == 0;
+if (h == 0)
+  h = 1;
+  }
+}
+int main() {
+  int d = 8;
+  for (; e;)
+d = 0;
+  c = d;
+  g(0);
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 9856d3e139e..fd472771b1e 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -1364,6 +1364,10 @@ value_replacement (basic_block cond_bb, basic_block 
middle_bb,
empty_or_with_defined_p = false;
 }
 
+  /* The middle bb is not empty if there are any phi nodes. */
+  if (phi_nodes (middle_bb))
+empty_or_with_defined_p = false;
+
   cond = last_stmt (cond_bb);
   code = gimple_cond_code (cond);
 
-- 
2.43.0



Re: [PATCH] [testsuite] [ppc] pr87600, pr89313: test for __PPC__ as well

2025-04-14 Thread Peter Bergner
On 4/11/25 1:03 PM, Alexandre Oliva wrote:
> gcc.dg/pr87600.h and gcc.dg/pr89313.c test for __powerpc__ and
> __POWERPC__ to choose ppc register names, but ppc-elf defines neither;
> it defines __PPC__, so test for that as well.

Is there a reason why powerpc-*-elf doesn't define __powerpc__ or
__POWERPC__ like we do for other powerpc* targets?

That said, I think this probably falls under the "obvious" rule too.

Peter





Re: [RFC] [C]New syntax for the argument of counted_by attribute for C language

2025-04-14 Thread Bill Wendling
On Mon, Apr 14, 2025 at 1:56 PM Qing Zhao  wrote:
>
> Hi, Bill,
>
> Thanks for your new proposal.
>
> If I understand correctly, this new proposal basically is back to one of our 
> previous proposal:
>
> Adding a new structure scoping for counted_by attribute into C;
>
> With this approach, there is one new structure scoping added to C, and this 
> new scope
> will shadow other scopes in the current  C.
>
> The identifiers inside the counted_by attribute will be looked up within this 
> new structure scope first.
> Conflicted local or global variables need to be prefixed with special builtin 
> to explicitly specify its scope.
>
> Is this understanding correctly?
>
Yes, in a sense. I called it a "pseudo" struct scope, because it's not
fully fleshed out and is limited to very specific instances with very
specific behavior.

> My opinion on this:
>
> 1. Personally, as I mentioned multiple times, I think that this might be the 
> cleanest solution;
> If other people agree on this, I am happy to go with this.  -:)
>
:-)

> 2. However, my understanding from our previous long discussion is:
>Adding a new structure scope to C (even it’s only for counted_by 
> attribute) should not be done without
>Having a clear specification and support from WG14.
>
> Please refer to the following:
>
> https://gcc.gnu.org/pipermail/gcc-patches/2025-April/679922.html.
> https://gcc.gnu.org/pipermail/gcc-patches/2025-April/679923.html.
>
> Martin and Joseph, what’s your opinion on this proposal?
>
I should point out that using the forward declaration syntax could
cause errors with macro expansions. For example,

#define FOO (len + 42)
struct A {
  int *buf __counted_by_expr(size_t len; len << FOO);
  int len;
};

The 'len' from the macro expansion will use the 'len' in the struct,
which may not be what was intended, but would nevertheless be quietly
accepted.

-bw

> Thanks.
>
> Qing
> > On Apr 14, 2025, at 13:12, Bill Wendling  wrote:
> >
> > SAfter being on a mini-vacation and thinking about this more,
> > I'm a bit less satisfied with the current proposal. The main issue is
> > that we have seemingly two lookup rules based on which attribute is
> > used (counted_by vs. counted_by_expr).
> >
> >  1. counted_by: We expect an expression that's a lone identifier.
> > Here, we use a pseudo-struct scope to resolve that identifier.
> > ("Pseudo" because it's not fully defined in the standard but created
> > for this feature alone.)
> >
> >  2. counted_by_expr: Any identifiers that appear in the struct need
> > to be forward declared. If they aren't, the normal lookup rules apply.
> >
> > Now, I don't think this will be necessarily confusing to the
> > programmer, but it's inconsistent. In other words, either 'counted_by'
> > *must* forward declare the in-structure identifier or neither must.
> >
> > It's also probable that most expressions will use in-structure
> > identifiers, with the occasional enum or macro. (I'm going off of
> > Yeoul's assertion that they've implemented this successfully on large
> > code bases and haven't had to make allowances for global identifiers.)
> >
> > My counter proposal then is to do something like this:
> >
> > 1. The syntax needs to be unambiguous.
> > 2. Identifier lookup must be consistent between the two attribute forms.
> > 3. The common use case should take the least amount of code to write.
> > (More of a "nice to have".)
> >
> > Therefore, I suggest the following rules, that are more-or-less the
> > reverse of the current proposal's rules:
> >
> > - All untagged identifiers are assumed to be within the structure. If
> > they aren't found in the struct, it's an error.
> > - All globals (i.e. identifiers not in the struct) must be referenced
> > via a special tag or a builtin (e.g. __builtin_global_ref()). The tag
> > or builtin follow current scoping rules---i.e. it may pick up a shadow
> > variable rather than the global.
> >
> > Examples:
> >
> > [Assume a builtin called '__builtin_global_ref' that takes an
> > expression where every identifier within that expression is assumed
> > "global".]
> >
> > struct A {
> >  int *buf __counted_by(len); // 'len' *must* be in the struct.
> >  int len;
> > };
> >
> > constexpr int len = 42;
> > struct B {
> >  int *buf __counted_by(__builtin_global_ref(len)); // 'len' is a global.
> > };
> >
> > enum { PADDING = 42 };
> > struct C {
> >  int *buf __counted_by_expr(len * __builtin_global_ref(PADDING));
> >  int len;
> > };
> >
> > #define PADDING_EXPR __builtin_gloal_ref(len) + 42
> > struct D {
> >  int *buf __counted_by_expr(len * PADDING_EXPR);
> >// PADDING_EXPR is expanded and that 'len' is not in the structure.
> >  int len;
> > };
> >
> > #define PADDING_EXPR len + 42
> > struct E {
> >  int *buf __counted_by_expr(len * __builtin_global_ref(PADDING_EXPR));
> >// PADDING_EXPR is expanded and that 'len' is not in the structure.
> >  int len;
> > };
> >
> > There is the issue that the __builtin_global_ref() in 'struct E' 

Re: [PATCH] aarch64: Fix CFA offsets in non-initial stack probes [PR119610]

2025-04-14 Thread Jeff Law




On 4/11/25 4:22 AM, Richard Biener wrote:

On Fri, Apr 11, 2025 at 12:18 PM Richard Sandiford
 wrote:


Richard Biener  writes:

On Fri, Apr 11, 2025 at 11:10 AM Richard Sandiford
 wrote:


Richard Biener  writes:

On Thu, Apr 10, 2025 at 10:10 PM Richard Sandiford
 wrote:


PR119610 is about incorrect CFI output for a stack probe when that
probe is not the initial allocation.  The main aarch64 stack probe
function, aarch64_allocate_and_probe_stack_space, implicitly assumed
that the incoming stack pointer pointed to the top of the frame,
and thus held the CFA.

aarch64_save_callee_saves and aarch64_restore_callee_saves use a
parameter called bytes_below_sp to track how far the stack pointer
is above the base of the static frame.  This patch does the same
thing for aarch64_allocate_and_probe_stack_space.

Also, I noticed that the SVE path was attaching the first CFA note
to the wrong instruction: it was attaching the note to the calculation
of the stack size, rather than to the r11<-sp copy.

Bootstrapped & regression-tested on aarch64-linux-gnu.  I'll push on
Monday if there are no comments before then.  I'd appreciate a second
pair of eyes though, since this is a sensitive area.


Do you happen to know if the backports to older branches you provided for
the change that triggered this issue (in particular to GCC 7) are also affected?


GCC 7 and GCC 8 should be ok.  The bug relies on stack protection being
enabled (-fstack-protector-strong for the testcase in the PR, but just
-fstack-protector for others) and that was added in GCC 9.


Hmm, I see -fstack-protector[-strong] working with GCC 7 on aarch64.


I think it's just being silently accepted as a nop.  At least:


Specifically
the testcase produces for foo():

 .text
 .align  2
 .global _Z3foov
 .type   _Z3foov, %function
_Z3foov:
.LFB0:
 .cfi_startproc
 stp x29, x30, [sp, -16]!
 .cfi_def_cfa_offset 16
 .cfi_offset 29, -16
 .cfi_offset 30, -8
 add x29, sp, 0
 .cfi_def_cfa_register 29
 sub sp, sp, #16
 sub sp, sp, #524288


...the function isn't probing the stack here.  It ought to be doing
something like the code that Alex quoted in the PR.  Compare the
GCC 8 and GCC 9 output in https://godbolt.org/z/cWbsG3eGb .


Yes, I thought that's the -fstack-clash-protection support being sub-par
(not enforced for VLA allocations).  So I wrongly assumed this is
about -fstack-protector (the __stack_chk_guard thing?)
?!? stack clash protection does support VLAs since those go through the 
standard routines to allocate stack in explow.cc IIRC.


jeff



[PUSHED 3/3] Add 'throw', dead code test cases for GCN, nvptx target and OpenACC, OpenMP 'target' offloading

2025-04-14 Thread Thomas Schwinge
gcc/testsuite/
* g++.target/gcn/exceptions-throw-3.C: New.
* g++.target/nvptx/exceptions-throw-3.C: Likewise.
libgomp/
* testsuite/libgomp.c++/target-exceptions-throw-3.C: New.
* testsuite/libgomp.oacc-c++/exceptions-throw-3.C: Likewise.
---
 .../g++.target/gcn/exceptions-throw-3.C   | 11 +
 .../g++.target/nvptx/exceptions-throw-3.C | 11 +
 .../libgomp.c++/target-exceptions-throw-3.C   | 19 
 .../libgomp.oacc-c++/exceptions-throw-3.C | 43 +++
 4 files changed, 84 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/gcn/exceptions-throw-3.C
 create mode 100644 gcc/testsuite/g++.target/nvptx/exceptions-throw-3.C
 create mode 100644 libgomp/testsuite/libgomp.c++/target-exceptions-throw-3.C
 create mode 100644 libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-3.C

diff --git a/gcc/testsuite/g++.target/gcn/exceptions-throw-3.C 
b/gcc/testsuite/g++.target/gcn/exceptions-throw-3.C
new file mode 100644
index 000..5c1ad7a8fde
--- /dev/null
+++ b/gcc/testsuite/g++.target/gcn/exceptions-throw-3.C
@@ -0,0 +1,11 @@
+/* 'throw', dead code.  */
+
+/* { dg-do run } */
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+/* { dg-additional-options -fexceptions } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+#include "../../../../libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-3.C"
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_allocate_exception, } 
1 optimized } }
+   { dg-final { scan-tree-dump-times {gimple_call <__cxa_throw, } 1 optimized 
} } */
diff --git a/gcc/testsuite/g++.target/nvptx/exceptions-throw-3.C 
b/gcc/testsuite/g++.target/nvptx/exceptions-throw-3.C
new file mode 100644
index 000..5c1ad7a8fde
--- /dev/null
+++ b/gcc/testsuite/g++.target/nvptx/exceptions-throw-3.C
@@ -0,0 +1,11 @@
+/* 'throw', dead code.  */
+
+/* { dg-do run } */
+/* Via the magic string "-std=*++" indicate that testing one (the default) C++ 
standard is sufficient.  */
+/* { dg-additional-options -fexceptions } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+#include "../../../../libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-3.C"
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_allocate_exception, } 
1 optimized } }
+   { dg-final { scan-tree-dump-times {gimple_call <__cxa_throw, } 1 optimized 
} } */
diff --git a/libgomp/testsuite/libgomp.c++/target-exceptions-throw-3.C 
b/libgomp/testsuite/libgomp.c++/target-exceptions-throw-3.C
new file mode 100644
index 000..c35180de28d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-exceptions-throw-3.C
@@ -0,0 +1,19 @@
+/* 'throw' in OpenMP 'target' region, dead code.  */
+
+/* { dg-require-effective-target exceptions }
+   { dg-additional-options -fexceptions } */
+/* { dg-additional-options -DDEFAULT=defaultmap(to) }
+   ... to avoid wrong code for offloading execution; PR119692.
+   With this, the device code still isn't correct, but the defects are in dead 
code.
+   { dg-additional-options -fdump-tree-gimple } */
+/* { dg-additional-options -fdump-tree-optimized-raw }
+   { dg-additional-options -foffload-options=-fdump-tree-optimized-raw } */
+
+#include "../libgomp.oacc-c++/exceptions-throw-3.C"
+
+/* { dg-final { scan-tree-dump-not {(?n)#pragma omp target .* defaultmap\(to\) 
map\(to:_ZTI11MyException \[len: [0-9]+\] \[runtime_implicit\]\)$} gimple { 
xfail *-*-* } } } */
+
+/* { dg-final { scan-tree-dump-times {gimple_call <__cxa_allocate_exception, } 
1 optimized } }
+   { dg-final { scan-tree-dump-times {gimple_call <__cxa_throw, } 1 optimized 
} }
+   { dg-final { scan-offload-tree-dump-times {gimple_call 
<__cxa_allocate_exception, } 1 optimized } }
+   { dg-final { scan-offload-tree-dump-times {gimple_call <__cxa_throw, } 1 
optimized } } */
diff --git a/libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-3.C 
b/libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-3.C
new file mode 100644
index 000..74a62b3abfa
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c++/exceptions-throw-3.C
@@ -0,0 +1,43 @@
+/* 'throw' in OpenACC compute region, dead code.  */
+
+/* { dg-require-effective-target exceptions }
+   { dg-additional-options -fexceptions } */
+/* Wrong code for offloading execution.
+   { dg-skip-if PR119692 { ! openacc_host_selected } }
+   { dg-additional-options -fdump-tree-gimple } */
+/* { dg-additional-options -fdump-tree-optimized-raw } */
+
+/* See also '../libgomp.c++/target-exceptions-throw-3.C'.  */
+
+/* See also '../../../gcc/testsuite/g++.target/gcn/exceptions-throw-3.C',
+   '../../../gcc/testsuite/g++.target/nvptx/exceptions-throw-3.C'.  */
+
+/* For PR119692 workarounds.  */
+#ifndef DEFAULT
+# define DEFAULT
+#endif
+
+class MyException
+{
+};
+
+int main()
+{
+#pragma omp target DEFAULT
+#pragma acc serial DEFAULT
+  /* { dg-bogus {using 'vector_length \(32\)', ignoring 1} {} { target 
openacc_nvi

Re: [PATCH] [riscv] vec_dup immediate constants in pred_broadcast expand [PR118182]

2025-04-14 Thread Jeff Law




On 4/13/25 11:03 PM, Alexandre Oliva wrote:

On Apr 12, 2025, Jeff Law  wrote:


for  gcc/ChangeLog
PR target/118182
* config/riscv/vector.md (@pred_broadcast): Expand to
_zero and _imm variants without vec_duplicate.

I'd said this should tend to wait for gcc-16 since it doesn't fix a
regression.


That works for me.

Technically, the failure now in gcc-14 is not a regression indeed, but
it may seem like one.  I have no objections to leaving the patch for
gcc-16 only, and the failure in gcc-14 is nothing but a missed
optimization, but it's a failure nevertheless.

As for the newly-backported failing test in gcc-14...  Would you rather
leave it failing-14, adjust it so as to expect the code output by
gcc-14, remove the failing test, or revert the recently-backported patch
that introduced it?  I'd be happy to go either way, but my preference
would be for adjusting the test.
No strong opinion.  I'd lean towards xfail or twiddling the test since 
that's obviously super-save WRT codegen on the gcc-14 release branch.





So just keep it in mind as you're poking around -- what you're finding
likely will show up elsewhere and I'm supportive of moving this stuff
to expansion time.


ACK, thanks for the heads up and support.  It's not like I've been
*looking* for such stuff, it's just that FAILs often catch my attention,
especially if they seem like regressions.
Understood.  Just wanted to point out something I'd seen which I think 
is relatively common.  I'd hate to see work duplicated, so better to let 
folks know what's in flight than be silent.


jeff



Fix PR lto/119792

2025-04-14 Thread Eric Botcazou
The backport of the change made for PR c/113688 onto the 14 branch a couple of 
weeks ago has seriously broken the LTO compiler for the Ada language on the 14 
branch, because it changes the GCC type system for the sake of C in a way that 
is not compatible with simple discriminated types in Ada.  To be more precise,
useless_type_conversion_p now returns true for (view-) conversions that are
needed by the rest of the compiler.

PR c/113688 is not a regression so it was agreed that the backport should be 
reverted on the 14 branch, while the status quo is kept on the mainline (and 
future 15 branch), where the change is equally problematic, until a way out is 
devised for Ada.

Tested on x86-64/Linux, applied on the 14 branch.


2025-04-14 Eric Botcazou  

PR lto/119792
Revert

Backported from master:
2024-12-12  Martin Uecker  

PR c/113688
PR c/114014
PR c/114713
PR c/117724
* tree.cc (gimple_canonical_types_compatible_p): Add exception.
(verify_type): Add exception.
lto/
* lto-common.cc (hash_canonical_type): Add exception.

-- 
Eric Botcazoudiff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc
index 7697a7d6ea0..2ce94cc3282 100644
--- a/gcc/lto/lto-common.cc
+++ b/gcc/lto/lto-common.cc
@@ -254,8 +254,7 @@ hash_canonical_type (tree type)
  checked.  */
   code = tree_code_for_canonical_type_merging (TREE_CODE (type));
   hstate.add_int (code);
-  if (!RECORD_OR_UNION_TYPE_P (type))
-hstate.add_int (TYPE_MODE (type));
+  hstate.add_int (TYPE_MODE (type));
 
   /* Incorporate common features of numerical types.  */
   if (INTEGRAL_TYPE_P (type)
@@ -333,11 +332,7 @@ hash_canonical_type (tree type)
 	&& (! DECL_SIZE (f)
 		|| ! integer_zerop (DECL_SIZE (f
 	  {
-	tree t = TREE_TYPE (f);
-	if (!TREE_CHAIN (f)
-		&& TREE_CODE (t) == ARRAY_TYPE)
-	  t = TREE_TYPE  (t);
-	iterative_hash_canonical_type (t, hstate);
+	iterative_hash_canonical_type (TREE_TYPE (f), hstate);
 	nf++;
 	  }
 
diff --git a/gcc/tree.cc b/gcc/tree.cc
index a4c62e1f068..d716d7ccfe3 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -13846,11 +13846,8 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
   || TREE_CODE (t1) == NULLPTR_TYPE)
 return true;
 
-  /* Can't be compatible types if they have different mode.  Because of
- flexible array members, we allow mismatching modes for structures or
- unions.  */
-  if (!RECORD_OR_UNION_TYPE_P (t1)
-  && TYPE_MODE (t1) != TYPE_MODE (t2))
+  /* Can't be the same type if they have different mode.  */
+  if (TYPE_MODE (t1) != TYPE_MODE (t2))
 return false;
 
   /* Non-aggregate types can be handled cheaply.  */
@@ -13901,7 +13898,7 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
 {
 case ARRAY_TYPE:
   /* Array types are the same if the element types are the same and
-	 minimum and maximum index are the same.  */
+	 the number of elements are the same.  */
   if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2),
 		trust_type_canonical)
 	  || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
@@ -13995,46 +13992,23 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
 	 f1 || f2;
 	 f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
 	  {
-	/* Skip non-fields and zero-sized fields, except zero-sized
-	   arrays at the end.  */
+	/* Skip non-fields and zero-sized fields.  */
 	while (f1 && (TREE_CODE (f1) != FIELD_DECL
 			  || (DECL_SIZE (f1)
-			  && integer_zerop (DECL_SIZE (f1))
-			  && (TREE_CHAIN (f1)
-  || TREE_CODE (TREE_TYPE (f1))
- != ARRAY_TYPE
+			  && integer_zerop (DECL_SIZE (f1)
 	  f1 = TREE_CHAIN (f1);
 	while (f2 && (TREE_CODE (f2) != FIELD_DECL
 			  || (DECL_SIZE (f2)
-			  && integer_zerop (DECL_SIZE (f2))
-			  && (TREE_CHAIN (f2)
-  || TREE_CODE (TREE_TYPE (f2))
- != ARRAY_TYPE
+			  && integer_zerop (DECL_SIZE (f2)
 	  f2 = TREE_CHAIN (f2);
 	if (!f1 || !f2)
 	  break;
-
-	tree t1 = TREE_TYPE (f1);
-	tree t2 = TREE_TYPE (f2);
-
-	/* If the last element are arrays, we only compare the element
-	   types.  */
-	if (TREE_CHAIN (f1) == NULL_TREE && TREE_CODE (t1) == ARRAY_TYPE
-		&& TREE_CHAIN (f2) == NULL_TREE && TREE_CODE (t2) == ARRAY_TYPE)
-	  {
-		/* If both arrays have zero size, this is a match.  */
-		if (DECL_SIZE (f1) && integer_zerop (DECL_SIZE (f1))
-		&& DECL_SIZE (f2) && integer_zerop (DECL_SIZE (f2)))
-		  return true;
-
-		t1 = TREE_TYPE (t1);
-		t2 = TREE_TYPE (t2);
-	  }
-
+	/* The fields must have the same name, offset and type.  */
 	if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
 		|| !gimple_compare_field_offset (f1, f2)
 		|| !gimple_canonical_types_compatible_p
-		  (t1, t2, trust_type_canonical))
+		  (TREE_TYPE (f1), TREE_TYPE (f2),
+		   trust_t

Re: [PATCH] [testsuite] [ppc] compile [PR112822] with -mvsx

2025-04-14 Thread Peter Bergner
On 4/11/25 12:57 PM, Alexandre Oliva wrote:
> diff --git a/gcc/testsuite/g++.dg/pr112822.C b/gcc/testsuite/g++.dg/pr112822.C
> index a8557522467d7..9ec5707eb4c4d 100644
> --- a/gcc/testsuite/g++.dg/pr112822.C
> +++ b/gcc/testsuite/g++.dg/pr112822.C
> @@ -1,6 +1,8 @@
>  /* PR tree-optimization/112822 */
>  /* { dg-do compile { target c++17 } } */
>  /* { dg-options "-w -O2" } */
> +/* Required for altivec double vectors.  */
> +/* { dg-additional-options "-mvsx" { target powerpc*-*-* } } */
>  
>  /* Verify we do not ICE on the following noisy creduced test case.  */

This will still have problems after Mike's patch goes in:

   https://gcc.gnu.org/pipermail/gcc-patches/2024-November/669106.html

It fixes the -mvsx option so that it does not silently promote the -mcpu=
option on you, so I don't think this is the correct fix.  The problem is
currently, if you compile with -mcpu=power4 (or any cpu without vector hw)
and then add -mvsx, we silently (and I'd say erroneously) promote your
compile to -mcpu=power7.  Mike's patch will instead give an error saying
you need a newer -mcpu= to use -mvsx.

The test case was creduced from preprocessed source, so how about we
remove the altivec attribute and instead use a more generic attribute
which should also compile into simple scalar code for old cpus that don't
have vectors?  Then we don't need -mvsx at all.  Like the below.
Does that work for you?

This is an architecture independent test case, so I'm surprised this
doesn't FAIL on non-powerpc targets since they don't know anything
about altivec.  I'd think the following fix should help them too.

Peter



diff --git a/gcc/testsuite/g++.dg/pr112822.C b/gcc/testsuite/g++.dg/pr112822.C
index a8557522467..f88bd833c92 100644
--- a/gcc/testsuite/g++.dg/pr112822.C
+++ b/gcc/testsuite/g++.dg/pr112822.C
@@ -89,7 +89,7 @@ template  struct cg { 
typedef aj cn; };
 namespace ai {
 template  cj cp;
 template  void cl(bu *cr, cj cs) { ct(cr, cs); }
-typedef __attribute__((altivec(vector__))) double co;
+typedef double co __attribute__ ((vector_size (16)));
 void ct(double *cr, co cs) { *(co *)cr = cs; }
 struct cq {
   co q;





Re: [PATCH] [testsuite] [ppc] ipa-sra-19.c: pass -Wno-psabi on powerpc-*-elf as well

2025-04-14 Thread Peter Bergner
On 4/11/25 1:01 PM, Alexandre Oliva wrote:
> Like other ppc targets, powerpc-*-elf needs -Wno-psabi to compile
> gcc.dg/ipa/ipa-sra-19.c without an undesired warning about vector
> argument passing.
> 
> Regstrapped on powerpc64le-linux-gnu.  Also tested with gcc-14 on
> x86_64-linux-x-powerpc-elf.  Ok to install?
> 
> 
> for  gcc/testsuite/ChangeLog
> 
>   * gcc.dg/ipa/ipa-sra-19.c: Add -Wno-psabi on ppc-elf too.

If you really see a warning with powerpc-*-elf, then I'd consider this
falls under the obvious rule.

Peter



[PUSHED] Add 'g++.target/gcn/gcn.exp' for GCN-specific C++ test cases

2025-04-14 Thread Thomas Schwinge
Like 'gcc.target/gcn/gcn.exp' is modeled after 'gcc.dg/dg.exp', this new
'g++.target/gcn/gcn.exp' is modeled after 'g++.dg/dg.exp'.

gcc/testsuite/
* g++.target/gcn/gcn.exp: New.
---
 gcc/testsuite/g++.target/gcn/gcn.exp | 56 
 1 file changed, 56 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/gcn/gcn.exp

diff --git a/gcc/testsuite/g++.target/gcn/gcn.exp 
b/gcc/testsuite/g++.target/gcn/gcn.exp
new file mode 100644
index 000..a3bd75f2a79
--- /dev/null
+++ b/gcc/testsuite/g++.target/gcn/gcn.exp
@@ -0,0 +1,56 @@
+# Specific regression driver for GCN.
+#   Copyright (C) 2000-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .
+
+# G++ testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a GCN target.
+if ![istarget amdgcn*-*-*] then {
+  return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CXXFLAGS
+if ![info exists DEFAULT_CXXFLAGS] then {
+set DEFAULT_CXXFLAGS " -pedantic-errors -Wno-long-long"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Recursively find files in $dir and subdirs, do not walk into subdirs
+# that contain their own .exp file.
+proc find-cxx-tests { dir suffix } {
+set tests [lsort [glob -nocomplain -directory $dir "*.$suffix" ]]
+foreach subdir [lsort [glob -nocomplain -type d -directory $dir *]] {
+   if { [glob -nocomplain -directory $subdir *.exp] eq "" } {
+   eval lappend tests [find-cxx-tests $subdir $suffix]
+   }
+}
+return $tests
+}
+
+set tests [find-cxx-tests $srcdir/$subdir {C}]
+
+# Main loop.
+g++-dg-runtest $tests "" $DEFAULT_CXXFLAGS
+
+
+# All done.
+dg-finish
-- 
2.34.1



[COMMITTED 11/19] gccrs: expansion: Desugar doc comments into attributes before expansion

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* expand/rust-macro-expand.cc (MacroExpander::expand_decl_macro): Call 
into
TokenTreeDesugar.
* expand/rust-token-tree-desugar.cc: New file.
* expand/rust-token-tree-desugar.h: New file.
* Make-lang.in: Compile them.

gcc/testsuite/ChangeLog:

* rust/compile/macros/mbe/macro-issue3709-1.rs: New test.
* rust/compile/macros/mbe/macro-issue3709-2.rs: New test.
---
 gcc/rust/Make-lang.in |  1 +
 gcc/rust/expand/rust-macro-expand.cc  |  6 +-
 gcc/rust/expand/rust-token-tree-desugar.cc| 72 +
 gcc/rust/expand/rust-token-tree-desugar.h | 55 +
 .../compile/macros/mbe/macro-issue3693.rs | 10 +++
 .../compile/macros/mbe/macro-issue3709-1.rs   | 10 +++
 .../compile/macros/mbe/macro-issue3709-2.rs   | 81 +++
 7 files changed, 234 insertions(+), 1 deletion(-)
 create mode 100644 gcc/rust/expand/rust-token-tree-desugar.cc
 create mode 100644 gcc/rust/expand/rust-token-tree-desugar.h
 create mode 100644 gcc/testsuite/rust/compile/macros/mbe/macro-issue3693.rs
 create mode 100644 gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-1.rs
 create mode 100644 gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 4028b47fa87..835e113aee2 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -115,6 +115,7 @@ GRS_OBJS = \
 rust/rust-macro-builtins-format-args.o \
 rust/rust-macro-builtins-location.o \
 rust/rust-macro-builtins-include.o \
+rust/rust-token-tree-desugar.o \
rust/rust-fmt.o \
 rust/rust-hir.o \
 rust/rust-hir-map.o \
diff --git a/gcc/rust/expand/rust-macro-expand.cc 
b/gcc/rust/expand/rust-macro-expand.cc
index 6e62a083ae7..673b8fb20fa 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -28,6 +28,7 @@
 #include "rust-cfg-strip.h"
 #include "rust-early-name-resolver.h"
 #include "rust-proc-macro.h"
+#include "rust-token-tree-desugar.h"
 
 namespace Rust {
 
@@ -78,7 +79,10 @@ MacroExpander::expand_decl_macro (location_t invoc_locus,
* trees.
*/
 
-  AST::DelimTokenTree &invoc_token_tree = invoc.get_delim_tok_tree ();
+  AST::DelimTokenTree &invoc_token_tree_sugar = invoc.get_delim_tok_tree ();
+
+  // We must first desugar doc comments into proper attributes
+  auto invoc_token_tree = AST::TokenTreeDesugar ().go (invoc_token_tree_sugar);
 
   // find matching arm
   AST::MacroRule *matched_rule = nullptr;
diff --git a/gcc/rust/expand/rust-token-tree-desugar.cc 
b/gcc/rust/expand/rust-token-tree-desugar.cc
new file mode 100644
index 000..3b471805924
--- /dev/null
+++ b/gcc/rust/expand/rust-token-tree-desugar.cc
@@ -0,0 +1,72 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-token-tree-desugar.h"
+#include "rust-ast.h"
+#include "rust-token.h"
+
+namespace Rust {
+namespace AST {
+
+DelimTokenTree
+TokenTreeDesugar::go (DelimTokenTree &tts)
+{
+  tts.accept_vis (*this);
+
+  return DelimTokenTree (tts.get_delim_type (), std::move (desugared),
+tts.get_locus ());
+}
+
+void
+TokenTreeDesugar::append (TokenPtr &&new_token)
+{
+  desugared.emplace_back (std::make_unique (std::move (new_token)));
+}
+
+void
+TokenTreeDesugar::append (std::unique_ptr &&new_token)
+{
+  desugared.emplace_back (std::move (new_token));
+}
+
+void
+TokenTreeDesugar::visit (Token &tts)
+{
+  if (tts.get_id () == TokenId::OUTER_DOC_COMMENT
+  || tts.get_id () == TokenId::INNER_DOC_COMMENT)
+{
+  append (Rust::Token::make (TokenId::HASH, tts.get_locus ()));
+
+  if (tts.get_id () == TokenId::INNER_DOC_COMMENT)
+   append (Rust::Token::make (EXCLAM, tts.get_locus ()));
+
+  append (Rust::Token::make (TokenId::LEFT_SQUARE, tts.get_locus ()));
+  append (Rust::Token::make_identifier (tts.get_locus (), "doc"));
+  append (Rust::Token::make (TokenId::EQUAL, tts.get_locus ()));
+  append (Rust::Token::make_string (tts.get_locus (),
+   std::string (tts.get_str (;
+  append (Rust::Token::make (TokenId::RIGHT_SQUARE, tts.get_locus ()));
+}
+  else
+{
+  append (tts.clone_token ());
+}
+}
+
+}; // 

[COMMITTED 09/19] gccrs: session: Desugar question mark operator after expansion instead.

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* rust-session-manager.cc (Session::compile_crate): Call the visitor 
later in the pipeline.
---
 gcc/rust/rust-session-manager.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 15f21ef12a9..48acbf34222 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -611,7 +611,6 @@ Session::compile_crate (const char *filename)
 return;
 
   AST::CollectLangItems ().go (parsed_crate);
-  AST::DesugarQuestionMark ().go (parsed_crate);
 
   auto name_resolution_ctx = Resolver2_0::NameResolutionContext ();
   // expansion pipeline stage
@@ -619,6 +618,7 @@ Session::compile_crate (const char *filename)
   expansion (parsed_crate, name_resolution_ctx);
 
   AST::DesugarForLoops ().go (parsed_crate);
+  AST::DesugarQuestionMark ().go (parsed_crate);
 
   rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m");
   if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP))
-- 
2.49.0



Re: [PATCH v2] libstdc++: Fix std::string construction from volatile char* [PR119748]

2025-04-14 Thread Tomasz Kaminski
On Mon, Apr 14, 2025 at 6:08 PM Jonathan Wakely  wrote:

> On Mon, 14 Apr 2025 at 16:25, Tomasz Kaminski  wrote:
> >
> >
> >
> > On Mon, Apr 14, 2025 at 5:06 PM Jonathan Wakely 
> wrote:
> >>
> >> My recent r15-9381-g648d5c26e25497 change assumes that a contiguous
> >> iterator with the correct value_type can be converted to a const charT*
> >> but that's not true for volatile charT*. The optimization should only be
> >> done if it can be converted to the right pointer type.
> >>
> >> Additionally, the generic loop for non-contiguous iterators needs an
> >> explicit cast to deal with iterators that have a reference type that is
> >> not explicitly convertible to charT.
> >
> > As mentioned before, we do not need to handle explicit conversion for
> CharT.
>
> Ah yes, I forgot to fix that part of the commit message.
>
> > We still need to perform static_cast to create a temporary CharT when
> passing
> > to traits::assign, as otherwise we will get a mismatch in deduction.
>
> I agree we still need to create a temporary, but there's no deduction
> involved. traits_type::assign takes charT& and const charT&, and the
> volatile charT& cannot bind to the latter.
>
> I'll change the second paragraph of the commit message to say:
>
>Additionally, some generic loops for non-contiguous iterators need an
>explicit cast to deal with iterator reference types that do not bind to
>the const charT& parameter of traits_type::assign.
>
>
>
> >> libstdc++-v3/ChangeLog:
> >>
> >> PR libstdc++/119748
> >> * include/bits/basic_string.h (_S_copy_chars): Only optimize for
> >> contiguous iterators that are convertible to const charT*. Use
> >> explicit conversion to charT after dereferencing iterator.
> >> (_S_copy_range): Likewise for contiguous ranges.
> >> * include/bits/basic_string.tcc (_M_construct): Use explicit
> >> conversion to charT after dereferencing input iterator.
> >> * include/bits/cow_string.h (_S_copy_chars): Likewise.
> >> (basic_string(from_range_t, R&&, const Allocator&)): Likewise.
> >> Only optimize for contiguous iterators that are convertible to
> >> const charT*.
> >> * testsuite/21_strings/basic_string/cons/char/119748.cc: New
> >> test.
> >> * testsuite/21_strings/basic_string/cons/wchar_t/119748.cc:
> >> New test.
> >> ---
> >>
> >> Changes in v2:
> >> - Added static_assert in _M_construct overload for input iterators.
> >> - Added tests using non-contiguous iterators.
> >>
> >>  libstdc++-v3/include/bits/basic_string.h  | 24 +---
> >>  libstdc++-v3/include/bits/basic_string.tcc|  3 +-
> >>  libstdc++-v3/include/bits/cow_string.h| 17 --
> >>  .../basic_string/cons/char/119748.cc  | 55 +++
> >>  .../basic_string/cons/wchar_t/119748.cc   |  7 +++
> >>  5 files changed, 93 insertions(+), 13 deletions(-)
> >>  create mode 100644
> libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc
> >>  create mode 100644
> libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc
> >>
> >> diff --git a/libstdc++-v3/include/bits/basic_string.h
> b/libstdc++-v3/include/bits/basic_string.h
> >> index 9c431c765ab..c90bd099b63 100644
> >> --- a/libstdc++-v3/include/bits/basic_string.h
> >> +++ b/libstdc++-v3/include/bits/basic_string.h
> >> @@ -488,8 +488,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> >>   is_same<_IterBase, const _CharT*>>::value)
> >> _S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
> >>  #if __cpp_lib_concepts
> >> - else if constexpr (contiguous_iterator<_Iterator>
> >> -  && is_same_v,
> _CharT>)
> >> + else if constexpr (requires {
> >> +  requires contiguous_iterator<_Iterator>;
> >> +  { std::to_address(__k1) }
> >> +-> convertible_to;
> >> +})
> >
> > I would prefer, but this is not a strong preference.
> >if constexpr (ranges::contiguous_range<_Rg>)
> >  if constexpr
> (convertible_to(__rg))), const
> CharT*>>)
>
> Yes, in general I would prefer that, but then the else-branch would
> bind incorrectly:
>
> if constexpr (pointer or string::iterator)
> { }
> else if constexpr (contiguous_range)
>   if constexpr (convertible to pointer)
>   { }
> else
>   for-loop
>
> And it can't be a single condition because the ranges::data call isn't
> valid unless it's a contiguous iterator.
>
> I could write it:
>
> if constexpr (pointer or string::iterator)
> { }
> else if constexpr (contiguous_range)
>   if constexpr (convertible to pointer)
>   { }
>   else
> for-loop
> else
>   for-loop
>
> Or just don't use a discarded statement for the for-loop:
>
> if constexpr (pointer or string::iterator)
> { }
> else if constexpr (contiguous_range)
>   if constexpr (convertible to pointer)
>   { }
> for-loop

[COMMITTED 14/19] gccrs: install.texi: Mention Rust requirement for building gccrs

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

Addresses PR#117869

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117869

gcc/ChangeLog:

* doc/install.texi: Add requirements for building gccrs.
---
 gcc/doc/install.texi | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index b5509ff0c86..1af0082ed77 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -350,6 +350,12 @@ documentation including the target @code{SYSTEM} 
definition module.
 If Python3 is unavailable Modula-2 documentation will include a target
 independent version of the SYSTEM modules.
 
+@item @anchor{gccrs-prerequisite}gccrs
+
+The official Rust compiler and Rust build system (cargo) are required for
+building various parts of the gccrs frontend, until gccrs can compile them
+by itself. The minimum supported Rust version is 1.49.
+
 @item A ``working'' POSIX compatible shell, or GNU bash
 
 Necessary when running @command{configure} because some
-- 
2.49.0



[committed] testsuite: Fix up ipa/pr119530.c testcase [PR119318]

2025-04-14 Thread Jakub Jelinek
Hi!

On Sat, Apr 12, 2025 at 12:19:28AM +0200, Martin Jambor wrote:
> 2025-04-11  Martin Jambor  
> 
>   PR ipa/119318
>   * gcc.dg/ipa/pr119318.c: New test.
>   * gcc.dg/ipa/pr119530.c: Likwise.

I'm seeing
+FAIL: gcc.dg/ipa/pr119530.c execution test
on i686-linux.  The problem is that when long is just 32-bit and
so is unsigned, the testcase then behaves differently and should abort.
Fixed by making the argument long long instead.
While at it, just in case I've changed type of d variable to signed char
as well just in case there is -funsigned-char 8-bit int target or something
similar.

Fixed thusly, tested on x86_64-linux and i686-linux (also with reversion
of the PR119318 ipa-cp.cc change where it FAILs on both), committed to trunk
as obvious.

2025-04-14  Jakub Jelinek  

PR ipa/119318
* gcc.dg/ipa/pr119530.c (d): Change type from char to signed char.
(e): Change argument type from long to long long.

--- gcc/testsuite/gcc.dg/ipa/pr119530.c.jj  2025-04-14 15:02:23.768540571 
+0200
+++ gcc/testsuite/gcc.dg/ipa/pr119530.c 2025-04-14 18:47:15.610079496 +0200
@@ -5,8 +5,8 @@ struct a {
   int b;
 };
 int c;
-char d;
-static int e(long f) { return f < 0; }
+signed char d;
+static int e(long long f) { return f < 0; }
 static void g(unsigned f) { c = e(~f); }
 int main() {
   int h;


Jakub



[v2] Polish 'dg-output-file' test logs (was: [PATCH] testsuite: Add support for dg-output-file directive)

2025-04-14 Thread Thomas Schwinge
Hi!

On 2025-04-13T17:15:05+0200, I wrote:
> On 2025-03-18T14:54:23+0100, Jakub Jelinek  wrote:
>> The following patch offers [...] dg-output-file
>> directive where one can supply a text file with expected output
>
>> --- gcc/doc/sourcebuild.texi.jj  2025-03-11 09:18:21.750133577 +0100
>> +++ gcc/doc/sourcebuild.texi 2025-03-18 14:41:59.253345259 +0100
>> @@ -1315,6 +1315,10 @@ Prune messages matching @var{regexp} fro
>>  @item @{ dg-output @var{regexp} [@{ target/xfail @var{selector} @}] @}
>>  This DejaGnu directive compares @var{regexp} to the combined output
>>  that the test executable writes to @file{stdout} and @file{stderr}.
>> +
>> +@item @{ dg-output-file @var{file} [@{ target/xfail @var{selector} @}] @}
>> +Compares the content of @var{file} against the combined output that the
>> +test executable writes to @file{stdout} and @file{stderr}.
>>  @end table
>
> Do we have to clarify (in documentation and/or code) what happens if both
> 'dg-output' and 'dg-output-file' are used?

>> --- gcc/testsuite/lib/gcc-dg.exp.jj  2025-03-13 14:05:09.707017142 +0100
>> +++ gcc/testsuite/lib/gcc-dg.exp 2025-03-18 14:37:32.476088575 +0100
>
>> @@ -497,6 +498,75 @@ if { [info procs ${tool}_load] != [list]
>
>> +set name [file tail [lindex ${output-file} 1]]
>
>> +fail "$name output file test"
>> +send_log "Unexpected character $c on line [expr 
>> $linenum - 1] where new-line expected\n"
>> +verbose "Failed test for output line [expr $linenum - 
>> 1]" 3
>
>> +fail "$name output file test"
>> +send_log "Output line $linenum was:\n$output_line\nShould 
>> match (from [lindex ${output-file} 1]):\n$line\n"
>> +verbose "Failed test for output line $linenum $line" 3
>
>> +fail "$name output file test"
>> +send_log "Unexpected character $c on line $linenum where 
>> and of output expected\n"
>> +verbose "Failed test for output line $linenum" 3
>
>> +pass "$name output file test"
>> +verbose "Passed test for output file [lindex ${output-file} 
>> 1]" 3
>
> OK to push the attached "Polish 'dg-output-file' test logs"?

> --- a/gcc/testsuite/lib/gcc-dg.exp
> +++ b/gcc/testsuite/lib/gcc-dg.exp
> @@ -507,8 +507,7 @@ if { [info procs ${tool}_load] != [list] \
>   set linenum 1
>   set outfile [open [lindex ${output-file} 1]]
>   set do_fail 0
> - set name [file tail [lindex ${output-file} 1]]
> - verbose "output-file args is $args program is $program" 1
> + upvar name name

OK, that would've been too simple...  It did work when testing, for
example, 'RUNTESTFLAGS=dg.exp=dg-output-file-1.c' in isolation, but
breaks when doing a full test run:

[...]
spawn [open ...]
This is a test output for ilp32 target
to verify
dg-output-file directive
ERROR: tcl error sourcing [...]/source-gcc/gcc/testsuite/gcc.dg/dg.exp.
ERROR: can't read "name": no such variable
while executing
"pass "$name output file test""
(procedure "saved_asan_gcc_load" line 90)
invoked from within
"saved_asan_gcc_load ./dg-output-file-1.exe"
("eval" body line 1)
invoked from within
"eval [list saved_asan_${tool}_load $program] $args"
(procedure "gcc_load" line 5)
invoked from within
"${tool}_load $output_file"
(procedure "saved-dg-test" line 218)
invoked from within
"saved-dg-test [...]/source-gcc/gcc/testsuite/gcc.dg/dg-output-file-1.c {} 
{ -ansi -pedantic-erro..."
("eval" body line 1)
invoked from within
"eval saved-dg-test $args "
(procedure "dg-test" line 1)
invoked from within
"dg-test $testcase $options ${default-extra-options}"
(procedure "dg-runtest" line 10)
[...]

Spot in there our dear friend 'saved_asan_${tool}_load',

"Re: Asan/Tsan Unit/Regression testing".  But even with that fixed,
there'd be legitimate uses of wrapping '${tool}_load', so we have to
support that.  Fortunately, there's 'testname-for-summary' available,
which is already used in a lot of similar cases, and takes care to
'upvar' through the levels, until it finds 'name' of 'dg-test'.  OK to
push the attached v2 "Polish 'dg-output-file' test logs"?


Grüße
 Thomas


>From 86f294b84d18facf980181d9c4caa9eee6f309e0 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge 
Date: Sun, 13 Apr 2025 16:50:37 +0200
Subject: [PATCH] Polish 'dg-output-file' test logs

Per commit r15-8260-g563e6d926d9826d76895086d0c40a29dc90d66e5
"testsuite: Add support for dg-output-file directive", this currently produces
test logs as follows:

PASS: gcc.dg/dg-output-file-1.c (test for excess errors)
PASS: dg-output-file-1-lp64.txt output file test
PASS: gcc.dg/dg-output-file-1.c execution test

PASS: cobol.dg/group2/COMP-6

[PUSHED/14 1/6] phiopt: Fix VCE moving by rewriting it into cast [PR116098]

2025-04-14 Thread Andrew Pinski
Phiopt match_and_simplify might move a well defined VCE assign statement
from being conditional to being uncondtitional; that VCE might no longer
being defined. It will need a rewrite into a cast instead.

This adds the rewriting code to move_stmt for the VCE case.
This is enough to fix the issue at hand. It should also be using 
rewrite_to_defined_overflow
but first I need to move the check to see a rewrite is needed into its own 
function
and that is causing issues (see 
https://gcc.gnu.org/pipermail/gcc-patches/2024-September/663938.html).
Plus this version is easiest to backport.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/116098

gcc/ChangeLog:

* tree-ssa-phiopt.cc (move_stmt): Rewrite VCEs from integer to integer
types to case.

gcc/testsuite/ChangeLog:

* c-c++-common/torture/pr116098-2.c: New test.
* g++.dg/torture/pr116098-1.C: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit 1f619fe25925a5f79b9c33962e7a72e1f9fa)
---
 .../c-c++-common/torture/pr116098-2.c | 46 +++
 gcc/testsuite/g++.dg/torture/pr116098-1.C | 33 +
 gcc/tree-ssa-phiopt.cc| 28 ++-
 3 files changed, 106 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/c-c++-common/torture/pr116098-2.c
 create mode 100644 gcc/testsuite/g++.dg/torture/pr116098-1.C

diff --git a/gcc/testsuite/c-c++-common/torture/pr116098-2.c 
b/gcc/testsuite/c-c++-common/torture/pr116098-2.c
new file mode 100644
index 000..614ed049171
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr116098-2.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* PR tree-optimization/116098 */
+
+
+#include 
+
+struct Value {
+int type;
+union {
+bool boolean;
+long long t;
+};
+};
+
+static struct Value s_item_mem;
+
+/* truthy was being miscompiled for the value.type==2 case,
+   because we would have a VCE from unsigned char to bool
+   that went from being conditional in the value.type==1 case
+   to unconditional when `value.type!=0`.
+   The move of the VCE from conditional to unconditional,
+   needs to changed into a convert (NOP_EXPR). */
+static bool truthy(void) __attribute__((noipa));
+static bool
+truthy(void)
+{
+struct Value value = s_item_mem;
+if (value.type == 0)
+  return 0;
+if (value.type == 1)
+  return value.boolean;
+return 1;
+}
+
+int
+main(void)
+{
+s_item_mem.type = 2;
+s_item_mem.t = -1;
+bool b1 = !truthy();
+s_item_mem.type = 1;
+s_item_mem.boolean = b1;
+bool b = truthy();
+if (b1 != b)  __builtin_abort();
+if (b) __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr116098-1.C 
b/gcc/testsuite/g++.dg/torture/pr116098-1.C
new file mode 100644
index 000..90e44a6eeed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr116098-1.C
@@ -0,0 +1,33 @@
+// { dg-do run }
+/* PR tree-optimization/116098 */
+
+
+static bool truthy(int type, unsigned char data) __attribute__((noipa));
+/* truthy was being miscompiled for the type==2 case,
+   because we would have a VCE from unsigned char to bool
+   that went from being conditional in the type==1 case
+   to unconditional when `type!=0`.
+   The move of the VCE from conditional to unconditional,
+   needs to changed into a convert (NOP_EXPR). */
+
+static bool truthy(void) __attribute__((noipa));
+static bool
+truthy(int type, unsigned char data)
+{
+if (type == 0)
+  return 0;
+if (type == 1)
+  /* Emulate what SRA does, so this can be
+tested without depending on SRA. */
+  return __builtin_bit_cast (bool, data);
+return 1;
+}
+
+int
+main(void)
+{
+bool b1 = !truthy(2, -1);
+bool b = truthy(1, b1);
+if (b1 != b)  __builtin_abort();
+if (b) __builtin_abort();
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index f01979aa003..fa8dc2c8a4e 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -728,7 +728,8 @@ empty_bb_or_one_feeding_into_p (basic_block bb,
 }
 
 /* Move STMT to before GSI and insert its defining
-   name into INSERTED_EXPRS bitmap. */
+   name into INSERTED_EXPRS bitmap.
+   Also rewrite its if it might be undefined when unconditionalized.  */
 static void
 move_stmt (gimple *stmt, gimple_stmt_iterator *gsi, auto_bitmap 
&inserted_exprs)
 {
@@ -747,6 +748,31 @@ move_stmt (gimple *stmt, gimple_stmt_iterator *gsi, 
auto_bitmap &inserted_exprs)
   gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt);
   gsi_move_before (&gsi1, gsi);
   reset_flow_sensitive_info (name);
+
+  /* Rewrite some code which might be undefined when
+ unconditionalized. */
+  if (gimple_assign_single_p (stmt))
+{
+  tree rhs = gimple_assign_rhs1 (stmt);
+  /* VCE from integral types to another integral types but with
+different precisions need to be changed into casts
+to be well defined when unconditional. */
+  if (gimple_assign_rhs_code (stmt) 

[PUSHED/14 2/6] aarch64: Fix early ra for -fno-delete-dead-exceptions [PR116927]

2025-04-14 Thread Andrew Pinski
Early-RA was considering throwing instructions as being dead and removing
them even if -fno-delete-dead-exceptions was in use. This fixes that oversight.

Built and tested for aarch64-linux-gnu.

PR target/116927

gcc/ChangeLog:

* config/aarch64/aarch64-early-ra.cc (early_ra::is_dead_insn): Insns
that throw are not dead with -fno-delete-dead-exceptions.

gcc/testsuite/ChangeLog:

* g++.dg/torture/pr116927-1.C: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit edec4bfc99744b48da3ffde1e4f39c9aceecfd42)
---
 gcc/config/aarch64/aarch64-early-ra.cc|  6 ++
 gcc/testsuite/g++.dg/torture/pr116927-1.C | 15 +++
 2 files changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/torture/pr116927-1.C

diff --git a/gcc/config/aarch64/aarch64-early-ra.cc 
b/gcc/config/aarch64/aarch64-early-ra.cc
index dd2ed762f8a..427b6a13aec 100644
--- a/gcc/config/aarch64/aarch64-early-ra.cc
+++ b/gcc/config/aarch64/aarch64-early-ra.cc
@@ -3437,6 +3437,12 @@ early_ra::is_dead_insn (rtx_insn *insn)
   if (side_effects_p (set))
 return false;
 
+  /* If we can't delete dead exceptions and the insn throws,
+ then the instruction is not dead.  */
+  if (!cfun->can_delete_dead_exceptions
+  && !insn_nothrow_p (insn))
+return false;
+
   return true;
 }
 
diff --git a/gcc/testsuite/g++.dg/torture/pr116927-1.C 
b/gcc/testsuite/g++.dg/torture/pr116927-1.C
new file mode 100644
index 000..22fa1dbd7e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr116927-1.C
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-additional-options "-fnon-call-exceptions -fno-delete-dead-exceptions" 
}
+
+// PR target/116927
+// aarch64's Early ra was removing possiblely trapping
+// floating point insn
+
+void
+foo (float f)
+{
+  try {
+f ++;
+  }catch(...)
+  {}
+}
-- 
2.43.0



[PUSHED/14 0/6] Back port a few patches to 14

2025-04-14 Thread Andrew Pinski
Backport a few of my patches from the trunk to GCC 14 release branch.
These all have been sitting on the trunk for some time now so it was time
to backport them before a release.

Andrew Pinski (6):
  phiopt: Fix VCE moving by rewriting it into cast [PR116098]
  aarch64: Fix early ra for -fno-delete-dead-exceptions [PR116927]
  backprop: Fix deleting of a phi node [PR116922]
  vec-lowering: Fix ABSU lowering [PR111285]
  match: Reject non-ssa name/min invariants in gimple_extract [PR116412]
  testcase: Add testcase for already fixed PR [PR118476]

 gcc/config/aarch64/aarch64-early-ra.cc|  6 +++
 gcc/gimple-match-exports.cc   |  6 +++
 gcc/gimple-ssa-backprop.cc| 10 +++-
 .../c-c++-common/torture/pr116098-2.c | 46 +++
 gcc/testsuite/g++.dg/torture/pr116098-1.C | 33 +
 gcc/testsuite/g++.dg/torture/pr116927-1.C | 15 ++
 gcc/testsuite/g++.dg/torture/vect-absu-1.C| 29 
 gcc/testsuite/gcc.dg/torture/pr116412-1.c |  6 +++
 gcc/testsuite/gcc.dg/torture/pr116922.c   | 19 
 gcc/testsuite/gcc.dg/torture/pr118476-1.c | 14 ++
 gcc/tree-ssa-phiopt.cc| 28 ++-
 gcc/tree-vect-generic.cc  | 10 +++-
 12 files changed, 218 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/torture/pr116098-2.c
 create mode 100644 gcc/testsuite/g++.dg/torture/pr116098-1.C
 create mode 100644 gcc/testsuite/g++.dg/torture/pr116927-1.C
 create mode 100644 gcc/testsuite/g++.dg/torture/vect-absu-1.C
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr116412-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr116922.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr118476-1.c

-- 
2.43.0



[COMMITTED 08/19] gccrs: ast: Add get_locus() to DelimTokenTree

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* ast/rust-ast.h (DelimTokenTree::get_locus): New function.
---
 gcc/rust/ast/rust-ast.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 09e0fce4f19..91611ec6a62 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1018,6 +1018,7 @@ public:
   }
 
   DelimType get_delim_type () const { return delim_type; }
+  location_t get_locus () const { return locus; }
 };
 
 /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
-- 
2.49.0



[PATCH 3/3] RISC-V: Implement TARGET_VERSION_COMPATIBLE

2025-04-14 Thread Yangyu Chen
This patch implements the TARGET_VERSION_COMPATIBLE macro for RISC-V.
It checks if the versioned callee is compatible with the versioned
caller.

Signed-off-by: Yangyu Chen 

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_version_compatible): New function.
(TARGET_VERSION_COMPATIBLE): Define to riscv_version_compatible.
---
 gcc/config/riscv/riscv.cc | 24 
 1 file changed, 24 insertions(+)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 65b82795541..30e980dbc80 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -13213,6 +13213,27 @@ riscv_compare_version_priority (tree decl1, tree decl2)
   return compare_fmv_features (mask1, mask2, prio1, prio2);
 }
 
+
+bool
+riscv_version_compatible (tree caller, tree callee)
+{
+  struct cl_target_option caller_opts;
+  struct cl_target_option callee_opts;
+  bool caller_not_def = parse_features_for_version (caller, caller_opts);
+  bool callee_not_def = parse_features_for_version (callee, callee_opts);
+
+  /* Callee must be compatible with caller when callee is default.  */
+  if (! callee_not_def)
+return true;
+
+  /* Callee must not be compatible with caller when caller is default but 
callee
+ is not.  */
+  if (! caller_not_def)
+return false;
+
+  return riscv_ext_is_subset (&caller_opts, &callee_opts);
+}
+
 /* This function returns true if FN1 and FN2 are versions of the same function,
that is, the target_version attributes of the function decls are different.
This assumes that FN1 and FN2 have the same signature.  */
@@ -14427,6 +14448,9 @@ bool need_shadow_stack_push_pop_p ()
 #undef TARGET_COMPARE_VERSION_PRIORITY
 #define TARGET_COMPARE_VERSION_PRIORITY riscv_compare_version_priority
 
+#undef TARGET_VERSION_COMPATIBLE
+#define TARGET_VERSION_COMPATIBLE riscv_version_compatible
+
 #undef TARGET_OPTION_FUNCTION_VERSIONS
 #define TARGET_OPTION_FUNCTION_VERSIONS riscv_common_function_versions
 
-- 
2.49.0



[PATCH 2/3] RISC-V: Split parse_features_for_version with cl_target_option returned

2025-04-14 Thread Yangyu Chen
In some new cases, we need to parse the features for a specific version
of the target and get the cl_target_option. This commit splits the
parse_features_for_version function to a new function that returns
the cl_target_option. The original function is kept for backward
compatibility.

Signed-off-by: Yangyu Chen 

gcc/ChangeLog:

* config/riscv/riscv.cc (parse_features_for_version): Split
parse_features_for_version with cl_target_option returned.
---
 gcc/config/riscv/riscv.cc | 60 ---
 1 file changed, 37 insertions(+), 23 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 38f3ae7cd84..65b82795541 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -13092,31 +13092,25 @@ riscv_c_mode_for_floating_type (enum tree_index ti)
   return default_mode_for_floating_type (ti);
 }
 
-/* This parses the attribute arguments to target_version in DECL and modifies
-   the feature mask and priority required to select those targets.  */
-static void
+/* This parses the attribute arguments for target_version in DECL and modifies
+   the cl_target_option &opt.  Return value indicates whether the attribute was
+   found and the arch is not default. If the attribute is not found, or the 
arch
+   is default, return false, and the res is not modified.  */
+static bool
 parse_features_for_version (tree decl,
-   struct riscv_feature_bits &res,
-   int &priority)
+   struct cl_target_option &opt)
 {
   tree version_attr = lookup_attribute ("target_version",
DECL_ATTRIBUTES (decl));
   if (version_attr == NULL_TREE)
-{
-  res.length = 0;
-  priority = 0;
-  return;
-}
+return false;
 
   const char *version_string = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE
(version_attr)));
   gcc_assert (version_string != NULL);
   if (strcmp (version_string, "default") == 0)
-{
-  res.length = 0;
-  priority = 0;
-  return;
-}
+return false;
+
   struct cl_target_option cur_target;
   cl_target_option_save (&cur_target, &global_options,
 &global_options_set);
@@ -13128,19 +13122,39 @@ parse_features_for_version (tree decl,
 
   riscv_process_target_version_attr (TREE_VALUE (version_attr),
 DECL_SOURCE_LOCATION (decl));
+  /* In case of the parse error, compilation will be aborted, thus
+ we don't need to check the return value.  */
 
-  priority = global_options.x_riscv_fmv_priority;
-  const char *arch_string = global_options.x_riscv_arch_string;
+  cl_target_option_save (&opt, &global_options,
+&global_options_set);
+
+  cl_target_option_restore (&global_options, &global_options_set,
+   &cur_target);
+  return true;
+}
+
+/* This parses the attribute arguments to target_version in DECL and modifies
+   the feature mask and priority required to select those targets.  */
+static void
+parse_features_for_version (tree decl,
+   struct riscv_feature_bits &res,
+   int &priority)
+{
+  struct cl_target_option versioned_opts;
+  bool opts_res = parse_features_for_version (decl, versioned_opts);
+  if (! opts_res)
+{
+  res.length = 0;
+  priority = 0;
+  return;
+}
+
+  priority = versioned_opts.x_riscv_fmv_priority;
+  const char *arch_string = versioned_opts.x_riscv_arch_string;
   bool parse_res
 = riscv_minimal_hwprobe_feature_bits (arch_string, &res,
  DECL_SOURCE_LOCATION (decl));
   gcc_assert (parse_res);
-
-  if (arch_string != default_opts->x_riscv_arch_string)
-free (CONST_CAST (void *, (const void *) arch_string));
-
-  cl_target_option_restore (&global_options, &global_options_set,
-   &cur_target);
 }
 
 /* Compare priorities of two feature masks.  Return:
-- 
2.49.0



[PATCH] RISC-V: Add zvfbfa and zvfofp8min intrinsic.

2025-04-14 Thread Dongyan Chen
This patch add zvfbfa and zvfofp8min intrinsic[1].
To enable GCC to recognize and process zvfbfa and zvfofp8min extensions 
correctly at compile time.

[1]https://github.com/aswaterman/riscv-misc/blob/e515758c24504cf3c16145bc763a76c59425ed1b/isa/zvfbfa.adoc

gcc/ChangeLog:

* common/config/riscv/riscv-common.cc: New intrinsic.
* config/riscv/riscv-vector-builtins.cc 
(validate_instance_type_required_extensions): Add required_ext checking for 
'zvfbfa' and 'zvfofp8min'.
* config/riscv/riscv-vector-builtins.h (RVV_REQUIRE_ELEN_OFP_8): New 
bit value for OFP8.
(enum required_ext): Add required_ext declaration for 'zvfbfa' and 
'zvfofp8min'.
(required_ext_to_isa_name): Ditto.
(required_extensions_specified): Ditto.
(struct function_group_info): Add match case for 'zvfbfa' and 
'zvfofp8min'.
* config/riscv/riscv.opt: New mask for 'zvfbfa' and 'zvfofp8min'.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/arch-45.c: New test.
* gcc.target/riscv/arch-46.c: New test.

---
 gcc/common/config/riscv/riscv-common.cc   |  9 +
 gcc/config/riscv/riscv-vector-builtins.cc | 20 
 gcc/config/riscv/riscv-vector-builtins.h  | 15 +++
 gcc/config/riscv/riscv.opt|  6 ++
 gcc/testsuite/gcc.target/riscv/arch-45.c  |  5 +
 gcc/testsuite/gcc.target/riscv/arch-46.c  |  5 +
 6 files changed, 60 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-45.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-46.c

diff --git a/gcc/common/config/riscv/riscv-common.cc 
b/gcc/common/config/riscv/riscv-common.cc
index b34409adf39c..7aaa9d92455b 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -193,12 +193,15 @@ static const riscv_implied_info_t riscv_implied_info[] =

   {"zfa", "f"},

+  {"zvfbfa", "zve32f"},
+  {"zvfbfa", "zfbfmin"},
   {"zvfbfmin", "zve32f"},
   {"zvfbfwma", "zvfbfmin"},
   {"zvfbfwma", "zfbfmin"},
   {"zvfhmin", "zve32f"},
   {"zvfh", "zve32f"},
   {"zvfh", "zfhmin"},
+  {"zvfofp8min", "zve32f"},

   {"zhinx", "zhinxmin"},
   {"zhinxmin", "zfinx"},
@@ -383,10 +386,12 @@ static const struct riscv_ext_version 
riscv_ext_version_table[] =
   {"zfbfmin",   ISA_SPEC_CLASS_NONE, 1, 0},
   {"zfh",   ISA_SPEC_CLASS_NONE, 1, 0},
   {"zfhmin",ISA_SPEC_CLASS_NONE, 1, 0},
+  {"zvfbfa",ISA_SPEC_CLASS_NONE, 0, 1},
   {"zvfbfmin",  ISA_SPEC_CLASS_NONE, 1, 0},
   {"zvfbfwma",  ISA_SPEC_CLASS_NONE, 1, 0},
   {"zvfhmin",   ISA_SPEC_CLASS_NONE, 1, 0},
   {"zvfh",  ISA_SPEC_CLASS_NONE, 1, 0},
+  {"zvfofp8min",ISA_SPEC_CLASS_NONE, 0, 2},

   {"zfa", ISA_SPEC_CLASS_NONE, 1, 0},

@@ -1676,10 +1681,12 @@ static const riscv_ext_flag_table_t 
riscv_ext_flag_table[] =
   RISCV_EXT_FLAG_ENTRY ("zve64x",   x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_64),
   RISCV_EXT_FLAG_ENTRY ("zve64f",   x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_FP_32),
   RISCV_EXT_FLAG_ENTRY ("zve64d",   x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_FP_64),
+  RISCV_EXT_FLAG_ENTRY ("zvfbfa",   x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_BF_16),
   RISCV_EXT_FLAG_ENTRY ("zvfbfmin", x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_BF_16),
   RISCV_EXT_FLAG_ENTRY ("zvfbfwma", x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_BF_16),
   RISCV_EXT_FLAG_ENTRY ("zvfhmin",  x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_FP_16),
   RISCV_EXT_FLAG_ENTRY ("zvfh", x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_FP_16),
+  RISCV_EXT_FLAG_ENTRY ("zvfofp8min",   x_riscv_vector_elen_flags, 
MASK_VECTOR_ELEN_OFP_8),

   RISCV_EXT_FLAG_ENTRY ("zvbb",   x_riscv_zvb_subext, MASK_ZVBB),
   RISCV_EXT_FLAG_ENTRY ("zvbc",   x_riscv_zvb_subext, MASK_ZVBC),
@@ -1714,10 +1721,12 @@ static const riscv_ext_flag_table_t 
riscv_ext_flag_table[] =
   RISCV_EXT_FLAG_ENTRY ("zfbfmin",  x_riscv_zf_subext, MASK_ZFBFMIN),
   RISCV_EXT_FLAG_ENTRY ("zfhmin",   x_riscv_zf_subext, MASK_ZFHMIN),
   RISCV_EXT_FLAG_ENTRY ("zfh",  x_riscv_zf_subext, MASK_ZFH),
+  RISCV_EXT_FLAG_ENTRY ("zvfbfa",   x_riscv_zf_subext, MASK_ZVFBFA),
   RISCV_EXT_FLAG_ENTRY ("zvfbfmin", x_riscv_zf_subext, MASK_ZVFBFMIN),
   RISCV_EXT_FLAG_ENTRY ("zvfbfwma", x_riscv_zf_subext, MASK_ZVFBFWMA),
   RISCV_EXT_FLAG_ENTRY ("zvfhmin",  x_riscv_zf_subext, MASK_ZVFHMIN),
   RISCV_EXT_FLAG_ENTRY ("zvfh", x_riscv_zf_subext, MASK_ZVFH),
+  RISCV_EXT_FLAG_ENTRY ("zvfofp8min",   x_riscv_zf_subext, MASK_ZVFOFP8MIN),

   RISCV_EXT_FLAG_ENTRY ("zfa", x_riscv_zfa_subext, MASK_ZFA),

diff --git a/gcc/config/riscv/riscv-vector-builtins.cc 
b/gcc/config/riscv/riscv-vector-builtins.cc
index 61dcdabbb403..290b342abc56 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -4915,6 +4915,26 @@ validate_instance_type_required_extensions (const 
rvv_type_info type,
 {
   uint64_t exts = type.required_extensions;

+  if ((exts & RVV_REQUIRE_ELEN_BF_16)
+  && !TARGET_VECTOR_ELEN_BF_16_P

Re: [PATCH] Locality cloning pass (was: Introduce -flto-partition=locality)

2025-04-14 Thread Kyrylo Tkachov
Hi Honza,

> On 13 Apr 2025, at 23:19, Jan Hubicka  wrote:
> 
>> +@opindex fipa-reorder-for-locality
>> +@item -fipa-reorder-for-locality
>> +Group call chains close together in the binary layout to improve code code
>> +locality.  This option is incompatible with an explicit
>> +@option{-flto-partition=} option since it enforces a custom partitioning
>> +scheme.
> 
> Please also cross-link this with -fprofile-reorder-functions and
> -freorder-functions, which does similar thing.
> If you see how to clean-up the description of the other two so user is
> not confused. 
> 
> Perhaps say that -freorder-functions only partitions functions into
> never-executed/cold/normal/hot and -fprofile-reroder-functions is aiming
> for program startup optimization (it reorders by measured first time the
> function is executed.  By accident it seems to kind of work for
> locality.

Yeah, the option names are quite similar aren't they?
I’ve attempted to disambiguate them a bit in their description.
I’m attaching a diff from the previous version (as the full updated patch) to 
make it easier to see what’s adjusted.


> 
>> +
>> +/* Helper function of to accumulate call counts.  */
>> +static bool
>> +accumulate_profile_counts_after_cloning (cgraph_node *node, void *data)
>> +{
>> +  struct profile_stats *stats = (struct profile_stats *) data;
>> +  for (cgraph_edge *e = node->callers; e; e = e->next_caller)
>> +{
>> +  if (e->caller == stats->target)
>> + {
>> +  if (stats->rec_count.compatible_p (e->count.ipa ()))
>> +stats->rec_count += e->count.ipa ();
>> + }
>> +  else
>> + {
>> +  if (stats->nonrec_count.compatible_p (e->count.ipa ()))
>> +stats->nonrec_count += e->count.ipa ();
>> + }
> In case part of profile is missing (which may happen if one unit has -O0
> or so) , we may have counts to be uninitialized. Uninitialized counts are
> compatible with everything, but any arithmetics with it will produce
> uninitialized result which will likely confuse code later.  So I would
> skip edges with uninitialized counts.
> 
> On the other hand ipa counts are always compatible, so compatible_p
> should be redundat. Main reaosn for existence of compatible_p is that we
> can have local profiles that are 0 or unknown at IPA level.  The ipa ()
> conversion turns all counts into IPA counts and those are compatible
> with each other.
> 
> I suppose compatibe_p test is there since the code ICEd in past,but I
> think it was because of missing ipa() conversion.
> 
> 
>> +}
>> +  return false;
>> +}
>> +
>> +/* NEW_NODE is a previously created clone of ORIG_NODE already present in
>> +   current partition.  EDGES contains newly redirected edges to NEW_NODE.
>> +   Adjust profile information for both nodes and the edge.  */
>> +
>> +static void
>> +adjust_profile_info_for_non_self_rec_edges (auto_vec &edges,
>> +cgraph_node *new_node,
>> +cgraph_node *orig_node)
>> +{
>> +  profile_count orig_node_count = orig_node->count.ipa ();
>> +  profile_count edge_count = profile_count::zero ();
>> +  profile_count final_new_count = profile_count::zero ();
>> +  profile_count final_orig_count = profile_count::zero ();
>> +
>> +  for (unsigned i = 0; i < edges.length (); ++i)
>> +edge_count += edges[i]->count.ipa ();
> Here I would again skip uninitialized.  It is probably legal for -O0
> function to end up in partition.
>> +
>> +  final_orig_count = orig_node_count - edge_count;
>> +
>> +  /* NEW_NODE->count was adjusted for other callers when the clone was
>> + first created.  Just add the new edge count.  */
>> +  if (new_node->count.compatible_p (edge_count))
>> +final_new_count = new_node->count + edge_count;
> And here compatible_p should be unnecesary.
>> +/* Accumulate frequency of all edges from EDGE->caller to EDGE->callee.  */
>> +
>> +static sreal
>> +accumulate_incoming_edge_frequency (cgraph_edge *edge)
>> +{
>> +  sreal count = 0;
>> +  struct cgraph_edge *e;
>> +  for (e = edge->callee->callers; e; e = e->next_caller)
>> +{
>> +  /* Make a local decision about all edges for EDGE->caller but not the
>> + other nodes already in the partition.  Their edges will be visited
>> + later or may have been visited before and not fit the
>> + cut-off criteria.  */
>> +  if (e->caller == edge->caller)
>> + {
>> +  profile_count caller_count = e->caller->inlined_to
>> + ? e->caller->inlined_to->count
>> + : e->caller->count;
>> +  if (e->count.compatible_p (caller_count))
> Here again compatiblity check should not be necessary, since the counts
> belong to one function body (after inlining) and should be compatible.
> inliner calls e->sreal_frequency all the time withotu further checks.
> 

Yeah, I’ve adjusted these uses and used checks for initialized_p where you 
highlighted.
Indeed it seems to work with a profiled bootstrap and the ICEs we were seeing 
earlier in development aren’t appearing.

> Patch is OK with these changes. I apologize for letting the review slip
> for so long.  I was s

Re: [PATCH 0/3] Redirect to specific target based on TARGET_VERSION_COMPATIBLE

2025-04-14 Thread Yangyu Chen



> On 14 Apr 2025, at 19:06, Alfie Richards  wrote:
> 
> Hi Yangyu,
> 
> This looks great with what we discussed previously.
> 
> I have a very similar patch that implements a slightly stronger optimisation 
> that I was about to send. It makes use of information if the caller is 
> versioned. I will share this with you shortly and we can work out what we 
> wish to use?

Sure! Thank you!

Thanks,
Yangyu Chen

> 
> Kind regards,
> Alfie
> 
> On 14/04/2025 10:00, Yangyu Chen wrote:
>> This patchset implements a new feature to redirect to a specific target
>> based on the TARGET_VERSION_COMPATIBLE macro. This allows for more
>> precise FMV callee selection and better performance for certain
>> architectures. Especially for those callee that needs to be inlined,
>> this patchset can help to avoid unnecessary function calls and improve
>> performance. The idea comes from the previous dicussion on the
>> gcc-patches mailing list [1].
>> Additionally, this patchset also includes a implementation of
>> TARGET_VERSION_COMPATIBLE for RISC-V, which allows for more
>> flexibility in selecting the target version for RISC-V architectures.
>> [1] https://patchwork.sourceware.org/comment/197172/
>> Yangyu Chen (3):
>>   Redirect to specific target based on TARGET_VERSION_COMPATIBLE
>>   RISC-V: Split parse_features_for_version with cl_target_option
>> returned
>>   RISC-V: Implement TARGET_VERSION_COMPATIBLE
>>  gcc/config/riscv/riscv.cc | 84 ---
>>  gcc/doc/tm.texi   |  7 
>>  gcc/doc/tm.texi.in|  2 +
>>  gcc/multiple_target.cc| 58 +--
>>  gcc/target.def| 12 ++
>>  5 files changed, 118 insertions(+), 45 deletions(-)
> 



[COMMITTED 03/19] rust: use range for inside rust-gcc.cc [PR119341]

2025-04-14 Thread arthur . cohen
From: Andrew Pinski 

There are some places inside rust-gcc.cc which are candidates
to use range for instead of iterators directly. This changes
the locations I saw and makes the code slightly more readable.

gcc/rust/ChangeLog:

PR rust/119341
* rust-gcc.cc (function_type): Use range fors.
(function_type_variadic): Likewise.
(fill_in_fields): Likewise.
(statement_list): Likewise.
(block): Likewise.
(block_add_statements): Likewise.
(function_set_parameters): Likewise.
(write_global_definitions): Likewise.

Signed-off-by: Andrew Pinski 
---
 gcc/rust/rust-gcc.cc | 57 
 1 file changed, 21 insertions(+), 36 deletions(-)

diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 13b7cea6a3f..bd1f13920bf 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -478,10 +478,9 @@ function_type (const typed_identifier &receiver,
   pp = &TREE_CHAIN (*pp);
 }
 
-  for (std::vector::const_iterator p = parameters.begin ();
-   p != parameters.end (); ++p)
+  for (const auto &p : parameters)
 {
-  tree t = p->type;
+  tree t = p.type;
   if (error_operand_p (t))
return error_mark_node;
   *pp = tree_cons (NULL_TREE, t, NULL_TREE);
@@ -527,10 +526,9 @@ function_type_variadic (const typed_identifier &receiver,
   if (receiver.type != NULL_TREE)
 args[offs++] = receiver.type;
 
-  for (std::vector::const_iterator p = parameters.begin ();
-   p != parameters.end (); ++p)
+  for (const auto &p : parameters)
 {
-  tree t = p->type;
+  tree t = p.type;
   if (error_operand_p (t))
return error_mark_node;
   args[offs++] = t;
@@ -609,14 +607,13 @@ fill_in_fields (tree fill, const 
std::vector &fields,
 {
   tree field_trees = NULL_TREE;
   tree *pp = &field_trees;
-  for (std::vector::const_iterator p = fields.begin ();
-   p != fields.end (); ++p)
+  for (const auto &p : fields)
 {
-  tree name_tree = get_identifier_from_string (p->name);
-  tree type_tree = p->type;
+  tree name_tree = get_identifier_from_string (p.name);
+  tree type_tree = p.type;
   if (error_operand_p (type_tree))
return error_mark_node;
-  tree field = build_decl (p->location, FIELD_DECL, name_tree, type_tree);
+  tree field = build_decl (p.location, FIELD_DECL, name_tree, type_tree);
   DECL_CONTEXT (field) = fill;
   *pp = field;
   pp = &DECL_CHAIN (field);
@@ -1741,10 +1738,8 @@ tree
 statement_list (const std::vector &statements)
 {
   tree stmt_list = NULL_TREE;
-  for (std::vector::const_iterator p = statements.begin ();
-   p != statements.end (); ++p)
+  for (tree t : statements)
 {
-  tree t = (*p);
   if (error_operand_p (t))
return error_mark_node;
   append_to_statement_list (t, &stmt_list);
@@ -1798,10 +1793,9 @@ block (tree fndecl, tree enclosing, const 
std::vector &vars,
 }
 
   tree *pp = &BLOCK_VARS (block_tree);
-  for (std::vector::const_iterator pv = vars.begin ();
-   pv != vars.end (); ++pv)
+  for (Bvariable *bv : vars)
 {
-  *pp = (*pv)->get_decl ();
+  *pp = bv->get_decl ();
   if (!error_operand_p (*pp))
pp = &DECL_CHAIN (*pp);
 }
@@ -1821,10 +1815,8 @@ void
 block_add_statements (tree bind_tree, const std::vector &statements)
 {
   tree stmt_list = NULL_TREE;
-  for (std::vector::const_iterator p = statements.begin ();
-   p != statements.end (); ++p)
+  for (tree s : statements)
 {
-  tree s = (*p);
   if (!error_operand_p (s))
append_to_statement_list (s, &stmt_list);
 }
@@ -2268,10 +2260,9 @@ function_set_parameters (tree function,
 
   tree params = NULL_TREE;
   tree *pp = ¶ms;
-  for (std::vector::const_iterator pv = param_vars.begin ();
-   pv != param_vars.end (); ++pv)
+  for (Bvariable *bv : param_vars)
 {
-  *pp = (*pv)->get_decl ();
+  *pp = bv->get_decl ();
   gcc_assert (!error_operand_p (*pp));
   pp = &DECL_CHAIN (*pp);
 }
@@ -2297,10 +2288,9 @@ write_global_definitions (const std::vector 
&type_decls,
 
   // Convert all non-erroneous declarations into Gimple form.
   size_t i = 0;
-  for (std::vector::const_iterator p = variable_decls.begin ();
-   p != variable_decls.end (); ++p)
+  for (Bvariable *bv : variable_decls)
 {
-  tree v = (*p)->get_decl ();
+  tree v = bv->get_decl ();
   if (error_operand_p (v))
continue;
   defs[i] = v;
@@ -2308,10 +2298,8 @@ write_global_definitions (const std::vector 
&type_decls,
   ++i;
 }
 
-  for (std::vector::const_iterator p = type_decls.begin ();
-   p != type_decls.end (); ++p)
+  for (tree type_tree : type_decls)
 {
-  tree type_tree = (*p);
   if (!error_operand_p (type_tree) && IS_TYPE_OR_DECL_P (type_tree))
{
  defs[i] = TYPE_NAME (type_tree);
@@ -2320,20 +2308,17 @@ write_global_definitions (const std::vector 
&type_

[COMMITTED 07/19] gccrs: ast: Support outer attributes for AST::RangeExpr

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* ast/rust-expr.h (class RangeExpr): Add empty outer attributes and 
allow getting them
and setting them.
---
 gcc/rust/ast/rust-expr.h | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 84cdfdb4678..69538df63e5 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -3004,6 +3004,10 @@ class RangeExpr : public ExprWithoutBlock
 {
   location_t locus;
 
+  // Some visitors still check for attributes on RangeExprs, and they will need
+  // to be supported in the future - so keep that for now
+  std::vector empty_attributes = {};
+
 protected:
   // outer attributes not allowed before range expressions
   RangeExpr (location_t locus) : locus (locus) {}
@@ -3013,15 +3017,11 @@ public:
 
   std::vector &get_outer_attrs () override final
   {
-// RangeExpr cannot have any outer attributes
-rust_assert (false);
+return empty_attributes;
   }
 
   // should never be called - error if called
-  void set_outer_attrs (std::vector /* new_attrs */) override
-  {
-rust_assert (false);
-  }
+  void set_outer_attrs (std::vector /* new_attrs */) override {}
 
   Expr::Kind get_expr_kind () const override { return Expr::Kind::Range; }
 };
-- 
2.49.0



[COMMITTED 02/19] rust: Use error_operand_p in rust-gcc.cc

2025-04-14 Thread arthur . cohen
From: Andrew Pinski 

Just a simple cleanupof the code to use error_operand_p
instead of directly comparing against error_mark_node.

This also moves some cdoe around when dealing with error_operand_p
just to be faster and/or slightly tighten up the code slightly.

gcc/rust/ChangeLog:

* rust-gcc.cc (Bvariable::get_tree): Use error_operand_p.
(pointer_type): Likewise.
(reference_type): Likewise.
(immutable_type): Likewise.
(function_type): Likewise.
(function_type_variadic): Likewise.
Cleanup the check for receiver.type first.
(function_ptr_type): Use error_operand_p.
(fill_in_fields): Likewise.
(fill_in_array): Likewise.
(named_type): Likewise.
(type_size): Likewise.
(type_alignment): Likewise.
(type_field_alignment): Likewise.
(type_field_offset): Likewise.
(zero_expression): Likewise.
(float_constant_expression): Likewise.
(convert_expression): Likewise.
(struct_field_expression): Likewise.
(compound_expression): Likewise.
(conditional_expression): Likewise.
(negation_expression): Likewise.
(arithmetic_or_logical_expression): Likewise.
(arithmetic_or_logical_expression_checked): Likewise.
(comparison_expression): Likewise.
(lazy_boolean_expression): Likewise.
(constructor_expression): Likewise.
(array_constructor_expression): Likewise.
(array_index_expression): Likewise.
(call_expression): Likewise.
(init_statement): Likewise.
(assignment_statement): Likewise.
(return_statement): Likewise.
(exception_handler_statement): Likewise.
(if_statement): Likewise.
(compound_statement): Likewise.
Tighten up the code, removing t variable.
(statement_list): Use error_operand_p.
(block): Likewise.
(block_add_statements): Likewise.
(convert_tree): Likewise.
(global_variable): Likewise.
(global_variable_set_init): Likewise.
(local_variable): Likewise.
(parameter_variable): Likewise.
(static_chain_variable): Likewise.
(temporary_variable): Likewise.
(function): Likewise. Tighten up the code.
(function_defer_statement): Use error_operand_p.
(function_set_parameters): Use error_operand_p.
(write_global_definitions): Use error_operand_p.
Tighten up the code around the loop.

Signed-off-by: Andrew Pinski 
---
 gcc/rust/rust-gcc.cc | 189 ---
 1 file changed, 88 insertions(+), 101 deletions(-)

diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 7c5af211bbc..13b7cea6a3f 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -61,7 +61,7 @@
 tree
 Bvariable::get_tree (location_t location) const
 {
-  if (this->t_ == error_mark_node)
+  if (error_operand_p (this->t_))
 return error_mark_node;
 
   TREE_USED (this->t_) = 1;
@@ -431,7 +431,7 @@ float_type (int bits)
 tree
 pointer_type (tree to_type)
 {
-  if (to_type == error_mark_node)
+  if (error_operand_p (to_type))
 return error_mark_node;
   tree type = build_pointer_type (to_type);
   return type;
@@ -442,7 +442,7 @@ pointer_type (tree to_type)
 tree
 reference_type (tree to_type)
 {
-  if (to_type == error_mark_node)
+  if (error_operand_p (to_type))
 return error_mark_node;
   tree type = build_reference_type (to_type);
   return type;
@@ -453,7 +453,7 @@ reference_type (tree to_type)
 tree
 immutable_type (tree base)
 {
-  if (base == error_mark_node)
+  if (error_operand_p (base))
 return error_mark_node;
   tree constified = build_qualified_type (base, TYPE_QUAL_CONST);
   return constified;
@@ -472,7 +472,7 @@ function_type (const typed_identifier &receiver,
   if (receiver.type != NULL_TREE)
 {
   tree t = receiver.type;
-  if (t == error_mark_node)
+  if (error_operand_p (t))
return error_mark_node;
   *pp = tree_cons (NULL_TREE, t, NULL_TREE);
   pp = &TREE_CHAIN (*pp);
@@ -482,7 +482,7 @@ function_type (const typed_identifier &receiver,
p != parameters.end (); ++p)
 {
   tree t = p->type;
-  if (t == error_mark_node)
+  if (error_operand_p (t))
return error_mark_node;
   *pp = tree_cons (NULL_TREE, t, NULL_TREE);
   pp = &TREE_CHAIN (*pp);
@@ -502,11 +502,11 @@ function_type (const typed_identifier &receiver,
   gcc_assert (result_struct != NULL);
   result = result_struct;
 }
-  if (result == error_mark_node)
+  if (error_operand_p (result))
 return error_mark_node;
 
   tree fntype = build_function_type (result, args);
-  if (fntype == error_mark_node)
+  if (error_operand_p (fntype))
 return error_mark_node;
 
   return build_pointer_type (fntype);
@@ -521,21 +521,17 @@ function_type_variadic (const typed_identifier &receiver,
   size_t n = parameters.size () + (receiver.type != NULL_TR

[COMMITTED 06/19] gccrs: nr2.0: Do not resolve modules this run if they are unloaded

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

Instead, mark the visitor as dirty and wait for the next round of the fixed 
point to take care of
them. This avoids issues with module items being loaded while not being 
stripped yet.

gcc/rust/ChangeLog:

* resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Return 
if module
is unloaded.
---
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index 8863be768a1..ba37dee88fa 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -113,7 +113,17 @@ TopLevel::visit (AST::Module &module)
   // This was copied from the old early resolver method
   // 'accumulate_escaped_macros'
   if (module.get_kind () == AST::Module::UNLOADED)
-module.load_items ();
+{
+  module.load_items ();
+
+  // If the module was previously unloaded, then we don't want to visit it
+  // this time around as the CfgStrip hasn't run on its inner items yet.
+  // Skip it for now, mark the visitor as dirty and try again
+
+  dirty = true;
+
+  return;
+}
 
   DefaultResolver::visit (module);
 
-- 
2.49.0



Re: [PATCH] pretty-print, expand: Print [must tail call] for CALL_EXPRs and fix up maybe_complain_about_tail_call [PR119718]

2025-04-14 Thread Richard Biener



> Am 14.04.2025 um 17:47 schrieb Jakub Jelinek :
> 
> Hi!
> 
> Andrew P. mentioned earlier he'd like to see in the dump files a note
> whether it was a failed must tail call or not.
> We already print that on the tailc/musttail pass side, because
> print_gimple_stmt prints [must tail call] after the musttail calls.
> The first hunk below does it for GENERIC CALL_EXPRs too (which is needed
> for the expand diagnostics).  That isn't enough though, because the
> error on it was done first and then CALL_EXPR_MUST_TAIL_CALL flag was
> cleared, so the dump didn't have it anymore.  I've reordered the
> dump printing with error, so that it works properly.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok

Richard 

> 2025-04-14  Jakub Jelinek  
> 
>PR tree-optimization/119718
>* tree-pretty-print.cc (dump_generic_node) : Dump
>also CALL_EXPR_MUST_TAIL_CALL flag.
>* calls.cc (maybe_complain_about_tail_call): Emit error about
>CALL_EXPR_MUST_TAIL_CALL only after emitting dump message, not before
>it.
> 
> --- gcc/tree-pretty-print.cc.jj2025-04-12 13:09:55.367024475 +0200
> +++ gcc/tree-pretty-print.cc2025-04-14 08:58:21.480256810 +0200
> @@ -3201,6 +3201,8 @@ dump_generic_node (pretty_printer *pp, t
>pp_string (pp, " [return slot optimization]");
>   if (CALL_EXPR_TAILCALL (node))
>pp_string (pp, " [tail call]");
> +  if (CALL_EXPR_MUST_TAIL_CALL (node))
> +pp_string (pp, " [must tail call]");
>   break;
> 
> case WITH_CLEANUP_EXPR:
> --- gcc/calls.cc.jj2025-04-12 13:12:53.788557966 +0200
> +++ gcc/calls.cc2025-04-14 09:00:00.939905377 +0200
> @@ -1273,11 +1273,6 @@ void
> maybe_complain_about_tail_call (tree call_expr, const char *reason)
> {
>   gcc_assert (TREE_CODE (call_expr) == CALL_EXPR);
> -  if (CALL_EXPR_MUST_TAIL_CALL (call_expr))
> -{
> -  error_at (EXPR_LOCATION (call_expr), "cannot tail-call: %s", reason);
> -  CALL_EXPR_MUST_TAIL_CALL (call_expr) = 0;
> -}
>   if (CALL_EXPR_TAILCALL (call_expr)
>   && dump_file
>   && (dump_flags & TDF_DETAILS))
> @@ -1286,6 +1281,11 @@ maybe_complain_about_tail_call (tree cal
>   print_generic_expr (dump_file, call_expr, TDF_SLIM);
>   fprintf (dump_file, "\n");
> }
> +  if (CALL_EXPR_MUST_TAIL_CALL (call_expr))
> +{
> +  error_at (EXPR_LOCATION (call_expr), "cannot tail-call: %s", reason);
> +  CALL_EXPR_MUST_TAIL_CALL (call_expr) = 0;
> +}
> }
> 
> /* Fill in ARGS_SIZE and ARGS array based on the parameters found in
> 
>Jakub
> 


[PUSHED] testcase: Add testcase for already fixed PR [PR118476]

2025-04-14 Thread Andrew Pinski
This testcase was fixed by r15-3052-gc7b76a076cb2c6ded but is
a testcase that failed in a different fashion and a much older
failure than the one added with r15-3052.

Pushed as obvious after a quick test.

PR tree-optimization/118476

gcc/testsuite/ChangeLog:

* gcc.dg/torture/pr118476-1.c: New test.

Signed-off-by: Andrew Pinski 
---
 gcc/testsuite/gcc.dg/torture/pr118476-1.c | 14 ++
 1 file changed, 14 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr118476-1.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr118476-1.c 
b/gcc/testsuite/gcc.dg/torture/pr118476-1.c
new file mode 100644
index 000..33509403b61
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr118476-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+/* PR tree-optimization/118476 */
+
+typedef unsigned long long poly64x1 
__attribute__((__vector_size__(1*sizeof(long long;
+
+poly64x1 vext_p64(poly64x1 a, poly64x1 b, const int n)
+{
+  poly64x1 r = a;
+  unsigned src = (unsigned)n;
+  long long t = b[0];
+  r[0] = (src < 1) ? a[src] : t;
+  return r;
+}
-- 
2.43.0



[PATCH] cobol: Fix -fmax-errors option [PR119776]

2025-04-14 Thread Jakub Jelinek
Hi!

There seems to be inconsistency in the -fmax-errors option
naming.  It is a generic option in common.opt (so applies
to all languages) but with the = character in it.
The gcobol.1 man page in one spot documents the generic
option (in the syntax, -fmax-errors=nerror) but in another
spot without the = character.

In common.opt it is
fmax-errors=
Common Joined RejectNegative UInteger Var(flag_max_errors)
-fmax-errors=   Maximum number of errors to report.

I hope the cobol addition is just a mistake, having -fmax-errors variant
without = character when Joined Separate would allow to specify
-fmax-errors 10 with the same meaning as -fmax-errors=10
but also -fmax-errors10 with the same meaning which is just weird.
Also, there is no UInteger and RejectNegative on it, so one can
also specific -fno-max-errors42 or -fmax-errors blah.

So, unless the spelling without = is intentional, here is a patch
to just remove it, the common option already should have arranged
for flag_max_errors to be set to the right number.

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

Or if it is intentional, I guess we'd need to at least add
RejectNegative UInteger (plus using atoi is generally undesirable
anywhere in the compiler because it does no error checking).
And the man page would need to be updated to specify both forms.

2025-04-14  Jakub Jelinek  

PR cobol/119776
* lang.opt (fmax-errors): Remove.
* lang.opt.urls: Regenerate.
* cobol1.cc (cobol_langhook_handle_option) :
Remove.
* gcobol.1: Document -fmax-errors=nerror rather than
-fmax-errors nerror.

--- gcc/cobol/lang.opt.jj   2025-04-14 11:08:31.808821317 +0200
+++ gcc/cobol/lang.opt  2025-04-14 11:20:52.369700721 +0200
@@ -89,10 +89,6 @@ finternal-ebcdic
 Cobol Var(cobol_ebcdic, 1) Init(0)
 -finternal-ebcdic  Internal processing is in EBCDIC Code Page 1140
 
-fmax-errors
-Cobol Joined Separate
-; Documented in C
-
 fstatic-call
 Cobol Var(cobol_static_call, 1) Init(1)
 Enable/disable static linkage for CALL literals
--- gcc/cobol/lang.opt.urls.jj  2025-04-14 10:57:06.579176798 +0200
+++ gcc/cobol/lang.opt.urls 2025-04-14 11:21:03.157553577 +0200
@@ -16,9 +16,6 @@ LangUrlSuffix_Fortran(gfortran/Fortran-D
 ffree-form
 LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-ffree-form)
 
-fmax-errors
-UrlSuffix(gcc/Warning-Options.html#index-fmax-errors) 
LangUrlSuffix_D(gdc/Warnings.html#index-fmax-errors)
-
 iprefix
 UrlSuffix(gcc/Directory-Options.html#index-iprefix) 
LangUrlSuffix_D(gdc/Directory-Options.html#index-iprefix) 
LangUrlSuffix_Fortran(gfortran/Preprocessing-Options.html#index-iprefix)
 
--- gcc/cobol/cobol1.cc.jj  2025-04-14 11:09:22.619126924 +0200
+++ gcc/cobol/cobol1.cc 2025-04-14 11:32:51.177896287 +0200
@@ -385,10 +385,6 @@ cobol_langhook_handle_option (size_t sco
 return true;
 }
 
-case OPT_fmax_errors:
-flag_max_errors = atoi(arg);
-return true;
-
 case OPT_ffixed_form:
 cobol_set_indicator_column(-7);
 return true;
--- gcc/cobol/gcobol.1.jj   2025-04-08 14:08:48.595318840 +0200
+++ gcc/cobol/gcobol.1  2025-04-14 11:19:17.017003687 +0200
@@ -224,7 +224,7 @@ had appeared.
 Not all exception conditions are implemented.  Any that are not
 produce a warning message.
 .
-.It Fl fmax-errors Ar nerror
+.It Fl fmax-errors Ns Li = Ns Ar nerror
 .Ar nerror
 represents the number of error messages produced.  Without this option,
 .Nm


Jakub



[COMMITTED 12/19] gccrs: format_args: Allow extraneous commas, improve safety

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* expand/rust-macro-builtins-format-args.cc 
(format_args_parse_arguments): Improve safety,
allow extra commas after end of argument list.

gcc/testsuite/ChangeLog:

* rust/compile/format_args_extra_comma.rs: New test.
---
 .../expand/rust-macro-builtins-format-args.cc |  7 +++
 .../rust/compile/format_args_extra_comma.rs   | 47 +++
 2 files changed, 54 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/format_args_extra_comma.rs

diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc 
b/gcc/rust/expand/rust-macro-builtins-format-args.cc
index 8eb32d5f1b3..3e1249d3d36 100644
--- a/gcc/rust/expand/rust-macro-builtins-format-args.cc
+++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc
@@ -55,6 +55,8 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
   if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
 format_expr = parser.parse_literal_expr ();
 
+  rust_assert (format_expr);
+
   // TODO(Arthur): Clean this up - if we haven't parsed a string literal but a
   // macro invocation, what do we do here? return a tl::unexpected?
   auto format_str = static_cast (*format_expr)
@@ -81,6 +83,11 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
 {
   parser.skip_token (COMMA);
 
+  // Check in case of an extraneous comma in the args list, which is
+  // allowed - format_args!("fmt", arg, arg2,)
+  if (parser.peek_current_token ()->get_id () == last_token_id)
+   break;
+
   if (parser.peek_current_token ()->get_id () == IDENTIFIER
  && parser.peek (1)->get_id () == EQUAL)
{
diff --git a/gcc/testsuite/rust/compile/format_args_extra_comma.rs 
b/gcc/testsuite/rust/compile/format_args_extra_comma.rs
new file mode 100644
index 000..fcc435c074c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/format_args_extra_comma.rs
@@ -0,0 +1,47 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! format_args {
+() => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+pub mod core {
+pub mod fmt {
+pub struct Formatter;
+pub struct Result;
+
+pub struct Arguments<'a>;
+
+impl<'a> Arguments<'a> {
+pub fn new_v1(_: &'a [&'static str], _: &'a [ArgumentV1<'a>]) -> 
Arguments<'a> {
+Arguments
+}
+}
+
+pub struct ArgumentV1<'a>;
+
+impl<'a> ArgumentV1<'a> {
+pub fn new<'b, T>(_: &'b T, _: fn(&T, &mut Formatter) -> Result) 
-> ArgumentV1 {
+ArgumentV1
+}
+}
+
+pub trait Display {
+fn fmt(&self, _: &mut Formatter) -> Result;
+}
+
+impl Display for i32 {
+fn fmt(&self, _: &mut Formatter) -> Result {
+// { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+Result
+}
+}
+}
+}
+
+fn main() {
+let _formatted = format_args!("extra commas {} {}", 15, 14,);
+}
-- 
2.49.0



[COMMITTED 16/19] gccrs: attributes: Add missing attributes used in `core`

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* util/rust-attribute-values.h: Add missing attributes.
* util/rust-attributes.cc: Likewise.
* util/rust-attributes.h (enum CompilerPass): Mention adding something 
for const
functions.
---
 gcc/rust/util/rust-attribute-values.h | 24 
 gcc/rust/util/rust-attributes.cc  | 20 +++-
 gcc/rust/util/rust-attributes.h   |  2 ++
 3 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/util/rust-attribute-values.h 
b/gcc/rust/util/rust-attribute-values.h
index d579fa29801..50ccb4ab6dc 100644
--- a/gcc/rust/util/rust-attribute-values.h
+++ b/gcc/rust/util/rust-attribute-values.h
@@ -40,12 +40,14 @@ public:
   static constexpr auto &NO_MANGLE = "no_mangle";
   static constexpr auto &REPR = "repr";
   static constexpr auto &RUSTC_BUILTIN_MACRO = "rustc_builtin_macro";
+  static constexpr auto &RUSTC_MACRO_TRANSPARENCY = "rustc_macro_transparency";
   static constexpr auto &PATH = "path";
   static constexpr auto &MACRO_USE = "macro_use";
   static constexpr auto &MACRO_EXPORT = "macro_export";
   static constexpr auto &PROC_MACRO = "proc_macro";
   static constexpr auto &PROC_MACRO_DERIVE = "proc_macro_derive";
   static constexpr auto &PROC_MACRO_ATTRIBUTE = "proc_macro_attribute";
+
   static constexpr auto &TARGET_FEATURE = "target_feature";
   // From now on, these are reserved by the compiler and gated through
   // #![feature(rustc_attrs)]
@@ -54,11 +56,33 @@ public:
 = "rustc_inherit_overflow_checks";
   static constexpr auto &STABLE = "stable";
   static constexpr auto &UNSTABLE = "unstable";
+
+  static constexpr auto &RUSTC_PROMOTABLE = "rustc_promotable";
   static constexpr auto &RUSTC_CONST_STABLE = "rustc_const_stable";
   static constexpr auto &RUSTC_CONST_UNSTABLE = "rustc_const_unstable";
+
+  static constexpr auto &RUSTC_SPECIALIZATION_TRAIT
+= "rustc_specialization_trait";
+  static constexpr auto &RUSTC_UNSAFE_SPECIALIZATION_MARKER
+= "rustc_unsafe_specialization_marker";
+  static constexpr auto &RUSTC_RESERVATION_IMPL = "rustc_reservation_impl";
+  static constexpr auto &RUSTC_PAREN_SUGAR = "rustc_paren_sugar";
+  static constexpr auto &RUSTC_NONNULL_OPTIMIZATION_GUARANTEED
+= "rustc_nonnull_optimization_guaranteed";
+
+  static constexpr auto &RUSTC_LAYOUT_SCALAR_VALID_RANGE_START
+= "rustc_layout_scalar_valid_range_start";
+
   static constexpr auto &MAY_DANGLE = "may_dangle";
   static constexpr auto &PRELUDE_IMPORT = "prelude_import";
   static constexpr auto &TRACK_CALLER = "track_caller";
+
+  static constexpr auto &RUSTC_DIAGNOSTIC_ITEM = "rustc_diagnostic_item";
+  static constexpr auto &RUSTC_ON_UNIMPLEMENTED = "rustc_on_unimplemented";
+
+  static constexpr auto &FUNDAMENTAL = "fundamental";
+
+  static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive";
 };
 } // namespace Values
 } // namespace Rust
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index df0fe1b0bca..7ddb476bbe6 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -57,6 +57,7 @@ static const BuiltinAttrDefinition __definitions[]
  {Attrs::NO_MANGLE, CODE_GENERATION},
  {Attrs::REPR, CODE_GENERATION},
  {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
+ {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
  {Attrs::PATH, EXPANSION},
  {Attrs::MACRO_USE, NAME_RESOLUTION},
  {Attrs::MACRO_EXPORT, NAME_RESOLUTION},
@@ -72,11 +73,28 @@ static const BuiltinAttrDefinition __definitions[]
  {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
  {Attrs::STABLE, STATIC_ANALYSIS},
  {Attrs::UNSTABLE, STATIC_ANALYSIS},
+
  // assuming we keep these for static analysis
+ {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
  {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
  {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
  {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
- {Attrs::TRACK_CALLER, CODE_GENERATION}};
+ {Attrs::TRACK_CALLER, CODE_GENERATION},
+ {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
+ {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
+ {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
+ {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
+ {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
+
+ {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
+
+ {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
+
+ {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
+ {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
+
+ {Attrs::FUNDAMENTAL, TYPE_CHECK},
+ {Attrs::NON_EXHAUSTIVE, TYPE_CHECK}};
 
 BuiltinAttributeMappings *
 BuiltinAttributeMappings::get ()
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index c928c8eb9d2..7e7cd2c3c63 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -41,6 +41,8 @@ enum CompilerPass
   TYPE_CHECK,
   STATIC_ANALYSIS,
   COD

[PUSHED/14 3/6] backprop: Fix deleting of a phi node [PR116922]

2025-04-14 Thread Andrew Pinski
The problem here is remove_unused_var is called on a name that is
defined by a phi node but it deletes it like removing a normal statement.
remove_phi_node should be called rather than gsi_remove for phinodes.

Note there is a possibility of using simple_dce_from_worklist instead
but that is for another day.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/116922

gcc/ChangeLog:

* gimple-ssa-backprop.cc (remove_unused_var): Handle phi
nodes correctly.

gcc/testsuite/ChangeLog:

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

Signed-off-by: Andrew Pinski 
(cherry picked from commit cea87c84eacdb422caeada734ba5138c994d7022)
---
 gcc/gimple-ssa-backprop.cc  | 10 --
 gcc/testsuite/gcc.dg/torture/pr116922.c | 19 +++
 2 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr116922.c

diff --git a/gcc/gimple-ssa-backprop.cc b/gcc/gimple-ssa-backprop.cc
index fe27ef51cdf..e3374b18138 100644
--- a/gcc/gimple-ssa-backprop.cc
+++ b/gcc/gimple-ssa-backprop.cc
@@ -663,8 +663,14 @@ remove_unused_var (tree var)
   print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
 }
   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
-  gsi_remove (&gsi, true);
-  release_defs (stmt);
+  if (gimple_code (stmt) == GIMPLE_PHI)
+remove_phi_node (&gsi, true);
+  else
+{
+  unlink_stmt_vdef (stmt);
+  gsi_remove (&gsi, true);
+  release_defs (stmt);
+}
 }
 
 /* Note that we're replacing OLD_RHS with NEW_RHS in STMT.  */
diff --git a/gcc/testsuite/gcc.dg/torture/pr116922.c 
b/gcc/testsuite/gcc.dg/torture/pr116922.c
new file mode 100644
index 000..0fcf912930f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116922.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-ffast-math" } */
+/* PR tree-optimization/116922 */
+
+
+static int g;
+
+void
+foo (int c, double v, double *r)
+{
+b:
+  do
+v /= g - v;
+  while (c);
+  *r = v;
+
+  double x;
+  foo (5, (double)0, &x);
+}
-- 
2.43.0



[PATCH] pretty-print, expand: Print [must tail call] for CALL_EXPRs and fix up maybe_complain_about_tail_call [PR119718]

2025-04-14 Thread Jakub Jelinek
Hi!

Andrew P. mentioned earlier he'd like to see in the dump files a note
whether it was a failed must tail call or not.
We already print that on the tailc/musttail pass side, because
print_gimple_stmt prints [must tail call] after the musttail calls.
The first hunk below does it for GENERIC CALL_EXPRs too (which is needed
for the expand diagnostics).  That isn't enough though, because the
error on it was done first and then CALL_EXPR_MUST_TAIL_CALL flag was
cleared, so the dump didn't have it anymore.  I've reordered the
dump printing with error, so that it works properly.

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

2025-04-14  Jakub Jelinek  

PR tree-optimization/119718
* tree-pretty-print.cc (dump_generic_node) : Dump
also CALL_EXPR_MUST_TAIL_CALL flag.
* calls.cc (maybe_complain_about_tail_call): Emit error about
CALL_EXPR_MUST_TAIL_CALL only after emitting dump message, not before
it.

--- gcc/tree-pretty-print.cc.jj 2025-04-12 13:09:55.367024475 +0200
+++ gcc/tree-pretty-print.cc2025-04-14 08:58:21.480256810 +0200
@@ -3201,6 +3201,8 @@ dump_generic_node (pretty_printer *pp, t
pp_string (pp, " [return slot optimization]");
   if (CALL_EXPR_TAILCALL (node))
pp_string (pp, " [tail call]");
+  if (CALL_EXPR_MUST_TAIL_CALL (node))
+   pp_string (pp, " [must tail call]");
   break;
 
 case WITH_CLEANUP_EXPR:
--- gcc/calls.cc.jj 2025-04-12 13:12:53.788557966 +0200
+++ gcc/calls.cc2025-04-14 09:00:00.939905377 +0200
@@ -1273,11 +1273,6 @@ void
 maybe_complain_about_tail_call (tree call_expr, const char *reason)
 {
   gcc_assert (TREE_CODE (call_expr) == CALL_EXPR);
-  if (CALL_EXPR_MUST_TAIL_CALL (call_expr))
-{
-  error_at (EXPR_LOCATION (call_expr), "cannot tail-call: %s", reason);
-  CALL_EXPR_MUST_TAIL_CALL (call_expr) = 0;
-}
   if (CALL_EXPR_TAILCALL (call_expr)
   && dump_file
   && (dump_flags & TDF_DETAILS))
@@ -1286,6 +1281,11 @@ maybe_complain_about_tail_call (tree cal
   print_generic_expr (dump_file, call_expr, TDF_SLIM);
   fprintf (dump_file, "\n");
 }
+  if (CALL_EXPR_MUST_TAIL_CALL (call_expr))
+{
+  error_at (EXPR_LOCATION (call_expr), "cannot tail-call: %s", reason);
+  CALL_EXPR_MUST_TAIL_CALL (call_expr) = 0;
+}
 }
 
 /* Fill in ARGS_SIZE and ARGS array based on the parameters found in

Jakub



[PUSHED/14 4/6] vec-lowering: Fix ABSU lowering [PR111285]

2025-04-14 Thread Andrew Pinski
ABSU_EXPR lowering incorrectly used the resulting type
for the new expression but in the case of ABSU the resulting
type is an unsigned type and with ABSU is folded away. The fix
is to use a signed type for the expression instead.

Bootstrapped and tested on x86_64-linux-gnu.

PR middle-end/111285

gcc/ChangeLog:

* tree-vect-generic.cc (do_unop): Use a signed type for the
operand if the operation was ABSU_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/torture/vect-absu-1.C: New test.

Signed-off-by: Andrew Pinski 
(cherry picked from commit ad0084337e901ddaedd48c14e7a5dad9fc2a093e)
---
 gcc/testsuite/g++.dg/torture/vect-absu-1.C | 29 ++
 gcc/tree-vect-generic.cc   | 10 +++-
 2 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/vect-absu-1.C

diff --git a/gcc/testsuite/g++.dg/torture/vect-absu-1.C 
b/gcc/testsuite/g++.dg/torture/vect-absu-1.C
new file mode 100644
index 000..0b2035f638f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/vect-absu-1.C
@@ -0,0 +1,29 @@
+// { dg-do run }
+// PR middle-end/111285
+
+// The lowering of vect absu was done incorrectly
+
+#define vect1 __attribute__((vector_size(sizeof(int
+
+#define negabs(a) a < 0 ? a : -a
+
+__attribute__((noinline))
+int s(int a)
+{
+  return negabs(a);
+}
+__attribute__((noinline))
+vect1 int v(vect1 int a)
+{
+  return negabs(a);
+}
+
+int main(void)
+{
+for(int i = -10; i < 10; i++)
+{
+  vect1 int t = {i};
+  if (v(t)[0] != s(i))
+__builtin_abort();
+}
+}
diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc
index 86d273923bb..84361dd5781 100644
--- a/gcc/tree-vect-generic.cc
+++ b/gcc/tree-vect-generic.cc
@@ -165,7 +165,15 @@ do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree 
a,
 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
 enum tree_code code, tree type ATTRIBUTE_UNUSED)
 {
-  a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
+  tree rhs_type = inner_type;
+
+  /* For ABSU_EXPR, use the signed type for the rhs if the rhs was signed. */
+  if (code == ABSU_EXPR
+  && ANY_INTEGRAL_TYPE_P (TREE_TYPE (a))
+  && !TYPE_UNSIGNED (TREE_TYPE (a)))
+rhs_type = signed_type_for (rhs_type);
+
+  a = tree_vec_extract (gsi, rhs_type, a, bitsize, bitpos);
   return gimplify_build1 (gsi, code, inner_type, a);
 }
 
-- 
2.43.0



[COMMITTED 13/19] gccrs: Fix const checking of enum discriminants

2025-04-14 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* checks/errors/rust-const-checker.cc
(ConstChecker::visit): Visit the enum items of enums.
* resolve/rust-ast-resolve-item.cc
(ResolveItem::visit): Resolve enum discriminants during nr1.0.

gcc/testsuite/ChangeLog:

* rust/compile/enum_discriminant2.rs: New test.

Signed-off-by: Owen Avery 
---
 gcc/rust/checks/errors/rust-const-checker.cc | 3 +++
 gcc/rust/resolve/rust-ast-resolve-item.cc| 2 ++
 gcc/testsuite/rust/compile/enum_discriminant2.rs | 9 +
 3 files changed, 14 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/enum_discriminant2.rs

diff --git a/gcc/rust/checks/errors/rust-const-checker.cc 
b/gcc/rust/checks/errors/rust-const-checker.cc
index 4904322b938..4c2257a2455 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -646,6 +646,9 @@ ConstChecker::visit (Enum &enum_item)
 {
   check_default_const_generics (enum_item.get_generic_params (),
ConstGenericCtx::Enum);
+
+  for (auto &item : enum_item.get_variants ())
+item->accept_vis (*this);
 }
 
 void
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc 
b/gcc/rust/resolve/rust-ast-resolve-item.cc
index d584961354f..30f6d430b86 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -356,6 +356,8 @@ ResolveItem::visit (AST::EnumItemDiscriminant &item)
   auto cpath = canonical_prefix.append (decl);
 
   mappings.insert_canonical_path (item.get_node_id (), cpath);
+
+  ResolveExpr::go (item.get_expr (), path, cpath);
 }
 
 void
diff --git a/gcc/testsuite/rust/compile/enum_discriminant2.rs 
b/gcc/testsuite/rust/compile/enum_discriminant2.rs
new file mode 100644
index 000..351dfbb6f85
--- /dev/null
+++ b/gcc/testsuite/rust/compile/enum_discriminant2.rs
@@ -0,0 +1,9 @@
+fn test() -> isize {
+1
+}
+
+enum Foo {
+Bar = test() // { dg-error "only functions marked as .const." }
+}
+
+fn main() {}
-- 
2.49.0



[PATCH] ltmain.in: don't suppress output for PIC compilations

2025-04-14 Thread Sam James
When working on xz, I set `-Werror=suggest-attribute=returns_nonnull`, and
the build failed (as I expected it to), but with no visible error from
the compiler. There's a mysterious '>/dev/null 2>&1' on the second line where
liblzma_la-common.o is built without PIC.

With -fPIC, IPA doesn't end up doing attribute discovery. Without it,
it does. This behaviour is IMO undesirable and we should patch it out.

This also affects building GCC and is particularly unfortunate if we hit
an ICE.

See https://bugs.gentoo.org/135865 and 
https://lists.gnu.org/archive/html/libtool-patches/2024-08/msg0.html.

* ltmain.sh (func_mode_compile): Don't suppress stdout/stderr for no-PIC
build.
---
I've proposed this upstream and it ended up being bikeshedded a bit. I've
been running this locally for nearly a year now and on IRC, others
expressed interest in this, as it causes pain when debugging.

 ltmain.sh | 2 --
 1 file changed, 2 deletions(-)

diff --git a/ltmain.sh b/ltmain.sh
index 1a710177fb26..79cd7c57f42e 100644
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -1576,8 +1576,6 @@ compiler."
command="$command -o $obj"
   fi
 
-  # Suppress compiler output if we already did a PIC compilation.
-  command="$command$suppress_output"
   func_show_eval_locale "$command" \
 '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
 
-- 
2.49.0



[COMMITTED 17/19] gccrs: nr2.0: Only insert derive macros if they exist

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

This causes an assertion failure when compiling core with nr2.0, but should
probably be improved. I'm not sure how this code enables built-in derive
macros to be resolved so this is a temporary fix.

gcc/rust/ChangeLog:

* resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): 
Remove assertion.
---
 gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index afaca1f71f0..36456e10ff2 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -325,10 +325,9 @@ Early::visit_attributes (std::vector 
&attrs)
  auto pm_def = mappings.lookup_derive_proc_macro_def (
definition->get_node_id ());
 
- rust_assert (pm_def.has_value ());
-
- mappings.insert_derive_proc_macro_invocation (trait,
-   pm_def.value ());
+ if (pm_def.has_value ())
+   mappings.insert_derive_proc_macro_invocation (trait,
+ pm_def.value ());
}
}
   else if (Analysis::BuiltinAttributeMappings::get ()
-- 
2.49.0



Re: [PATCH RFA (diagnostic)] c++: modules and #pragma diagnostic

2025-04-14 Thread Jason Merrill

On 1/9/25 10:00 PM, Jason Merrill wrote:

Tested x86_64-pc-linux-gnu.  Is the diagnostic.h change OK for trunk?


Ping?


-- 8< --

To respect the #pragma diagnostic lines in libstdc++ headers when compiling
with module std, we need to represent them in the module.

I think it's reasonable to make module_state a friend of
diagnostic_option_classifier to allow direct access to the data.  This is a
different approach from how Jakub made PCH streaming members of
diagnostic_option_classifier, but it seems to me that modules handling
belongs in module.cc.

gcc/ChangeLog:

* diagnostic.h: Add friends.

gcc/cp/ChangeLog:

* module.cc (module_state::write_diagnostic_classification): New.
(module_state::write_begin): Call it.
(module_state::read_diagnostic_classification): New.
(module_state::read_initial): Call it.

gcc/testsuite/ChangeLog:

* g++.dg/modules/warn-spec-3_a.C: New test.
* g++.dg/modules/warn-spec-3_b.C: New test.
---
  gcc/diagnostic.h |  4 +
  gcc/cp/module.cc | 86 +++-
  gcc/testsuite/g++.dg/modules/warn-spec-3_a.C | 20 +
  gcc/testsuite/g++.dg/modules/warn-spec-3_b.C |  8 ++
  4 files changed, 117 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-3_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-3_b.C

diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 202760b2f85..91bde3ff06c 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -299,6 +299,8 @@ private:
  
/* For pragma push/pop.  */

vec m_push_list;
+
+  friend class module_state;
  };
  
  /* A bundle of options relating to printing the user's source code

@@ -807,6 +809,8 @@ private:
/* The stack of sets of overridden diagnostic option severities.  */
diagnostic_option_classifier m_option_classifier;
  
+  friend class module_state;

+
/* True if we should print any CWE identifiers associated with
   diagnostics.  */
bool m_show_cwe;
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 78fb21dc22f..49c9c092163 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -3876,6 +3876,9 @@ class GTY((chain_next ("%h.parent"), for_user)) 
module_state {
void write_macro_maps (elf_out *to, range_t &, unsigned *crc_ptr);
bool read_macro_maps (line_map_uint_t);
  
+  void write_diagnostic_classification (elf_out *, diagnostic_context *, unsigned *);

+  bool read_diagnostic_classification (diagnostic_context *);
+
   private:
void write_define (bytes_out &, const cpp_macro *);
cpp_macro *read_define (bytes_in &, cpp_reader *) const;
@@ -17637,6 +17640,78 @@ module_state::write_ordinary_maps (elf_out *to, range_t 
&info,
dump.outdent ();
  }
  
+/* Write out any #pragma GCC diagnostic info to the .dgc section.  */

+
+void
+module_state::write_diagnostic_classification (elf_out *to,
+  diagnostic_context *dc,
+  unsigned *crc_p)
+{
+  auto &changes = dc->m_option_classifier.m_classification_history;
+
+  dump () && dump ("Writing diagnostic change locations");
+  dump.indent ();
+
+  bytes_out sec (to);
+  if (sec.streaming_p ())
+sec.begin ();
+
+  unsigned len = changes.length ();
+  dump () && dump ("Diagnostic changes: %u", len);
+  if (sec.streaming_p ())
+sec.u (len);
+
+  for (const auto &c: changes)
+{
+  write_location (sec, c.location);
+  if (sec.streaming_p ())
+   {
+ sec.u (c.option);
+ sec.u (c.kind);
+   }
+}
+
+  if (sec.streaming_p ())
+sec.end (to, to->name (MOD_SNAME_PFX ".dgc"), crc_p);
+  dump.outdent ();
+}
+
+/* Read any #pragma GCC diagnostic info from the .dgc section.  */
+
+bool
+module_state::read_diagnostic_classification (diagnostic_context *dc)
+{
+  bytes_in sec;
+
+  if (!sec.begin (loc, from (), MOD_SNAME_PFX ".dgc"))
+return false;
+
+  dump () && dump ("Reading diagnostic change locations");
+  dump.indent ();
+
+  unsigned len = sec.u ();
+  dump () && dump ("Diagnostic changes: %u", len);
+
+  auto &changes = dc->m_option_classifier.m_classification_history;
+  unsigned offset = changes.length ();
+  changes.reserve (len);
+  for (unsigned i = 0; i < len; ++i)
+{
+  location_t loc = read_location (sec);
+  int opt = sec.u ();
+  diagnostic_t kind = (diagnostic_t) sec.u ();
+  if (kind == DK_POP)
+   opt += offset;
+  changes.quick_push ({ loc, opt, kind });
+}
+
+  dump.outdent ();
+  if (!sec.end (from ()))
+return false;
+
+  return true;
+}
+
  void
  module_state::write_macro_maps (elf_out *to, range_t &info, unsigned *crc_p)
  {
@@ -19231,6 +19306,8 @@ module_state::write_begin (elf_out *to, cpp_reader 
*reader,
if (is_header ())
  macros = prepare_macros (reader);
  
+  write_diagnostic_classification (nullptr, global_dc, nullptr);

+
config.num_imports = mod_hwm;
config.num_

[PATCH] AArch64: Fix operands order in vec_extract expander

2025-04-14 Thread Tejas Belagod
The operand order to gen_vcond_mask call in the vec_extract pattern is wrong.
Fix the order where predicate is operand 3.

Tested and bootstrapped on aarch64-linux-gnu. OK for trunk?

gcc/ChangeLog

* config/aarch64/aarch64-sve.md (vec_extract): Fix operand
order to gen_vcond_mask_*.
---
 gcc/config/aarch64/aarch64-sve.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-sve.md 
b/gcc/config/aarch64/aarch64-sve.md
index 3dbd65986ec..d4af3706294 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -3133,9 +3133,9 @@
   "TARGET_SVE"
   {
 rtx tmp = gen_reg_rtx (mode);
-emit_insn (gen_vcond_mask_ (tmp, operands[1],
-CONST1_RTX (mode),
-CONST0_RTX (mode)));
+emit_insn (gen_vcond_mask_ (tmp, CONST1_RTX (mode),
+CONST0_RTX (mode),
+operands[1]));
 emit_insn (gen_vec_extract (operands[0], tmp, operands[2]));
 DONE;
   }
-- 
2.25.1



[PATCH] cobol: Drop -fsyntax-only from COBOL lang.opt [PR119777]

2025-04-14 Thread Jakub Jelinek
Hi!

The comment is incorrect, fsyntax-only is not documented in c.opt,
but in common.opt:
fsyntax-only
Common Var(flag_syntax_only)
Check for syntax errors, then stop.
and as such it applies to all languages, so adding CL_Cobol to
the CL_COMMON is both unnecessary and because of RejectNegative which
contradicts the generic option very harmful, because it makes
-fno-syntax-only invalid for all languages.

Fixed by just dropping it.

Bootstrapped/regtested on x86_64-linux and i686-linux (no cobol
in the latter), ok for trunk?

2025-04-14  Jakub Jelinek  

PR cobol/119777
* lang.opt (fsyntax-only): Remove.
* lang.opt.urls: Regenerate.

--- gcc/cobol/lang.opt.jj   2025-04-08 14:08:48.662317907 +0200
+++ gcc/cobol/lang.opt  2025-04-14 10:56:28.739693026 +0200
@@ -77,10 +77,6 @@ ffixed-form
 Cobol RejectNegative
 Assume that the source file is fixed form.
 
-fsyntax-only
-Cobol RejectNegative
-; Documented in c.opt
-
 ffree-form
 Cobol RejectNegative
 Assume that the source file is free form.
--- gcc/cobol/lang.opt.urls.jj  2025-04-08 14:08:48.662317907 +0200
+++ gcc/cobol/lang.opt.urls 2025-04-14 10:57:06.579176798 +0200
@@ -13,9 +13,6 @@ UrlSuffix(gcc/Directory-Options.html#ind
 ffixed-form
 LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-ffixed-form)
 
-fsyntax-only
-UrlSuffix(gcc/Warning-Options.html#index-fsyntax-only) 
LangUrlSuffix_D(gdc/Warnings.html#index-fno-syntax-only) 
LangUrlSuffix_Fortran(gfortran/Error-and-Warning-Options.html#index-fsyntax-only)
-
 ffree-form
 LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-ffree-form)
 

Jakub



[PATCH] expmed: Always use QImode for init_expmed set_zero_cost [PR119785]

2025-04-14 Thread Jakub Jelinek
Hi!

This is a regression on some targets introduced I believe by r6-2055
which added mode argument to set_src_cost.

The problem here is that in the first iteration, mode is always QImode
and we get as -Os zero cost set_src_cost (const0_rtx, QImode, false).
But then we use the mode variable for iterating over int, partial int
and vector int modes, so for the second iteration we call set_src_cost
with mode which is at that time (machine_mode) (MAX_MODE_VECTOR_INT + 1).

In the x86 case that happens to be V2HFmode and we don't crash (and
compute the same 0 cost as we would for QImode).
But e.g. in the SPARC case (machine_mode) (MAX_MODE_VECTOR_INT + 1) is
MAX_MACHINE_MODE and that does all kinds of weird things especially
when doing ubsan bootstrap.

Fixed by always using QImode.

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

2025-04-14  Jakub Jelinek  

PR rtl-optimization/119785
* expmed.cc (init_expmed): Always pass QImode rather than mode to
set_src_cost passed to set_zero_cost.

--- gcc/expmed.cc.jj2025-04-08 14:08:51.234282102 +0200
+++ gcc/expmed.cc   2025-04-14 12:17:48.334123928 +0200
@@ -285,7 +285,7 @@ init_expmed (void)
   for (speed = 0; speed < 2; speed++)
 {
   crtl->maybe_hot_insn_p = speed;
-  set_zero_cost (speed, set_src_cost (const0_rtx, mode, speed));
+  set_zero_cost (speed, set_src_cost (const0_rtx, QImode, speed));
 
   for (mode = MIN_MODE_INT; mode <= MAX_MODE_INT;
   mode = (machine_mode)(mode + 1))

Jakub



[PATCH] c++: improve constraint recursion diagnostic

2025-04-14 Thread Patrick Palka
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
look OK for trunk and perhaps 14?

-- >8 --

Our constraint recursion diagnostics are not ideal because they
usually show the atom with an uninstantiated parameter mapping, e.g

concepts-recursive-sat5.C:6:41: error: satisfaction of atomic constraint 
‘requires(A a, T t) {a | t;} [with T = T]’ depends on itself

This is a consequence of our two-level caching of atomic constraints,
where we first cache the uninstantiated atom+args and then the
instantiated atom+no args, and most likely the first level of caching
detects the recursion, at which point we have no way to get a hold of
the instantiated atom.

This patch fixes this by linking the the first level of caching to the
second level, so that we can conveniently print the instantiated atom in
case of constraint recursion detected from the first level of caching.

Alternatively we could make only the second level of caching diagnose
constraint recursion but then we'd no longer catch constraint recursion
that occurs during parameter mapping instantiation.  This current approach
seems simpler, and it also seems natural to have the two levels of caching
linked in some way anyway.

gcc/cp/ChangeLog:

* constraint.cc (struct sat_entry): New data member inst_entry.
(satisfaction_cache::get): Use it to prefer printing the
instantiated atom in case of constraint recursion.
(satisfy_atom): Set inst_entry on the first entry to point to
the second entry.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-recursive-sat2.C: Verify that the
instantiated parameter mapping is printed.
* g++.dg/cpp2a/concepts-recursive-sat5.C: Likewise.
---
 gcc/cp/constraint.cc | 12 ++--
 gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C |  3 ++-
 gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C |  3 ++-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 44fb086c6306..1bb237f5bb4f 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1895,6 +1895,10 @@ struct GTY((for_user)) sat_entry
  the first time.  */
   tree result;
 
+  /* For a !ATOMIC_CONSTR_MAP_INSTANTIATED_P atom, this is the entry
+ for the corresponding atom after instantiating its mapping.  */
+  sat_entry *inst_entry;
+
   /* The value of input_location when satisfaction of ATOM+ARGS was first
  performed.  */
   location_t location;
@@ -2093,10 +2097,12 @@ satisfaction_cache::get ()
 {
   /* If we get here, it means satisfaction is self-recursive.  */
   gcc_checking_assert (!entry->result || seen_error ());
+  /* Prefer printing the instantiated mapping.  */
+  tree atom = entry->inst_entry ? entry->inst_entry->atom : entry->atom;
   if (info.noisy ())
-   error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (entry->atom)),
+   error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (atom)),
  "satisfaction of atomic constraint %qE depends on itself",
- entry->atom);
+ atom);
   return error_mark_node;
 }
 
@@ -2416,6 +2422,8 @@ satisfy_atom (tree t, tree args, sat_info info)
   gcc_assert (!ATOMIC_CONSTR_MAP_INSTANTIATED_P (t));
   ATOMIC_CONSTR_MAP_INSTANTIATED_P (t) = true;
   satisfaction_cache inst_cache (t, /*args=*/NULL_TREE, info);
+  if (cache.entry)
+cache.entry->inst_entry = inst_cache.entry;
   if (tree r = inst_cache.get ())
 {
   cache.entry->location = inst_cache.entry->location;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
index 9bc96f58979d..a264f26bc55d 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
@@ -1,7 +1,8 @@
 // { dg-do compile { target c++20 } }
 
 template
-concept Fooable = requires(T t) { foo(t); }; // { dg-error "depends on itself" 
}
+concept Fooable = requires(T t) { foo(t); };
+// { dg-error "T = test::S]' depends on itself" "" { target *-*-* } .-1 }
 
 template
 void foo(T t) { }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C
index ba564873a204..63e032494e3d 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C
@@ -3,7 +3,8 @@
 
 struct A { };
 
-template concept pipeable = requires(A a, T t) { a | t; }; // { 
dg-error "depends on itself" }
+template concept pipeable = requires(A a, T t) { a | t; };
+// { dg-error "with T = int]' depends on itself" "" { target *-*-* } .-1 }
 
 template void operator|(A, T);
 
-- 
2.49.0.221.g485f5f8636



Re: [PATCH] cobol: Fix -fmax-errors option [PR119776]

2025-04-14 Thread Richard Biener



> Am 14.04.2025 um 18:13 schrieb Jakub Jelinek :
> 
> Hi!
> 
> There seems to be inconsistency in the -fmax-errors option
> naming.  It is a generic option in common.opt (so applies
> to all languages) but with the = character in it.
> The gcobol.1 man page in one spot documents the generic
> option (in the syntax, -fmax-errors=nerror) but in another
> spot without the = character.
> 
> In common.opt it is
> fmax-errors=
> Common Joined RejectNegative UInteger Var(flag_max_errors)
> -fmax-errors=   Maximum number of errors to report.
> 
> I hope the cobol addition is just a mistake, having -fmax-errors variant
> without = character when Joined Separate would allow to specify
> -fmax-errors 10 with the same meaning as -fmax-errors=10
> but also -fmax-errors10 with the same meaning which is just weird.
> Also, there is no UInteger and RejectNegative on it, so one can
> also specific -fno-max-errors42 or -fmax-errors blah.
> 
> So, unless the spelling without = is intentional, here is a patch
> to just remove it, the common option already should have arranged
> for flag_max_errors to be set to the right number.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok

Richard 

> Or if it is intentional, I guess we'd need to at least add
> RejectNegative UInteger (plus using atoi is generally undesirable
> anywhere in the compiler because it does no error checking).
> And the man page would need to be updated to specify both forms.
> 
> 2025-04-14  Jakub Jelinek  
> 
>PR cobol/119776
>* lang.opt (fmax-errors): Remove.
>* lang.opt.urls: Regenerate.
>* cobol1.cc (cobol_langhook_handle_option) :
>Remove.
>* gcobol.1: Document -fmax-errors=nerror rather than
>-fmax-errors nerror.
> 
> --- gcc/cobol/lang.opt.jj2025-04-14 11:08:31.808821317 +0200
> +++ gcc/cobol/lang.opt2025-04-14 11:20:52.369700721 +0200
> @@ -89,10 +89,6 @@ finternal-ebcdic
> Cobol Var(cobol_ebcdic, 1) Init(0)
> -finternal-ebcdicInternal processing is in EBCDIC Code Page 1140
> 
> -fmax-errors
> -Cobol Joined Separate
> -; Documented in C
> -
> fstatic-call
> Cobol Var(cobol_static_call, 1) Init(1)
> Enable/disable static linkage for CALL literals
> --- gcc/cobol/lang.opt.urls.jj2025-04-14 10:57:06.579176798 +0200
> +++ gcc/cobol/lang.opt.urls2025-04-14 11:21:03.157553577 +0200
> @@ -16,9 +16,6 @@ LangUrlSuffix_Fortran(gfortran/Fortran-D
> ffree-form
> LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-ffree-form)
> 
> -fmax-errors
> -UrlSuffix(gcc/Warning-Options.html#index-fmax-errors) 
> LangUrlSuffix_D(gdc/Warnings.html#index-fmax-errors)
> -
> iprefix
> UrlSuffix(gcc/Directory-Options.html#index-iprefix) 
> LangUrlSuffix_D(gdc/Directory-Options.html#index-iprefix) 
> LangUrlSuffix_Fortran(gfortran/Preprocessing-Options.html#index-iprefix)
> 
> --- gcc/cobol/cobol1.cc.jj2025-04-14 11:09:22.619126924 +0200
> +++ gcc/cobol/cobol1.cc2025-04-14 11:32:51.177896287 +0200
> @@ -385,10 +385,6 @@ cobol_langhook_handle_option (size_t sco
> return true;
> }
> 
> -case OPT_fmax_errors:
> -flag_max_errors = atoi(arg);
> -return true;
> -
> case OPT_ffixed_form:
> cobol_set_indicator_column(-7);
> return true;
> --- gcc/cobol/gcobol.1.jj2025-04-08 14:08:48.595318840 +0200
> +++ gcc/cobol/gcobol.12025-04-14 11:19:17.017003687 +0200
> @@ -224,7 +224,7 @@ had appeared.
> Not all exception conditions are implemented.  Any that are not
> produce a warning message.
> .
> -.It Fl fmax-errors Ar nerror
> +.It Fl fmax-errors Ns Li = Ns Ar nerror
> .Ar nerror
> represents the number of error messages produced.  Without this option,
> .Nm
> 
> 
>Jakub
> 


Re: [PATCH] expmed: Always use QImode for init_expmed set_zero_cost [PR119785]

2025-04-14 Thread Richard Biener



> Am 14.04.2025 um 18:19 schrieb Jakub Jelinek :
> 
> Hi!
> 
> This is a regression on some targets introduced I believe by r6-2055
> which added mode argument to set_src_cost.
> 
> The problem here is that in the first iteration, mode is always QImode
> and we get as -Os zero cost set_src_cost (const0_rtx, QImode, false).
> But then we use the mode variable for iterating over int, partial int
> and vector int modes, so for the second iteration we call set_src_cost
> with mode which is at that time (machine_mode) (MAX_MODE_VECTOR_INT + 1).
> 
> In the x86 case that happens to be V2HFmode and we don't crash (and
> compute the same 0 cost as we would for QImode).
> But e.g. in the SPARC case (machine_mode) (MAX_MODE_VECTOR_INT + 1) is
> MAX_MACHINE_MODE and that does all kinds of weird things especially
> when doing ubsan bootstrap.
> 
> Fixed by always using QImode.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok

Richard 

> 
> 2025-04-14  Jakub Jelinek  
> 
>PR rtl-optimization/119785
>* expmed.cc (init_expmed): Always pass QImode rather than mode to
>set_src_cost passed to set_zero_cost.
> 
> --- gcc/expmed.cc.jj2025-04-08 14:08:51.234282102 +0200
> +++ gcc/expmed.cc2025-04-14 12:17:48.334123928 +0200
> @@ -285,7 +285,7 @@ init_expmed (void)
>   for (speed = 0; speed < 2; speed++)
> {
>   crtl->maybe_hot_insn_p = speed;
> -  set_zero_cost (speed, set_src_cost (const0_rtx, mode, speed));
> +  set_zero_cost (speed, set_src_cost (const0_rtx, QImode, speed));
> 
>   for (mode = MIN_MODE_INT; mode <= MAX_MODE_INT;
>   mode = (machine_mode)(mode + 1))
> 
>Jakub
> 


[COMMITTED 19/19] gccrs: lang-items: Add ManuallyDrop

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* util/rust-lang-item.h: Add new manually_drop lang item.
* util/rust-lang-item.cc: Likewise.
---
 gcc/rust/util/rust-lang-item.cc | 1 +
 gcc/rust/util/rust-lang-item.h  | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc
index a76cc7ff651..9aff31b657c 100644
--- a/gcc/rust/util/rust-lang-item.cc
+++ b/gcc/rust/util/rust-lang-item.cc
@@ -118,6 +118,7 @@ const BiMap 
Rust::LangItem::lang_items = {{
 
   {"discriminant_kind", Kind::DISCRIMINANT_KIND},
   {"discriminant_type", Kind::DISCRIMINANT_TYPE},
+  {"manually_drop", Kind::MANUALLY_DROP},
 }};
 
 tl::optional
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 8f3af3615bb..67a5d9c438f 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -150,6 +150,8 @@ public:
 
 DISCRIMINANT_TYPE,
 DISCRIMINANT_KIND,
+
+MANUALLY_DROP,
   };
 
   static const BiMap lang_items;
-- 
2.49.0



Re: [RFC] [C]New syntax for the argument of counted_by attribute for C language

2025-04-14 Thread Bill Wendling
SAfter being on a mini-vacation and thinking about this more,
I'm a bit less satisfied with the current proposal. The main issue is
that we have seemingly two lookup rules based on which attribute is
used (counted_by vs. counted_by_expr).

  1. counted_by: We expect an expression that's a lone identifier.
Here, we use a pseudo-struct scope to resolve that identifier.
("Pseudo" because it's not fully defined in the standard but created
for this feature alone.)

  2. counted_by_expr: Any identifiers that appear in the struct need
to be forward declared. If they aren't, the normal lookup rules apply.

Now, I don't think this will be necessarily confusing to the
programmer, but it's inconsistent. In other words, either 'counted_by'
*must* forward declare the in-structure identifier or neither must.

It's also probable that most expressions will use in-structure
identifiers, with the occasional enum or macro. (I'm going off of
Yeoul's assertion that they've implemented this successfully on large
code bases and haven't had to make allowances for global identifiers.)

My counter proposal then is to do something like this:

1. The syntax needs to be unambiguous.
2. Identifier lookup must be consistent between the two attribute forms.
3. The common use case should take the least amount of code to write.
(More of a "nice to have".)

Therefore, I suggest the following rules, that are more-or-less the
reverse of the current proposal's rules:

- All untagged identifiers are assumed to be within the structure. If
they aren't found in the struct, it's an error.
- All globals (i.e. identifiers not in the struct) must be referenced
via a special tag or a builtin (e.g. __builtin_global_ref()). The tag
or builtin follow current scoping rules---i.e. it may pick up a shadow
variable rather than the global.

Examples:

[Assume a builtin called '__builtin_global_ref' that takes an
expression where every identifier within that expression is assumed
"global".]

struct A {
  int *buf __counted_by(len); // 'len' *must* be in the struct.
  int len;
};

constexpr int len = 42;
struct B {
  int *buf __counted_by(__builtin_global_ref(len)); // 'len' is a global.
};

enum { PADDING = 42 };
struct C {
  int *buf __counted_by_expr(len * __builtin_global_ref(PADDING));
  int len;
};

#define PADDING_EXPR __builtin_gloal_ref(len) + 42
struct D {
  int *buf __counted_by_expr(len * PADDING_EXPR);
// PADDING_EXPR is expanded and that 'len' is not in the structure.
  int len;
};

#define PADDING_EXPR len + 42
struct E {
  int *buf __counted_by_expr(len * __builtin_global_ref(PADDING_EXPR));
// PADDING_EXPR is expanded and that 'len' is not in the structure.
  int len;
};

There is the issue that the __builtin_global_ref() in 'struct E' may
appear to cause the sub-expression to have a higher affinity than the
multiplication but it doesn't. That may or may not be a programmer
error, but one to be aware of nonetheless.

-bw


[COMMITTED 04/19] rust: Add comment inside block [PR119342]

2025-04-14 Thread arthur . cohen
From: Andrew Pinski 

Inside a BLOCK node, all of the variables of the scope/block
are chained together and that connects them to the block.
This just adds a comment to that effect as reading the code
it is not so obvious why they need to be chained together.

gcc/rust/ChangeLog:

PR rust/119342
* rust-gcc.cc (block): Add comment on why chaining
the variables of the scope toether.

Signed-off-by: Andrew Pinski 
---
 gcc/rust/rust-gcc.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index bd1f13920bf..234721c585f 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -1792,6 +1792,8 @@ block (tree fndecl, tree enclosing, const 
std::vector &vars,
   *pp = block_tree;
 }
 
+  // Chain the variables of the scope together so they are all connected
+  // to the block.
   tree *pp = &BLOCK_VARS (block_tree);
   for (Bvariable *bv : vars)
 {
-- 
2.49.0



[PATCH] RISC-V: Put jump table in text for large code model

2025-04-14 Thread Kito Cheng
Large code model assume the data or rodata may put far away from
text section.  So we need to put jump table in text section for
large code model.

gcc/ChangeLog:

* config/riscv/riscv.h (JUMP_TABLES_IN_TEXT_SECTION): Check if
large code model.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/jump-table-large-code-model.c: New test.
---
 gcc/config/riscv/riscv.h  |  2 +-
 .../riscv/jump-table-large-code-model.c   | 24 +++
 2 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c

diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 2bcabd03517..2759a4cb1c9 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -888,7 +888,7 @@ extern enum riscv_cc get_riscv_cc (const rtx use);
 #define ASM_OUTPUT_OPCODE(STREAM, PTR) \
   (PTR) = riscv_asm_output_opcode(STREAM, PTR)
 
-#define JUMP_TABLES_IN_TEXT_SECTION 0
+#define JUMP_TABLES_IN_TEXT_SECTION (riscv_cmodel == CM_LARGE)
 #define CASE_VECTOR_MODE SImode
 #define CASE_VECTOR_PC_RELATIVE (riscv_cmodel != CM_MEDLOW)
 
diff --git a/gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c 
b/gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c
new file mode 100644
index 000..1ee7f6c07d3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -mcmodel=large" } */
+
+int foo(int x, int y)
+{
+  switch(x){
+  case 0:
+return 123 + y;
+  case 1:
+return 456 + y;
+  case 2:
+return 789 - y;
+  case 3:
+return 12 * y;
+  case 4:
+return 13 % y;
+  case 5:
+return 11 *y;
+  }
+  return 0;
+}
+
+
+/* { dg-final { scan-assembler-not "\.section  \.rodata" } } */
-- 
2.34.1



Re: Asan/Tsan Unit/Regression testing (was [asan] Emit GIMPLE direclty, small cleanups)

2025-04-14 Thread Jakub Jelinek
On Mon, Apr 14, 2025 at 03:33:10PM +0200, Thomas Schwinge wrote:
> Hi!
> 
> I've got a question regarding the 'gcc/testsuite/lib/asan-dg.exp'
> overriding of '${tool}_load', which was introduced here,
> Subversion r193511 (Git commit 8335a6439ddb66aa9ebc67ee47aa2e6e317e3ef9):
> 
> On 2012-11-14T12:11:13+0100, Jakub Jelinek  wrote:
> > --- gcc/testsuite/lib/asan-dg.exp.jj2012-11-14 09:11:13.086054131 
> > +0100
> > +++ gcc/testsuite/lib/asan-dg.exp   2012-11-14 11:45:40.142061595 +0100
> 
> > +# Replace ${tool}_load with a wrapper so that we can symbolize the output.
> > +if { [info procs ${tool}_load] != [list] \
> > +  && [info procs saved_asan_${tool}_load] == [list] } {
> > +rename ${tool}_load saved_asan_${tool}_load
> > +
> > +proc ${tool}_load { program args } {
> > +   global tool
> > +   set result [eval [list saved_asan_${tool}_load $program] $args]
> > +   set output [lindex $result 1]
> > +   set symbolized_output [asan_symbolize "$output"]
> > +   set result [list [lindex $result 0] $symbolized_output]
> > +   return $result
> > +}
> > +}
> 
> So, once 'load_lib asan-dg.exp' has been done, this globally wraps
> '${tool}_load', forever, for all following '*.exp' test suites, too.
> This introduces overhead: routes every '${tool}_load' through
> 'asan_symbolize', even for non-ASAN '*.exp' test suites.
> 
> Following the usual pattern, shouldn't we do such wrapping only locally,
> where necessary?  Here, I suppose we could move this wrapping setup into
> 'asan_init', and then undo it in 'asan_finish'.
> 
> I'll be happy to draft a patch if someone confirms my thinking.

I think you're right.
The cost probably isn't that significant, as
set addresses [regexp -inline -all -line "^ *#\[0-9\]+ 0x\[0-9a-f\]+ 
\[(\](\[^)\]+)\[+\](0x\[0-9a-f\]+)\[)\]$" "$output"]
will for most programs just result in empty list and so nothing will be
actually invoked, but it would be cleaner to deregister it, sure.

Jakub



Re: [PATCH v2] libstdc++: Fix std::string construction from volatile char* [PR119748]

2025-04-14 Thread Jonathan Wakely
On Mon, 14 Apr 2025 at 16:25, Tomasz Kaminski  wrote:
>
>
>
> On Mon, Apr 14, 2025 at 5:06 PM Jonathan Wakely  wrote:
>>
>> My recent r15-9381-g648d5c26e25497 change assumes that a contiguous
>> iterator with the correct value_type can be converted to a const charT*
>> but that's not true for volatile charT*. The optimization should only be
>> done if it can be converted to the right pointer type.
>>
>> Additionally, the generic loop for non-contiguous iterators needs an
>> explicit cast to deal with iterators that have a reference type that is
>> not explicitly convertible to charT.
>
> As mentioned before, we do not need to handle explicit conversion for CharT.

Ah yes, I forgot to fix that part of the commit message.

> We still need to perform static_cast to create a temporary CharT when passing
> to traits::assign, as otherwise we will get a mismatch in deduction.

I agree we still need to create a temporary, but there's no deduction
involved. traits_type::assign takes charT& and const charT&, and the
volatile charT& cannot bind to the latter.

I'll change the second paragraph of the commit message to say:

   Additionally, some generic loops for non-contiguous iterators need an
   explicit cast to deal with iterator reference types that do not bind to
   the const charT& parameter of traits_type::assign.



>> libstdc++-v3/ChangeLog:
>>
>> PR libstdc++/119748
>> * include/bits/basic_string.h (_S_copy_chars): Only optimize for
>> contiguous iterators that are convertible to const charT*. Use
>> explicit conversion to charT after dereferencing iterator.
>> (_S_copy_range): Likewise for contiguous ranges.
>> * include/bits/basic_string.tcc (_M_construct): Use explicit
>> conversion to charT after dereferencing input iterator.
>> * include/bits/cow_string.h (_S_copy_chars): Likewise.
>> (basic_string(from_range_t, R&&, const Allocator&)): Likewise.
>> Only optimize for contiguous iterators that are convertible to
>> const charT*.
>> * testsuite/21_strings/basic_string/cons/char/119748.cc: New
>> test.
>> * testsuite/21_strings/basic_string/cons/wchar_t/119748.cc:
>> New test.
>> ---
>>
>> Changes in v2:
>> - Added static_assert in _M_construct overload for input iterators.
>> - Added tests using non-contiguous iterators.
>>
>>  libstdc++-v3/include/bits/basic_string.h  | 24 +---
>>  libstdc++-v3/include/bits/basic_string.tcc|  3 +-
>>  libstdc++-v3/include/bits/cow_string.h| 17 --
>>  .../basic_string/cons/char/119748.cc  | 55 +++
>>  .../basic_string/cons/wchar_t/119748.cc   |  7 +++
>>  5 files changed, 93 insertions(+), 13 deletions(-)
>>  create mode 100644 
>> libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc
>>  create mode 100644 
>> libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc
>>
>> diff --git a/libstdc++-v3/include/bits/basic_string.h 
>> b/libstdc++-v3/include/bits/basic_string.h
>> index 9c431c765ab..c90bd099b63 100644
>> --- a/libstdc++-v3/include/bits/basic_string.h
>> +++ b/libstdc++-v3/include/bits/basic_string.h
>> @@ -488,8 +488,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
>>   is_same<_IterBase, const _CharT*>>::value)
>> _S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
>>  #if __cpp_lib_concepts
>> - else if constexpr (contiguous_iterator<_Iterator>
>> -  && is_same_v, _CharT>)
>> + else if constexpr (requires {
>> +  requires contiguous_iterator<_Iterator>;
>> +  { std::to_address(__k1) }
>> +-> convertible_to;
>> +})
>
> I would prefer, but this is not a strong preference.
>if constexpr (ranges::contiguous_range<_Rg>)
>  if constexpr 
> (convertible_to(__rg))), const 
> CharT*>>)

Yes, in general I would prefer that, but then the else-branch would
bind incorrectly:

if constexpr (pointer or string::iterator)
{ }
else if constexpr (contiguous_range)
  if constexpr (convertible to pointer)
  { }
else
  for-loop

And it can't be a single condition because the ranges::data call isn't
valid unless it's a contiguous iterator.

I could write it:

if constexpr (pointer or string::iterator)
{ }
else if constexpr (contiguous_range)
  if constexpr (convertible to pointer)
  { }
  else
for-loop
else
  for-loop

Or just don't use a discarded statement for the for-loop:

if constexpr (pointer or string::iterator)
{ }
else if constexpr (contiguous_range)
  if constexpr (convertible to pointer)
  { }
for-loop

But neither of these seems clearly better than just using a single
constexpr-if with a requires-expression as the condition.


>>
>> {
>>   const auto __d = __k2 - __k1;
>>   (void) (__k1 + __d); // See P3349R1
>> @@ -499,7 +502,7 @@ _GLIBCXX_BE

Re: [PATCH] cobol: Drop -fsyntax-only from COBOL lang.opt [PR119777]

2025-04-14 Thread Richard Biener



> Am 14.04.2025 um 17:56 schrieb Jakub Jelinek :
> 
> Hi!
> 
> The comment is incorrect, fsyntax-only is not documented in c.opt,
> but in common.opt:
> fsyntax-only
> Common Var(flag_syntax_only)
> Check for syntax errors, then stop.
> and as such it applies to all languages, so adding CL_Cobol to
> the CL_COMMON is both unnecessary and because of RejectNegative which
> contradicts the generic option very harmful, because it makes
> -fno-syntax-only invalid for all languages.
> 
> Fixed by just dropping it.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux (no cobol
> in the latter), ok for trunk?

Ok

Richard 

> 
> 2025-04-14  Jakub Jelinek  
> 
>PR cobol/119777
>* lang.opt (fsyntax-only): Remove.
>* lang.opt.urls: Regenerate.
> 
> --- gcc/cobol/lang.opt.jj2025-04-08 14:08:48.662317907 +0200
> +++ gcc/cobol/lang.opt2025-04-14 10:56:28.739693026 +0200
> @@ -77,10 +77,6 @@ ffixed-form
> Cobol RejectNegative
> Assume that the source file is fixed form.
> 
> -fsyntax-only
> -Cobol RejectNegative
> -; Documented in c.opt
> -
> ffree-form
> Cobol RejectNegative
> Assume that the source file is free form.
> --- gcc/cobol/lang.opt.urls.jj2025-04-08 14:08:48.662317907 +0200
> +++ gcc/cobol/lang.opt.urls2025-04-14 10:57:06.579176798 +0200
> @@ -13,9 +13,6 @@ UrlSuffix(gcc/Directory-Options.html#ind
> ffixed-form
> LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-ffixed-form)
> 
> -fsyntax-only
> -UrlSuffix(gcc/Warning-Options.html#index-fsyntax-only) 
> LangUrlSuffix_D(gdc/Warnings.html#index-fno-syntax-only) 
> LangUrlSuffix_Fortran(gfortran/Error-and-Warning-Options.html#index-fsyntax-only)
> -
> ffree-form
> LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-ffree-form)
> 
> 
>Jakub
> 


Re: [PATCH v2] libstdc++: Fix std::string construction from volatile char* [PR119748]

2025-04-14 Thread Tomasz Kaminski
On Mon, Apr 14, 2025 at 5:06 PM Jonathan Wakely  wrote:

> My recent r15-9381-g648d5c26e25497 change assumes that a contiguous
> iterator with the correct value_type can be converted to a const charT*
> but that's not true for volatile charT*. The optimization should only be
> done if it can be converted to the right pointer type.
>
> Additionally, the generic loop for non-contiguous iterators needs an
> explicit cast to deal with iterators that have a reference type that is
> not explicitly convertible to charT.
>
As mentioned before, we do not need to handle explicit conversion for CharT.
We still need to perform static_cast to create a temporary CharT when
passing
to traits::assign, as otherwise we will get a mismatch in deduction.

>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/119748
> * include/bits/basic_string.h (_S_copy_chars): Only optimize for
> contiguous iterators that are convertible to const charT*. Use
> explicit conversion to charT after dereferencing iterator.
> (_S_copy_range): Likewise for contiguous ranges.
> * include/bits/basic_string.tcc (_M_construct): Use explicit
> conversion to charT after dereferencing input iterator.
> * include/bits/cow_string.h (_S_copy_chars): Likewise.
> (basic_string(from_range_t, R&&, const Allocator&)): Likewise.
> Only optimize for contiguous iterators that are convertible to
> const charT*.
> * testsuite/21_strings/basic_string/cons/char/119748.cc: New
> test.
> * testsuite/21_strings/basic_string/cons/wchar_t/119748.cc:
> New test.
> ---
>
> Changes in v2:
> - Added static_assert in _M_construct overload for input iterators.
> - Added tests using non-contiguous iterators.
>
>  libstdc++-v3/include/bits/basic_string.h  | 24 +---
>  libstdc++-v3/include/bits/basic_string.tcc|  3 +-
>  libstdc++-v3/include/bits/cow_string.h| 17 --
>  .../basic_string/cons/char/119748.cc  | 55 +++
>  .../basic_string/cons/wchar_t/119748.cc   |  7 +++
>  5 files changed, 93 insertions(+), 13 deletions(-)
>  create mode 100644
> libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc
>  create mode 100644
> libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc
>
> diff --git a/libstdc++-v3/include/bits/basic_string.h
> b/libstdc++-v3/include/bits/basic_string.h
> index 9c431c765ab..c90bd099b63 100644
> --- a/libstdc++-v3/include/bits/basic_string.h
> +++ b/libstdc++-v3/include/bits/basic_string.h
> @@ -488,8 +488,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
>   is_same<_IterBase, const _CharT*>>::value)
> _S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
>  #if __cpp_lib_concepts
> - else if constexpr (contiguous_iterator<_Iterator>
> -  && is_same_v,
> _CharT>)
> + else if constexpr (requires {
> +  requires contiguous_iterator<_Iterator>;
> +  { std::to_address(__k1) }
> +-> convertible_to;
> +})
>
I would prefer, but this is not a strong preference.
   if constexpr (ranges::contiguous_range<_Rg>)
 if constexpr
(convertible_to(__rg))), const
CharT*>>)


> {
>   const auto __d = __k2 - __k1;
>   (void) (__k1 + __d); // See P3349R1
> @@ -499,7 +502,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
>   else
>  #endif
>   for (; __k1 != __k2; ++__k1, (void)++__p)
> -   traits_type::assign(*__p, *__k1); // These types are off.
> +   traits_type::assign(*__p, static_cast<_CharT>(*__k1));
> }
>  #pragma GCC diagnostic pop
>
> @@ -527,12 +530,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> static constexpr void
> _S_copy_range(pointer __p, _Rg&& __rg, size_type __n)
> {
> - if constexpr (ranges::contiguous_range<_Rg>
> - && is_same_v, _CharT>)
> + if constexpr (requires {
> + requires ranges::contiguous_range<_Rg>;
> + { ranges::data(std::forward<_Rg>(__rg)) }
> +   -> convertible_to;
>
Same as before.

+   })
> _S_copy(__p, ranges::data(std::forward<_Rg>(__rg)), __n);
>   else
> -   for (auto&& __e : __rg)
> - traits_type::assign(*__p++,
> std::forward(__e));
> +   {
> + auto __first = ranges::begin(__rg);
> + const auto __last = ranges::end(__rg);
> + for (; __first != __last; ++__first)
> +   traits_type::assign(*__p++, static_cast<_CharT>(*__first));
> +   }
> }
>  #endif
>
> diff --git a/libstdc++-v3/include/bits/basic_string.tcc
> b/libstdc++-v3/include/bits/basic_string.tcc
> index 02230aca5d2..bca55bc5658 100644
> --- a/libstdc++-v3/include/bits/basic_string.tcc
> +++ 

[PATCH] cobol: Fix up COBOL -include [PR119777]

2025-04-14 Thread Jakub Jelinek
Hi!

I was looking through options.cc diff between GCC 14 and 15, looking for
entries with added CL_Cobol where at least one other language is present
and was present before too.  Besides the -fsyntax-only changes this is
the only other one I found, COBOL adds Var(cobol_include) to something
which didn't have a Var at all before and IMHO it is actively harmful.
Because one can specify multiple -include file1 -include file2 options,
both in C/C++ etc. and in COBOL as well (as documented in the man
page).  A Var can track just one entry.  cobol_langhook_handle_option
should use arg instead.

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

2025-04-14  Jakub Jelinek  

PR cobol/119777
* lang.opt (include): Remove Var(cobol_include).
* cobol1.cc (cobol_langhook_handle_option) : Use
arg instead of cobol_include.

--- gcc/cobol/lang.opt.jj   2025-04-14 10:56:28.739693026 +0200
+++ gcc/cobol/lang.opt  2025-04-14 11:08:31.808821317 +0200
@@ -114,7 +114,7 @@ Cobol Joined Separate
 ; Documented in C
 
 include
-Cobol Joined Separate Var(cobol_include)
+Cobol Joined Separate
 ; Documented in C
 
 isysroot
--- gcc/cobol/cobol1.cc.jj  2025-04-12 13:10:31.592523688 +0200
+++ gcc/cobol/cobol1.cc 2025-04-14 11:09:22.619126924 +0200
@@ -413,8 +413,8 @@ cobol_langhook_handle_option (size_t sco
   }
   return true;
 case OPT_include:
-  if( ! include_file_add(cobol_include) ) {
-cbl_errx( "could not include %s", cobol_include);
+  if( ! include_file_add(arg) ) {
+cbl_errx( "could not include %s", arg);
   }
 return true;
 

Jakub



Re: [PATCH] cobol: Fix up COBOL -include [PR119777]

2025-04-14 Thread Richard Biener



> Am 14.04.2025 um 17:59 schrieb Jakub Jelinek :
> 
> Hi!
> 
> I was looking through options.cc diff between GCC 14 and 15, looking for
> entries with added CL_Cobol where at least one other language is present
> and was present before too.  Besides the -fsyntax-only changes this is
> the only other one I found, COBOL adds Var(cobol_include) to something
> which didn't have a Var at all before and IMHO it is actively harmful.
> Because one can specify multiple -include file1 -include file2 options,
> both in C/C++ etc. and in COBOL as well (as documented in the man
> page).  A Var can track just one entry.  cobol_langhook_handle_option
> should use arg instead.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok

Richard 

> 2025-04-14  Jakub Jelinek  
> 
>PR cobol/119777
>* lang.opt (include): Remove Var(cobol_include).
>* cobol1.cc (cobol_langhook_handle_option) : Use
>arg instead of cobol_include.
> 
> --- gcc/cobol/lang.opt.jj2025-04-14 10:56:28.739693026 +0200
> +++ gcc/cobol/lang.opt2025-04-14 11:08:31.808821317 +0200
> @@ -114,7 +114,7 @@ Cobol Joined Separate
> ; Documented in C
> 
> include
> -Cobol Joined Separate Var(cobol_include)
> +Cobol Joined Separate
> ; Documented in C
> 
> isysroot
> --- gcc/cobol/cobol1.cc.jj2025-04-12 13:10:31.592523688 +0200
> +++ gcc/cobol/cobol1.cc2025-04-14 11:09:22.619126924 +0200
> @@ -413,8 +413,8 @@ cobol_langhook_handle_option (size_t sco
>   }
>   return true;
> case OPT_include:
> -  if( ! include_file_add(cobol_include) ) {
> -cbl_errx( "could not include %s", cobol_include);
> +  if( ! include_file_add(arg) ) {
> +cbl_errx( "could not include %s", arg);
>   }
> return true;
> 
> 
>Jakub
> 


Re: [Fortran, Patch, Teams, 0/5] Improve on Fortran 2018 teams support

2025-04-14 Thread Jerry D

On 4/13/25 11:47 PM, Andre Vehreschild wrote:

Hi Jerry,

thank you very much for the review.

I would love to fix the nits you found, but I don't see, what you see. Can you
elaborate? May be some mail client has removed something, or I am missing
something. Are you commenting on


  gfc_error (
 "%s argument at %L must be a scalar %s variable of at least kind %d",


that this is formatted like this, i.e. the string in the next line? That is
clang-format's doing. That formatter is getting worse in each iteration.

I see this in the second and third chunk of your comment, too. Is this what you
like me to fix? I just want to prevent overlooking some typo or the like.

Thanks again and regards,
Andre



Yes, there appears to be some line breaks out of place like this one 
below. I only saw those in the one file after applying the patch. It is 
not critical, so proceed as you prefer.


Thanks,

Jerry

--- snip ---


 gfc_resolve_expr (e);
if (e
   && (e->ts.type != exp_type || e->ts.kind < exp_kind || e->rank != 0
  || e->expr_type != EXPR_VARIABLE))
  gfc_error (
 "%s argument at %L must be a scalar %s variable of at least kind %d",
name, &e->where, gfc_basic_typename (exp_type), exp_kind);



[PATCH v2] libstdc++: Fix std::string construction from volatile char* [PR119748]

2025-04-14 Thread Jonathan Wakely
My recent r15-9381-g648d5c26e25497 change assumes that a contiguous
iterator with the correct value_type can be converted to a const charT*
but that's not true for volatile charT*. The optimization should only be
done if it can be converted to the right pointer type.

Additionally, the generic loop for non-contiguous iterators needs an
explicit cast to deal with iterators that have a reference type that is
not explicitly convertible to charT.

libstdc++-v3/ChangeLog:

PR libstdc++/119748
* include/bits/basic_string.h (_S_copy_chars): Only optimize for
contiguous iterators that are convertible to const charT*. Use
explicit conversion to charT after dereferencing iterator.
(_S_copy_range): Likewise for contiguous ranges.
* include/bits/basic_string.tcc (_M_construct): Use explicit
conversion to charT after dereferencing input iterator.
* include/bits/cow_string.h (_S_copy_chars): Likewise.
(basic_string(from_range_t, R&&, const Allocator&)): Likewise.
Only optimize for contiguous iterators that are convertible to
const charT*.
* testsuite/21_strings/basic_string/cons/char/119748.cc: New
test.
* testsuite/21_strings/basic_string/cons/wchar_t/119748.cc:
New test.
---

Changes in v2:
- Added static_assert in _M_construct overload for input iterators.
- Added tests using non-contiguous iterators.

 libstdc++-v3/include/bits/basic_string.h  | 24 +---
 libstdc++-v3/include/bits/basic_string.tcc|  3 +-
 libstdc++-v3/include/bits/cow_string.h| 17 --
 .../basic_string/cons/char/119748.cc  | 55 +++
 .../basic_string/cons/wchar_t/119748.cc   |  7 +++
 5 files changed, 93 insertions(+), 13 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc
 create mode 100644 
libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index 9c431c765ab..c90bd099b63 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -488,8 +488,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
  is_same<_IterBase, const _CharT*>>::value)
_S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
 #if __cpp_lib_concepts
- else if constexpr (contiguous_iterator<_Iterator>
-  && is_same_v, _CharT>)
+ else if constexpr (requires {
+  requires contiguous_iterator<_Iterator>;
+  { std::to_address(__k1) }
+-> convertible_to;
+})
{
  const auto __d = __k2 - __k1;
  (void) (__k1 + __d); // See P3349R1
@@ -499,7 +502,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
  else
 #endif
  for (; __k1 != __k2; ++__k1, (void)++__p)
-   traits_type::assign(*__p, *__k1); // These types are off.
+   traits_type::assign(*__p, static_cast<_CharT>(*__k1));
}
 #pragma GCC diagnostic pop
 
@@ -527,12 +530,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
static constexpr void
_S_copy_range(pointer __p, _Rg&& __rg, size_type __n)
{
- if constexpr (ranges::contiguous_range<_Rg>
- && is_same_v, _CharT>)
+ if constexpr (requires {
+ requires ranges::contiguous_range<_Rg>;
+ { ranges::data(std::forward<_Rg>(__rg)) }
+   -> convertible_to;
+   })
_S_copy(__p, ranges::data(std::forward<_Rg>(__rg)), __n);
  else
-   for (auto&& __e : __rg)
- traits_type::assign(*__p++, std::forward(__e));
+   {
+ auto __first = ranges::begin(__rg);
+ const auto __last = ranges::end(__rg);
+ for (; __first != __last; ++__first)
+   traits_type::assign(*__p++, static_cast<_CharT>(*__first));
+   }
}
 #endif
 
diff --git a/libstdc++-v3/include/bits/basic_string.tcc 
b/libstdc++-v3/include/bits/basic_string.tcc
index 02230aca5d2..bca55bc5658 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -210,7 +210,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_data(__another);
_M_capacity(__capacity);
  }
-   traits_type::assign(_M_data()[__len++], *__beg);
+   traits_type::assign(_M_data()[__len++],
+   static_cast<_CharT>(*__beg));
++__beg;
  }
 
diff --git a/libstdc++-v3/include/bits/cow_string.h 
b/libstdc++-v3/include/bits/cow_string.h
index b250397151b..f9df2be20be 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -423,7 +423,7 @@ _GLIBCXX_BEG

Re: Asan/Tsan Unit/Regression testing (was [asan] Emit GIMPLE direclty, small cleanups)

2025-04-14 Thread Thomas Schwinge
Hi!

I've got a question regarding the 'gcc/testsuite/lib/asan-dg.exp'
overriding of '${tool}_load', which was introduced here,
Subversion r193511 (Git commit 8335a6439ddb66aa9ebc67ee47aa2e6e317e3ef9):

On 2012-11-14T12:11:13+0100, Jakub Jelinek  wrote:
> --- gcc/testsuite/lib/asan-dg.exp.jj  2012-11-14 09:11:13.086054131 +0100
> +++ gcc/testsuite/lib/asan-dg.exp 2012-11-14 11:45:40.142061595 +0100

> +# Replace ${tool}_load with a wrapper so that we can symbolize the output.
> +if { [info procs ${tool}_load] != [list] \
> +  && [info procs saved_asan_${tool}_load] == [list] } {
> +rename ${tool}_load saved_asan_${tool}_load
> +
> +proc ${tool}_load { program args } {
> + global tool
> + set result [eval [list saved_asan_${tool}_load $program] $args]
> + set output [lindex $result 1]
> + set symbolized_output [asan_symbolize "$output"]
> + set result [list [lindex $result 0] $symbolized_output]
> + return $result
> +}
> +}

So, once 'load_lib asan-dg.exp' has been done, this globally wraps
'${tool}_load', forever, for all following '*.exp' test suites, too.
This introduces overhead: routes every '${tool}_load' through
'asan_symbolize', even for non-ASAN '*.exp' test suites.

Following the usual pattern, shouldn't we do such wrapping only locally,
where necessary?  Here, I suppose we could move this wrapping setup into
'asan_init', and then undo it in 'asan_finish'.

I'll be happy to draft a patch if someone confirms my thinking.


Grüße
 Thomas


[PATCH] tree-optimization/119757 - reject mixed mask/non-mask ldst SLP

2025-04-14 Thread Richard Biener
The following makes sure to not mix masked/non-masked stmts when
forming a SLP node.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

PR tree-optimization/119757
* tree-vect-slp.cc (vect_build_slp_tree_1): Record and compare
whether a stmt uses a maks.

* gcc.dg/vect/pr119757.c: New testcase.
---
 gcc/testsuite/gcc.dg/vect/pr119757.c | 17 +
 gcc/tree-vect-slp.cc | 24 
 2 files changed, 33 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr119757.c

diff --git a/gcc/testsuite/gcc.dg/vect/pr119757.c 
b/gcc/testsuite/gcc.dg/vect/pr119757.c
new file mode 100644
index 000..86442998628
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr119757.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+void base64_encode(const char *table64,
+   const char *inputbuff, int insize,
+   char * __restrict output)
+{
+  const unsigned char *in = (const unsigned char *)inputbuff;
+
+  while(insize >= 3) {
+*output++ = table64[ in[0] >> 2 ];
+*output++ = table64[ ((in[0] & 0x03) << 4) | (in[1] >> 4) ];
+*output++ = table64[ ((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6) ];
+*output++ = table64[ in[2] & 0x3F ];
+insize -= 3;
+in += 3;
+  }
+}
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 7e1cba5c239..23a14ae6071 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -1100,7 +1100,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
   tree first_lhs = NULL_TREE;
   tree first_op1 = NULL_TREE;
   stmt_vec_info first_load = NULL, prev_first_load = NULL;
-  bool first_stmt_ldst_p = false;
+  bool first_stmt_ldst_p = false, first_stmt_ldst_masklen_p = false;
   bool first_stmt_phi_p = false;
   int first_reduc_idx = -1;
   bool maybe_soft_fail = false;
@@ -1134,6 +1134,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
   FOR_EACH_VEC_ELT (stmts, i, stmt_info)
 {
   bool ldst_p = false;
+  bool ldst_masklen_p = false;
   bool phi_p = false;
   code_helper rhs_code = ERROR_MARK;
 
@@ -1196,17 +1197,22 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
  else
rhs_code = CALL_EXPR;
 
- if (cfn == CFN_MASK_LOAD
- || cfn == CFN_GATHER_LOAD
- || cfn == CFN_MASK_GATHER_LOAD
- || cfn == CFN_MASK_LEN_GATHER_LOAD
- || cfn == CFN_SCATTER_STORE
- || cfn == CFN_MASK_SCATTER_STORE
- || cfn == CFN_MASK_LEN_SCATTER_STORE)
+ if (cfn == CFN_GATHER_LOAD
+ || cfn == CFN_SCATTER_STORE)
ldst_p = true;
+ else if (cfn == CFN_MASK_LOAD
+  || cfn == CFN_MASK_GATHER_LOAD
+  || cfn == CFN_MASK_LEN_GATHER_LOAD
+  || cfn == CFN_MASK_SCATTER_STORE
+  || cfn == CFN_MASK_LEN_SCATTER_STORE)
+   {
+ ldst_p = true;
+ ldst_masklen_p = true;
+   }
  else if (cfn == CFN_MASK_STORE)
{
  ldst_p = true;
+ ldst_masklen_p = true;
  rhs_code = CFN_MASK_STORE;
}
  else if (cfn == CFN_GOMP_SIMD_LANE)
@@ -1247,6 +1253,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
  first_lhs = lhs;
  first_stmt_code = rhs_code;
  first_stmt_ldst_p = ldst_p;
+ first_stmt_ldst_masklen_p = ldst_masklen_p;
  first_stmt_phi_p = phi_p;
  first_reduc_idx = STMT_VINFO_REDUC_IDX (stmt_info);
 
@@ -1365,6 +1372,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char 
*swap,
  && (STMT_VINFO_GATHER_SCATTER_P (stmt_info)
  != STMT_VINFO_GATHER_SCATTER_P (first_stmt_info)))
  || first_stmt_ldst_p != ldst_p
+ || (ldst_p && first_stmt_ldst_masklen_p != ldst_masklen_p)
  || first_stmt_phi_p != phi_p)
{
  if (dump_enabled_p ())
-- 
2.43.0


[COMMITTED 10/19] gccrs: expansion: Only add fragments if the matcher succeeded

2025-04-14 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* expand/rust-macro-expand.cc (MacroExpander::match_n_matches): Do not
insert fragments and substack fragments if the matcher failed.

gcc/testsuite/ChangeLog:

* rust/compile/macros/mbe/macro-issue3708.rs: New test.
---
 gcc/rust/expand/rust-macro-expand.cc  | 15 ++--
 .../compile/macros/mbe/macro-issue3708.rs | 80 +++
 2 files changed, 88 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs

diff --git a/gcc/rust/expand/rust-macro-expand.cc 
b/gcc/rust/expand/rust-macro-expand.cc
index cd17a3f9ba1..6e62a083ae7 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -621,9 +621,10 @@ MacroExpander::match_n_matches (Parser 
&parser,
// matched fragment get the offset in the token stream
size_t offs_end = source.get_offs ();
 
-   sub_stack.insert_metavar (
- MatchedFragment (fragment->get_ident ().as_string (),
-  offs_begin, offs_end));
+   if (valid_current_match)
+ sub_stack.insert_metavar (
+   MatchedFragment (fragment->get_ident ().as_string (),
+offs_begin, offs_end));
  }
  break;
 
@@ -650,15 +651,15 @@ MacroExpander::match_n_matches (Parser 
&parser,
}
   auto old_stack = sub_stack.pop ();
 
-  // nest metavars into repetitions
-  for (auto &ent : old_stack)
-   sub_stack.append_fragment (ent.first, std::move (ent.second));
-
   // If we've encountered an error once, stop trying to match more
   // repetitions
   if (!valid_current_match)
break;
 
+  // nest metavars into repetitions
+  for (auto &ent : old_stack)
+   sub_stack.append_fragment (ent.first, std::move (ent.second));
+
   match_amount++;
 
   // Break early if we notice there's too many expressions already
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs 
b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
new file mode 100644
index 000..e5b38bb0da7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
@@ -0,0 +1,80 @@
+// { dg-additional-options "-frust-name-resolution-2.0 
-frust-compile-until=lowering" }
+
+macro_rules! impl_fn_for_zst {
+($(
+$( #[$attr: meta] )*
+struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
+|$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
+$body: block;
+)+) => {
+$(
+$( #[$attr] )*
+struct $Name;
+
+impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
+#[inline]
+extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, 
)*)) -> $ReturnTy {
+$body
+}
+}
+
+impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
+#[inline]
+extern "rust-call" fn call_mut(
+&mut self,
+($( $arg, )*): ($( $ArgTy, )*)
+) -> $ReturnTy {
+Fn::call(&*self, ($( $arg, )*))
+}
+}
+
+impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
+type Output = $ReturnTy;
+
+#[inline]
+extern "rust-call" fn call_once(self, ($( $arg, )*): ($( 
$ArgTy, )*)) -> $ReturnTy {
+Fn::call(&self, ($( $arg, )*))
+}
+}
+)+
+}
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "fn"]
+pub trait Fn: FnMut {
+/// Performs the call operation.
+#[unstable(feature = "fn_traits", issue = "29625")]
+extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn_mut"]
+#[must_use = "closures are lazy and do nothing unless called"]
+pub trait FnMut: FnOnce {
+/// Performs the call operation.
+#[unstable(feature = "fn_traits", issue = "29625")]
+extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn_once"]
+pub trait FnOnce {
+/// The returned type after the call operator is used.
+#[lang = "fn_once_output"]
+#[stable(feature = "fn_once_output", since = "1.12.0")]
+type Output;
+
+/// Performs the call operation.
+#[unstable(feature = "fn_traits", issue = "29625")]
+extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+impl_fn_for_zst! {
+#[derive(Copy)]
+struct LinesAnyMap impl<'a> Fn = |line: &'a str| -> () {
+};
+}
-- 
2.49.0



[COMMITTED 01/19] rust: Use FLOAT_TYPE_P instead of manual checking

2025-04-14 Thread arthur . cohen
From: Andrew Pinski 

This moves is_floating_point over to using FLOAT_TYPE_P instead
of manually checking. Note before it would return true for all
COMPLEX_TYPE but complex types' inner type could be integral.

Also fixes up the comment to be in more of the GNU style.

Bootstrapped and tested on x86_64-linux-gnu.

gcc/rust/ChangeLog:

* rust-gcc.cc (is_floating_point): Use FLOAT_TYPE_P
instead of manually checking the type.

Signed-off-by: Andrew Pinski 
---
 gcc/rust/rust-gcc.cc | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 72aef08e35a..7c5af211bbc 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -1021,12 +1021,12 @@ operator_to_tree_code (LazyBooleanOperator op)
 }
 }
 
-/* Helper function for deciding if a tree is a floating point node. */
+/* Returns true if the type of EXP is a floating point type.
+   False otherwise.  */
 bool
-is_floating_point (tree t)
+is_floating_point (tree exp)
 {
-  auto tree_type = TREE_CODE (TREE_TYPE (t));
-  return tree_type == REAL_TYPE || tree_type == COMPLEX_TYPE;
+  return FLOAT_TYPE_P (TREE_TYPE (exp));
 }
 
 // Return an expression for the negation operation OP EXPR.
-- 
2.49.0



Re: [PATCH] AArch64: Fix operands order in vec_extract expander

2025-04-14 Thread Kyrylo Tkachov
Hi Tejas,

> On 14 Apr 2025, at 16:04, Tejas Belagod  wrote:
> 
> The operand order to gen_vcond_mask call in the vec_extract pattern is wrong.
> Fix the order where predicate is operand 3.
> 
> Tested and bootstrapped on aarch64-linux-gnu. OK for trunk?
> 
> gcc/ChangeLog
> 
> * config/aarch64/aarch64-sve.md (vec_extract): Fix operand
> order to gen_vcond_mask_*.
> ---
> gcc/config/aarch64/aarch64-sve.md | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/gcc/config/aarch64/aarch64-sve.md 
> b/gcc/config/aarch64/aarch64-sve.md
> index 3dbd65986ec..d4af3706294 100644
> --- a/gcc/config/aarch64/aarch64-sve.md
> +++ b/gcc/config/aarch64/aarch64-sve.md
> @@ -3133,9 +3133,9 @@
>   "TARGET_SVE"
>   {
> rtx tmp = gen_reg_rtx (mode);
> -emit_insn (gen_vcond_mask_ (tmp, operands[1],
> - CONST1_RTX (mode),
> - CONST0_RTX (mode)));
> +emit_insn (gen_vcond_mask_ (tmp, CONST1_RTX (mode),
> + CONST0_RTX (mode),
> + operands[1]));
> emit_insn (gen_vec_extract (operands[0], tmp, operands[2]));
> DONE;

Looks like a correct fix, is there a test case where this causes a problem?
Does it need back porting?

Thanks,
Kyrill


>   }
> -- 
> 2.25.1
> 



Re: [v2] Polish 'dg-output-file' test logs (was: [PATCH] testsuite: Add support for dg-output-file directive)

2025-04-14 Thread Jakub Jelinek
On Mon, Apr 14, 2025 at 07:47:21PM +0200, Thomas Schwinge wrote:
>   gcc/testsuite/
>   * lib/gcc-dg.exp (${tool}_load): Polish 'dg-output-file' test
>   logs.
> ---
>  gcc/testsuite/lib/gcc-dg.exp | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
> index eadc1cd90bc..6dd8fa3fce9 100644
> --- a/gcc/testsuite/lib/gcc-dg.exp
> +++ b/gcc/testsuite/lib/gcc-dg.exp
> @@ -507,8 +507,7 @@ if { [info procs ${tool}_load] != [list] \
>   set linenum 1
>   set outfile [open [lindex ${output-file} 1]]
>   set do_fail 0
> - set name [file tail [lindex ${output-file} 1]]
> - verbose "output-file args is $args program is $program" 1
> + set name [testname-for-summary]
>   while { [gets $outfile line] >= 0 } {
>   if { $linenum != 1 } {
>   set c [string index $output $idx]

LGTM, thanks.

Jakub



[PATCH] libatomic: Fix up libat_{,un}lock_n [PR119796]

2025-04-14 Thread Jakub Jelinek
Hi!

As mentioned in the PR (and I think in PR101075 too), we can run into
deadlock with libat_lock_n calls with larger n.
As mentioned in PR66842, we use multiple locks (normally 64 mutexes
for each 64 byte cache line in 4KiB page) and currently can lock more
than one lock, in particular for n [0, 64] a single lock, for n [65, 128]
2 locks, for n [129, 192] 3 locks etc.
There are two problems with this:
1) we can deadlock if there is some wrap-around, because the locks are
   acquired always in the order from addr_hash (ptr) up to
   locks[NLOCKS-1].mutex and then if needed from locks[0].mutex onwards;
   so if e.g. 2 threads perform libat_lock_n with n = 2048+64, in one
   case at pointer starting at page boundary and in another case at
   page boundary + 2048 bytes, the first thread can lock the first
   32 mutexes, the second thread can lock the last 32 mutexes and
   then first thread wait for the lock 32 held by second thread and
   second thread wait for the lock 0 held by the first thread;
   fixed below by always locking the locks in order of increasing
   index, if there is a wrap-around, by locking in 2 loops, first
   locking some locks at the start of the array and second at the
   end of it
2) the number of locks seems to be determined solely depending on the
   n value, I think that is wrong, we don't know the structure alignment
   on the libatomic side, it could very well be 1 byte aligned struct,
   and so how many cachelines are actually (partly or fully) occupied
   by the atomic access depends not just on the size, but also on
   ptr % WATCH_SIZE, e.g. 2 byte structure at address page_boundary+63
   should IMHO lock 2 locks because it occupies the first and second
   cacheline

Note, before this patch it locked exactly one lock for n = 0, while
with this patch it could lock either no locks at all (if it is at cacheline
boundary) or 1 (otherwise).
Dunno of libatomic APIs can be called for zero sizes and whether
we actually care that much how many mutexes are locked in that case,
because one can't actually read/write anything into zero sized memory.
If you think it is important, I could add else if (nlocks == 0) nlocks = 1;
in both spots.

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

2025-04-14  Jakub Jelinek  

PR libstdc++/119796
* config/posix/lock.c (libat_lock_n, libat_unlock_n): Start with
computing how many locks will be needed and take into account
((uintptr_t)ptr % WATCH_SIZE).  If some locks from the end of the
locks array and others from the start of it will be needed, first
lock the ones from the start followed by ones from the end.

--- libatomic/config/posix/lock.c.jj2025-04-08 14:09:40.988589457 +0200
+++ libatomic/config/posix/lock.c   2025-04-14 14:27:11.933210898 +0200
@@ -81,19 +81,22 @@ libat_lock_n (void *ptr, size_t n)
 {
   uintptr_t h = addr_hash (ptr);
   size_t i = 0;
+  size_t nlocks
+= (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE;
 
   /* Don't lock more than all the locks we have.  */
-  if (n > PAGE_SIZE)
-n = PAGE_SIZE;
+  if (nlocks > NLOCKS)
+nlocks = NLOCKS;
 
-  do
+  if (__builtin_expect (h + nlocks > NLOCKS, 0))
 {
-  pthread_mutex_lock (&locks[h].mutex);
-  if (++h == NLOCKS)
-   h = 0;
-  i += WATCH_SIZE;
+  size_t j = h + nlocks - NLOCKS;
+  for (; i < j; ++i)
+   pthread_mutex_lock (&locks[i].mutex);
 }
-  while (i < n);
+
+  for (; i < nlocks; ++i)
+pthread_mutex_lock (&locks[h++].mutex);
 }
 
 void
@@ -101,16 +104,20 @@ libat_unlock_n (void *ptr, size_t n)
 {
   uintptr_t h = addr_hash (ptr);
   size_t i = 0;
+  size_t nlocks
+= (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE;
 
-  if (n > PAGE_SIZE)
-n = PAGE_SIZE;
+  /* Don't lock more than all the locks we have.  */
+  if (nlocks > NLOCKS)
+nlocks = NLOCKS;
 
-  do
+  if (__builtin_expect (h + nlocks > NLOCKS, 0))
 {
-  pthread_mutex_unlock (&locks[h].mutex);
-  if (++h == NLOCKS)
-   h = 0;
-  i += WATCH_SIZE;
+  size_t j = h + nlocks - NLOCKS;
+  for (; i < j; ++i)
+   pthread_mutex_unlock (&locks[i].mutex);
 }
-  while (i < n);
+
+  for (; i < nlocks; ++i)
+pthread_mutex_unlock (&locks[h++].mutex);
 }

Jakub



[PATCH] libatomic: Fix up libat_{,un}lock_n for mingw [PR119796]

2025-04-14 Thread Jakub Jelinek
Hi!

Here is just a port of the previously posted patch to mingw which
clearly has the same problems.

Untested though, I don't have Windows anywhere around.

2025-04-14  Jakub Jelinek  

PR libstdc++/119796
* config/mingw/lock.c (libat_lock_n, libat_unlock_n): Start with
computing how many locks will be needed and take into account
((uintptr_t)ptr % WATCH_SIZE).  If some locks from the end of the
locks array and others from the start of it will be needed, first
lock the ones from the start followed by ones from the end.

--- libatomic/config/mingw/lock.c.jj2025-04-08 14:09:40.988589457 +0200
+++ libatomic/config/mingw/lock.c   2025-04-14 15:39:08.244686172 +0200
@@ -87,21 +87,30 @@ libat_lock_n (void *ptr, size_t n)
 {
   uintptr_t h = addr_hash (ptr);
   size_t i = 0;
+  size_t nlocks
+= (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE;
 
   /* Don't lock more than all the locks we have.  */
-  if (n > PAGE_SIZE)
-n = PAGE_SIZE;
+  if (nlocks > NLOCKS)
+nlocks = NLOCKS;
 
-  do
+  if (__builtin_expect (h + nlocks > NLOCKS, 0))
+{
+  size_t j = h + nlocks - NLOCKS;
+  for (; i < j; ++i)
+   {
+ if (!locks[i].mutex)
+   locks[i].mutex = CreateMutex (NULL, FALSE, NULL);
+ WaitForSingleObject (locks[i].mutex, INFINITE);
+   }
+}
+
+  for (; i < nlocks; ++i)
 {
   if (!locks[h].mutex)
-   locks[h].mutex = CreateMutex  (NULL, FALSE, NULL);
-  WaitForSingleObject (locks[h].mutex, INFINITE);
-  if (++h == NLOCKS)
-   h = 0;
-  i += WATCH_SIZE;
+   locks[h].mutex = CreateMutex (NULL, FALSE, NULL);
+  WaitForSingleObject (locks[h++].mutex, INFINITE);
 }
-  while (i < n);
 }
 
 void
@@ -109,17 +118,22 @@ libat_unlock_n (void *ptr, size_t n)
 {
   uintptr_t h = addr_hash (ptr);
   size_t i = 0;
+  size_t nlocks
+= (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE;
 
-  if (n > PAGE_SIZE)
-n = PAGE_SIZE;
+  /* Don't lock more than all the locks we have.  */
+  if (nlocks > NLOCKS)
+nlocks = NLOCKS;
 
-  do
+  if (__builtin_expect (h + nlocks > NLOCKS, 0))
 {
-  if (locks[h].mutex)
-   ReleaseMutex (locks[h].mutex);
-  if (++h == NLOCKS)
-   h = 0;
-  i += WATCH_SIZE;
+  size_t j = h + nlocks - NLOCKS;
+  for (; i < j; ++i)
+   if (locks[i].mutex)
+ ReleaseMutex (locks[i].mutex);
 }
-  while (i < n);
+
+  for (; i < nlocks; ++i, ++h)
+if (locks[h].mutex)
+  ReleaseMutex (locks[h].mutex);
 }

Jakub



  1   2   >