aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--MAINTAINERS1
-rw-r--r--config/gthr.m423
-rw-r--r--contrib/ChangeLog10
-rwxr-xr-xcontrib/check_GNU_style_lib.py3
-rwxr-xr-xcontrib/test_installed19
-rw-r--r--gcc/ChangeLog99
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in7
-rw-r--r--gcc/ada/ChangeLog14
-rw-r--r--gcc/ada/rtfinal.c2
-rw-r--r--gcc/ada/rtinit.c3
-rw-r--r--gcc/ada/sem_attr.adb47
-rw-r--r--gcc/analyzer/ChangeLog5
-rw-r--r--gcc/analyzer/kf.cc3
-rw-r--r--gcc/c/c-decl.cc7
-rw-r--r--gcc/c/c-typeck.cc2
-rw-r--r--gcc/cgraph.cc6
-rw-r--r--gcc/cgraphclones.cc4
-rw-r--r--gcc/config/aarch64/aarch64-cores.def5
-rw-r--r--gcc/config/aarch64/aarch64-simd.md12
-rw-r--r--gcc/config/aarch64/aarch64-tune.md2
-rw-r--r--gcc/config/gcn/gcn.cc9
-rw-r--r--gcc/config/gcn/mkoffload.cc9
-rw-r--r--gcc/config/i386/i386-expand.cc9
-rw-r--r--gcc/config/i386/i386.cc15
-rw-r--r--gcc/config/i386/sse.md3
-rw-r--r--gcc/config/mingw/winnt.cc10
-rw-r--r--gcc/config/riscv/autovec.md31
-rw-r--r--gcc/config/riscv/predicates.md2
-rw-r--r--gcc/config/riscv/riscv-c.cc44
-rw-r--r--gcc/config/riscv/riscv-protos.h4
-rw-r--r--gcc/config/riscv/riscv-target-attr.cc96
-rw-r--r--gcc/config/riscv/riscv-v.cc50
-rw-r--r--gcc/config/riscv/riscv.cc47
-rw-r--r--gcc/config/riscv/riscv.opt4
-rw-r--r--gcc/config/riscv/riscv.opt.urls2
-rw-r--r--gcc/config/riscv/vector.md8
-rw-r--r--gcc/config/rs6000/predicates.md5
-rw-r--r--gcc/config/rs6000/vsx.md7
-rw-r--r--gcc/config/s390/predicates.md5
-rw-r--r--gcc/config/s390/vector.md7
-rwxr-xr-xgcc/configure6
-rw-r--r--gcc/configure.ac1
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/pt.cc7
-rw-r--r--gcc/doc/extend.texi12
-rw-r--r--gcc/doc/invoke.texi9
-rw-r--r--gcc/doc/md.texi20
-rw-r--r--gcc/fortran/ChangeLog9
-rw-r--r--gcc/fortran/decl.cc4
-rw-r--r--gcc/gimple-fold.cc225
-rw-r--r--gcc/internal-fn.cc13
-rw-r--r--gcc/optabs-tree.cc31
-rw-r--r--gcc/testsuite/ChangeLog233
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C31
-rw-r--r--gcc/testsuite/g++.dg/torture/pr123040.C61
-rw-r--r--gcc/testsuite/gcc.dg/pointer-counted-by-pr122982.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr123018.c17
-rw-r--r--gcc/testsuite/gcc.dg/tls/data-sections-1.c14
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr123027.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr46555.c28
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr123038.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr123026.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121230.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr123027.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-vec-length-epil-8.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/pragma-target-1.c59
-rw-r--r--gcc/testsuite/gcc.target/riscv/pragma-target-2.c26
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-1.c21
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-2.c21
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122635-1.c20
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122635-2.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123022-2.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123022.c21
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123074.C124
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-1-run.c49
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-1.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-2-run.c49
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-2.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-3-run.c49
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-3.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-4-run.c49
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-4.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-5-run.c47
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-5.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-6-run.c47
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-6.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-7-run.c47
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-7.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-8-run.c47
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-8.c25
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h1
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h136
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i16.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i32.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i64.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i8.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/rvv.exp2
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f901
-rw-r--r--gcc/testsuite/gfortran.dg/automatic_char_len_1.f901
-rw-r--r--gcc/testsuite/gfortran.dg/entry_23.f1
-rw-r--r--gcc/testsuite/gfortran.dg/finalize_59.f904
-rw-r--r--gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f1
-rw-r--r--gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f1
-rw-r--r--gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f1
-rw-r--r--gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f1
-rw-r--r--gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f1
-rw-r--r--gcc/testsuite/gfortran.dg/initialization_9.f901
-rw-r--r--gcc/testsuite/gfortran.dg/intrinsic_actual_4.f901
-rw-r--r--gcc/testsuite/gfortran.dg/namelist_assumed_char.f902
-rw-r--r--gcc/testsuite/gfortran.dg/pr15140.f901
-rw-r--r--gcc/testsuite/gnat.dg/reduce3.adb17
-rw-r--r--gcc/tree-cfg.cc218
-rw-r--r--gcc/tree-cfg.h1
-rw-r--r--gcc/tree-cfgcleanup.cc9
-rw-r--r--gcc/tree-ssa-dce.cc212
-rw-r--r--gcc/tree-ssa-sccvn.cc5
-rw-r--r--gcc/tree-vect-loop.cc1
-rw-r--r--gcc/tree-vect-patterns.cc14
-rw-r--r--gcc/tree-vect-stmts.cc66
-rw-r--r--libatomic/Makefile.in35
-rw-r--r--libatomic/aclocal.m41
-rwxr-xr-xlibatomic/configure27
-rw-r--r--libatomic/configure.ac4
-rw-r--r--libatomic/testsuite/Makefile.in5
-rw-r--r--libcpp/ChangeLog10
-rw-r--r--libgcc/Makefile.in2
-rw-r--r--libgcc/config/rs6000/t-slibgcc-aix8
-rwxr-xr-xlibgcc/configure65
-rw-r--r--libgcc/configure.ac18
-rw-r--r--libgomp/testsuite/lib/libgomp.exp23
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C1
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c1
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-link-3.c1
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-link-4.c1
-rw-r--r--libgomp/testsuite/libgomp.fortran/self_maps.f901
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-1.c2
-rwxr-xr-xlibphobos/configure2
-rw-r--r--libphobos/m4/druntime/os.m42
-rw-r--r--libstdc++-v3/ChangeLog68
-rw-r--r--libstdc++-v3/acinclude.m46
-rwxr-xr-xlibstdc++-v3/configure41
-rw-r--r--libstdc++-v3/include/Makefile.am1
-rw-r--r--libstdc++-v3/include/Makefile.in1
-rw-r--r--libstdc++-v3/include/bits/intcmp.h120
-rw-r--r--libstdc++-v3/include/bits/iterator_concepts.h4
-rw-r--r--libstdc++-v3/include/bits/max_size_type.h6
-rw-r--r--libstdc++-v3/include/bits/sat_arith.h12
-rw-r--r--libstdc++-v3/include/bits/version.def12
-rw-r--r--libstdc++-v3/include/bits/version.h15
-rw-r--r--libstdc++-v3/include/c_compatibility/stdckdint.h32
-rw-r--r--libstdc++-v3/include/ext/numeric_traits.h2
-rw-r--r--libstdc++-v3/include/std/charconv6
-rw-r--r--libstdc++-v3/include/std/concepts23
-rw-r--r--libstdc++-v3/include/std/latch2
-rw-r--r--libstdc++-v3/include/std/mdspan723
-rw-r--r--libstdc++-v3/include/std/type_traits13
-rw-r--r--libstdc++-v3/include/std/utility72
-rw-r--r--libstdc++-v3/include/std/variant34
-rw-r--r--libstdc++-v3/libsupc++/compare7
-rw-r--r--libstdc++-v3/src/c++23/std.cc.in2
-rw-r--r--libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc60
-rw-r--r--libstdc++-v3/testsuite/20_util/variant/112591.cc32
-rw-r--r--libstdc++-v3/testsuite/20_util/variant/87619.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h4
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/generic.cc71
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left.cc9
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded.cc12
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/right.cc9
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/right_padded.cc12
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/stride.cc9
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/testcases.h360
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc301
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc122
-rw-r--r--libstdc++-v3/testsuite/26_numerics/saturation/extended.cc55
-rw-r--r--libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc65
-rw-r--r--libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc28
205 files changed, 5036 insertions, 705 deletions
diff --git a/ChangeLog b/ChangeLog
index 6131707..b39348d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2025-12-08 Nathan Myers <ncm@cantrip.org>
+
+ * MAINTAINERS: add ncm
+
2025-11-30 Jose E. Marchesi <jose.marchesi@oracle.com>
* MAINTAINERS: Add Algol 68 subsystems.
diff --git a/MAINTAINERS b/MAINTAINERS
index 22d4172..53a35b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -706,6 +706,7 @@ Christoph Müllner cmuellner <christoph.muellner@vrull.eu>
Steven Munroe munroesj <munroesj52@gmail.com>
Philippe De Muyter - <phdm@macqel.be>
Joseph Myers jsm28 <josmyers@redhat.com>
+Nathan Myers ncm <ncm@cantrip.org>
Szabolcs Nagy nsz <nsz@gcc.gnu.org>
Victor Do Nascimento victorldn <victor.donascimento@arm.com>
Quentin Neill qneill <quentin.neill.gnu@gmail.com>
diff --git a/config/gthr.m4 b/config/gthr.m4
index 1199624..e8fac4a 100644
--- a/config/gthr.m4
+++ b/config/gthr.m4
@@ -5,6 +5,26 @@ dnl Public License, this file may be distributed as part of a program
dnl that contains a configuration script generated by Autoconf, under
dnl the same distribution terms as the rest of that program.
+dnl Define thread model
+
+dnl usage: GCC_AC_THREAD_MODEL
+AC_DEFUN([GCC_AC_THREAD_MODEL],
+[
+# Specify the threading model for this GCC runtime library
+# Pass with no value to take from compiler's metadata
+# Pass with a value to specify a thread package
+# 'single' means single threaded -- without threads.
+AC_CACHE_CHECK([for the threading model used by GCC], [gcc_cv_target_thread_file], [
+ # Set new cache variable
+ gcc_cv_target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
+])
+# Set variable name (not prefixed enough to be a good cache variable
+# name) traditionally used for this purpose, to avoid having to change
+# a bunch of configure scripts.
+target_thread_file="$gcc_cv_target_thread_file"
+])
+
+
dnl Define header location by thread model
dnl usage: GCC_AC_THREAD_HEADER([thread_model])
@@ -23,6 +43,9 @@ case $1 in
vxworks) thread_header=config/gthr-vxworks.h ;;
win32) thread_header=config/i386/gthr-win32.h ;;
mcf) thread_header=config/i386/gthr-mcf.h ;;
+ *)
+ AC_MSG_ERROR([No known header for threading model '$1'.])
+ ;;
esac
AC_SUBST(thread_header)
])
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index ea2d807..6683ddc 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,13 @@
+2025-12-08 Joseph Myers <josmyers@redhat.com>
+
+ * test_installed (--with-alt-cc=, --with-alt-cxx=)
+ (--with-compat-options=, --with-libiconv=): New options.
+
+2025-12-08 Jonathan Wakely <jwakely@redhat.com>
+
+ * check_GNU_style_lib.py (check_GNU_style_file): Do not check
+ libstdc++ files.
+
2025-12-06 Mark Zhuang <mark.zhuang@spacemit.com>
* prepare-commit-msg: check --default-prefix
diff --git a/contrib/check_GNU_style_lib.py b/contrib/check_GNU_style_lib.py
index faf30c4..fccb3d6 100755
--- a/contrib/check_GNU_style_lib.py
+++ b/contrib/check_GNU_style_lib.py
@@ -285,6 +285,9 @@ def check_GNU_style_file(file, format):
# Skip testsuite files
if 'testsuite' in t or t.endswith('.py'):
continue
+ # Libstdc++ does not use GNU style
+ if t.startswith('libstdc++-v3/'):
+ continue
for hunk in pfile:
delta = 0
diff --git a/contrib/test_installed b/contrib/test_installed
index 77492ca..42c3f12 100755
--- a/contrib/test_installed
+++ b/contrib/test_installed
@@ -42,6 +42,7 @@ if test -f site.exp; then
exit 1
fi
+libiconv=-liconv
while true; do
case "$1" in
--with-testsuite=*) testsuite=`echo "$1" | sed 's/[^=]*=//'`; shift;;
@@ -51,6 +52,10 @@ while true; do
--with-gcc=*) GCC_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;;
--with-g++=*) GXX_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;;
--with-gfortran=*) GFORTRAN_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;;
+ --with-alt-cc=*) ALT_CC_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;;
+ --with-alt-cxx=*) ALT_CXX_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;;
+ --with-compat-options=*) COMPAT_OPTIONS=`echo "$1" | sed 's/[^=]*=//'`; shift;;
+ --with-libiconv=*) libiconv=`echo "$1" | sed 's/[^=]*=//'`; shift;;
--without-gcc) GCC_UNDER_TEST=no; shift;;
--without-g++) GXX_UNDER_TEST=no; shift;;
--without-gfortran) GFORTRAN_UNDER_TEST=no; shift;;
@@ -78,6 +83,10 @@ Supported arguments:
--with-gcc=/some/dir/bin/gcc use specified gcc program [gcc]
--with-g++=/some/dir/bin/g++ use specified g++ program [g++]
--with-gfortran=/some/dir/bin/gfortran use specified gfortran program [gfortran]
+--with-alt-cc=/some/compiler use specified alternative compiler in compat tests
+--with-alt-cxx=/some/compiler use specified alternative compiler in compat tests
+--with-compat-options=opts use specified COMPAT_OPTIONS in compat tests
+--with-libiconv=linker-args use given arguments to link with iconv [-liconv]
--without-gcc do not run gcc testsuite
--without-g++ do not run g++ testsuite
--without-gfortran do not run gfortran testsuite
@@ -108,6 +117,7 @@ cat >site.exp <<EOF
set rootme "."
set tmpdir "${tmpdir-`${PWDCMD-pwd}`}"
set srcdir "${testsuite-${srcdir}/gcc/testsuite}"
+set libiconv "$libiconv"
set CFLAGS ""
set CXXFLAGS ""
set GCC_UNDER_TEST "${GCC_UNDER_TEST-${prefix}${prefix+/bin/}gcc}"
@@ -123,6 +133,15 @@ if test x${target} != x; then
echo "set target_triplet $target" >> site.exp
echo "set target_alias $target" >> site.exp
fi
+if test x"$ALT_CC_UNDER_TEST" != x; then
+ echo "set ALT_CC_UNDER_TEST \"${ALT_CC_UNDER_TEST}\"" >> site.exp
+fi
+if test x"$ALT_CXX_UNDER_TEST" != x; then
+ echo "set ALT_CXX_UNDER_TEST \"${ALT_CXX_UNDER_TEST}\"" >> site.exp
+fi
+if test x"$COMPAT_OPTIONS" != x; then
+ echo "set COMPAT_OPTIONS \"${COMPAT_OPTIONS}\"" >> site.exp
+fi
test x"${GCC_UNDER_TEST}" = x"no" || runtest --tool gcc ${1+"$@"}
test x"${GXX_UNDER_TEST}" = x"no" || runtest --tool g++ ${1+"$@"}
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ed720db..e6da5b8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,102 @@
+2025-12-08 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ PR tree-optimization/46555
+ * tree-cfgcleanup.cc (execute_cleanup_cfg_post_optimizing):
+ Don't set todo to include cleanupcfg; do it manually.
+ Call make_forwarders_with_degenerate_phis if optimizing.
+
+2025-12-08 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ * tree-cfg.cc (make_forwarders_with_degenerate_phis): Add debug
+ dump.
+
+2025-12-08 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ * tree-ssa-dce.cc (sort_phi_args): Move to tree-cfg.cc.
+ (make_forwarders_with_degenerate_phis): Move to tree-cfg.cc.
+ (perform_tree_ssa_dce): Update for the updated return type
+ of make_forwarders_with_degenerate_phis.
+ * tree-cfg.cc (sort_phi_args): Moved from tree-ssa-dce.cc.
+ (make_forwarders_with_degenerate_phis): Moved from tree-ssa-dce.cc.
+ Update return type to bool and return true if an edge was split.
+ * tree-cfg.h (make_forwarders_with_degenerate_phis): New decl.
+
+2025-12-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/80881
+ * config/mingw/winnt.cc (mingw_pe_unique_section): Put two dollar
+ signs for TLS sections after the prefix.
+ (mingw_pe_asm_named_section): Deal with all TLS sections uniformly.
+
+2025-12-08 Ezra Sitorus <Ezra.Sitorus@arm.com>
+
+ * config/aarch64/aarch64-cores.def (AARCH64_CORE): Add C1-Nano,
+ C1-Pro, C1-Premium and C1-Ultra.
+ * config/aarch64/aarch64-tune.md: Regenerate.
+ * doc/invoke.texi: Document C1 cores.
+
+2025-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/123040
+ * tree-ssa-sccvn.cc (vn_nary_build_or_lookup_1): Only insert
+ nary results.
+
+2025-12-08 Josef Melcr <josef.melcr@suse.com>
+
+ PR ipa/122798
+ * cgraph.cc (cgraph_edge::redirect_callee): Use
+ iterate_referring instead of referred_to_p.
+ * cgraphclones.cc (set_new_clone_decl_and_node_flags): Set local
+ to true iff the node does not have its address taken.
+
+2025-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/123038
+ * tree-vect-patterns.cc (vect_recog_ctz_ffs_pattern): Reject
+ pattern for reductions when the call argument is used multiple
+ times.
+
+2025-12-08 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/123026
+ * config/aarch64/aarch64-simd.md (reduc_sbool_ior_scal_<mode>,
+ reduc_sbool_and_scal_<mode>): Fix tmp operands[1] override.
+
+2025-12-08 Tamar Christina <tamar.christina@arm.com>
+
+ PR tree-optimization/122868
+ * tree-vect-stmts.cc (vectorizable_load): Move check for invariant loads
+ down into the loop.
+
+2025-12-08 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/122343
+ * config/i386/sse.md (*<avx512>_cmp<mode>3_dup_op): Don't allow
+ 2 volatile memory references.
+
+2025-12-07 Jason Merrill <jason@redhat.com>
+
+ * config/darwin-c.cc (find_subframework_header): Use
+ _cpp_get_file_*.
+
+2025-12-07 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/122343
+ * common.opt: Add -ffuse-ops-with-volatile-access.
+ * common.opt.urls: Regenerated.
+ * recog.cc (general_operand): Allow volatile memory reference if
+ -ffuse-ops-with-volatile-access is enabled.
+ * simplify-rtx.cc (simplify_binary_operation_1): Keep PLUS for 2
+ volatile memory references.
+ * doc/invoke.texi: Document -ffuse-ops-with-volatile-access.
+
+2025-12-07 Alexandre Oliva <oliva@adacore.com>
+
+ * cselib.cc (dump_cselib_val): Split out of and rename to...
+ (dump_cselib_val_ptr): ... this.
+ (dump_cselib_table): Adjust. Skip cselib_preserved_hash_table
+ when not allocated.
+
2025-12-06 Alexandre Oliva <oliva@adacore.com>
PR rtl-optimization/122947
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 47f4b89..4568345 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20251207
+20251209
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 2c3194e..d623145 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2503,13 +2503,6 @@ libgcc.mvars: config.status Makefile specs xgcc$(exeext)
: > tmp-libgcc.mvars
echo GCC_CFLAGS = '$(GCC_CFLAGS)' >> tmp-libgcc.mvars
echo INHIBIT_LIBC_CFLAGS = '$(INHIBIT_LIBC_CFLAGS)' >> tmp-libgcc.mvars
- echo TARGET_SYSTEM_ROOT = '$(TARGET_SYSTEM_ROOT)' >> tmp-libgcc.mvars
- if test @enable_default_pie@ = yes; then \
- NO_PIE_CFLAGS="-fno-PIE"; \
- else \
- NO_PIE_CFLAGS=; \
- fi; \
- echo NO_PIE_CFLAGS = "$$NO_PIE_CFLAGS" >> tmp-libgcc.mvars
mv tmp-libgcc.mvars libgcc.mvars
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index fca1a9e..8b19deb 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,17 @@
+2025-12-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/123037
+ * rtinit.c [__MINGW32__]: Include <stdlib.h> and not <windows.h>.
+ * rtfinal.c [__MINGW32__]: Do not include <windows.h>.
+
+2025-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/115349
+ * sem_attr.adb (Resolve_Attribute) <Attribute_Reduce>: Use the base
+ type as Accum_Type if the reducer is an operator from Standard and
+ the type is numeric. Use the type of the first operand for other
+ operators. Streamline the error message given for limited types.
+
2025-12-06 Denis Mazzucato <mazzucato@adacore.com>
* sem_attr.adb (Resolve_Attribute): Check if the reducer is a
diff --git a/gcc/ada/rtfinal.c b/gcc/ada/rtfinal.c
index 88bbb0e..0bd3ce4 100644
--- a/gcc/ada/rtfinal.c
+++ b/gcc/ada/rtfinal.c
@@ -46,9 +46,7 @@ extern int __gnat_rt_init_count;
/* see initialize.c */
#if defined (__MINGW32__)
-#define WIN32_LEAN_AND_MEAN
#include "mingw32.h"
-#include <windows.h>
extern CRITICAL_SECTION ProcListCS;
extern HANDLE ProcListEvt;
diff --git a/gcc/ada/rtinit.c b/gcc/ada/rtinit.c
index 598550c..3b5af0d 100644
--- a/gcc/ada/rtinit.c
+++ b/gcc/ada/rtinit.c
@@ -70,9 +70,8 @@ int __gnat_rt_init_count = 0;
and finalize properly the run-time. */
#if defined (__MINGW32__)
-#define WIN32_LEAN_AND_MEAN
+#include <stdlib.h>
#include "mingw32.h"
-#include <windows.h>
extern void __gnat_init_float (void);
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index ca19cad..74e9d6f 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -12919,7 +12919,7 @@ package body Sem_Attr is
-- Where the context is augmented with the iteration
-- variable I of the right type, and Init_Var of type
- -- Accum_Subtype. If the Reducer has both procedure and
+ -- Accum_Typ. If the Reducer has both procedure and
-- function interpretations with the proper reducer profile
-- an ambiguity error is emitted. Note that, this could be a
-- false positive as the two may coexist without ambiguity
@@ -13204,7 +13204,7 @@ package body Sem_Attr is
return;
end if;
- -- If no error has been posted and the accumulation type is
+ -- If no error has been posted and the accumulator type is
-- constrained, then the resolution of the reducer can start.
if Nkind (Reducer_N) = N_Attribute_Reference then
@@ -13252,44 +13252,50 @@ package body Sem_Attr is
end if;
end if;
- -- After resolving the reducer, determine the correct
- -- Accum_Subtype: if the reducer is an attribute (Min or Max),
- -- then the prefix type is the accumulation type.
+ -- After resolving the reducer, determine Accum_Typ: if the
+ -- reducer is an attribute (Min or Max), then its prefix is
+ -- the accumulator type.
if Nkind (Reducer_E) = N_Attribute_Reference then
- Accum_Typ := Etype (Prefix (Reducer_E));
+ Accum_Typ := Entity (Prefix (Reducer_E));
- -- If an operator from standard, then the type of its first
- -- formal woudl be Any_Type, in this case we make sure we don't
- -- use an universal type to avoid resolution problems later on.
+ -- If the reducer is an operator from Standard, then the type
+ -- of its first operand would be Any_Type. In this case, make
+ -- sure we do not have an universal type to avoid resolution
+ -- problems later on, and use the base type of numeric types
+ -- to avoid spurious subtype mismatches for the initial value.
- elsif Ekind (Reducer_E) = E_Operator
- or else Scope (Reducer_E) = Standard_Standard
- then
+ elsif Scope (Reducer_E) = Standard_Standard then
if Accum_Typ = Universal_Integer then
Accum_Typ := Standard_Integer;
elsif Accum_Typ = Universal_Real then
Accum_Typ := Standard_Float;
+ elsif Is_Numeric_Type (Accum_Typ) then
+ Accum_Typ := Base_Type (Accum_Typ);
end if;
- -- Otherwise, the Accum_Subtype is the subtype of the first
- -- formal of the reducer subprogram RM 4.5.10(19/5).
+ -- Otherwise, Accum_Typ is the subtype of the first formal
+ -- of the reducer subprogram (RM 4.5.10(19/5)).
+
+ elsif Ekind (Reducer_E) = E_Operator then
+ Accum_Typ := Etype (Left_Opnd (Reducer_E));
else
Accum_Typ := Etype (First_Formal (Reducer_E));
end if;
+
Set_Etype (N, Accum_Typ);
- -- Accumulation type must be nonlimited, RM 4.5.10(8/5)
+ -- The accumulator type must be nonlimited (RM 4.5.10(8/5))
if Is_Limited_Type (Accum_Typ) then
Error_Msg_N
- ("accumulated subtype of Reduce must be nonlimited", N);
+ ("type of reduction expression must be nonlimited", N);
- -- If the Accum_Typ is an unconstrained array and the reducer
+ -- If Accum_Typ is an unconstrained array and the reducer
-- subprogram is a function then a Constraint_Error will be
- -- raised at runtime as most computations will change its
- -- length type during the reduction execution, RM 4.5.10(25/5).
+ -- raised at run time, as most computations will change its
+ -- length during the reduction execution (RM 4.5.10(25/5)).
-- For instance, this is the case with:
-- [...]'Reduce ("&", ...)
-- When the expression yields non-empty strings, the reduction
@@ -13300,7 +13306,7 @@ package body Sem_Attr is
elsif Nkind (Reducer_E) /= N_Attribute_Reference
and then Ekind (Reducer_E) = E_Function
- and then not Is_Numeric_Type (Base_Type (Accum_Typ))
+ and then not Is_Numeric_Type (Accum_Typ)
and then not Is_Constrained (Accum_Typ)
then
declare
@@ -13318,6 +13324,7 @@ package body Sem_Attr is
-- resolving the initial expression and array aggregate.
Resolve (Init_Value_Expr, Accum_Typ);
+
if Nkind (P) = N_Aggregate then
Resolve_Aggregate (P,
Make_Array_Type (Index => Standard_Positive,
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 58fc1f4..9ede664 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,8 @@
+2025-12-07 David Malcolm <dmalcolm@redhat.com>
+
+ * kf.cc (register_known_functions): Remove duplicate calls to
+ register_atomic_builtins and register_varargs_builtins.
+
2025-11-28 Jakub Jelinek <jakub@redhat.com>
* known-function-manager.cc (known_function_manager::add): Avoid
diff --git a/gcc/analyzer/kf.cc b/gcc/analyzer/kf.cc
index b3c02e8..c9818de 100644
--- a/gcc/analyzer/kf.cc
+++ b/gcc/analyzer/kf.cc
@@ -2334,9 +2334,6 @@ register_known_functions (known_function_manager &kfm,
kfm.add ("__builtin_strlen", std::make_unique<kf_strlen> ());
kfm.add ("strstr", std::make_unique<kf_strstr> ());
kfm.add ("__builtin_strstr", std::make_unique<kf_strstr> ());
-
- register_atomic_builtins (kfm);
- register_varargs_builtins (kfm);
}
/* Known POSIX functions, and some non-standard extensions. */
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index a02fed1..e79f77e 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9774,6 +9774,13 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
unsigned HOST_WIDE_INT width
= tree_to_uhwi (DECL_INITIAL (field));
tree type = TREE_TYPE (field);
+ if (VECTOR_TYPE_P (type))
+ {
+ error_at (DECL_SOURCE_LOCATION (field),
+ "bit-field %qD has invalid type", field);
+ type = TREE_TYPE (type);
+ TREE_TYPE (field) = type;
+ }
if (width != TYPE_PRECISION (type))
{
if (TREE_CODE (type) == BITINT_TYPE
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index d7c9a32..735cfc6 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -3187,7 +3187,7 @@ build_access_with_size_for_counted_by (location_t loc, tree ref,
tree first_param = is_fam
? c_fully_fold (array_to_pointer_conversion (loc, ref),
false, NULL)
- : ref;
+ : c_fully_fold (ref, false, NULL);
tree second_param
= c_fully_fold (counted_by_ref, false, NULL);
tree third_param = build_int_cst (c_build_pointer_type (counted_by_type), 0);
diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 3c21e17..1a7d499 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -1696,8 +1696,12 @@ cgraph_edge::redirect_callee (cgraph_node *n)
old_ref->remove_reference ();
ipa_ref *new_ref = caller->create_reference (n, IPA_REF_ADDR, call_stmt);
new_ref->lto_stmt_uid = lto_stmt_uid;
- if (!old_callee->referred_to_p ())
+ /* If the last reference to OLD_CALLEE has been redirected, unset
+ address_taken. old_ref is only used as a placeholder when looking for
+ a different reference. */
+ if (!old_callee->iterate_referring (0, old_ref))
old_callee->address_taken = 0;
+ n->mark_address_taken ();
}
if (!inline_failed)
diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
index 49f0e58..816fc53 100644
--- a/gcc/cgraphclones.cc
+++ b/gcc/cgraphclones.cc
@@ -176,7 +176,9 @@ set_new_clone_decl_and_node_flags (cgraph_node *new_node)
DECL_IS_REPLACEABLE_OPERATOR (new_node->decl) = 0;
new_node->externally_visible = 0;
- new_node->local = 1;
+ /* Clones of callbacks might have their address taken, and thus cannot be
+ local. */
+ new_node->local = !new_node->address_taken;
new_node->lowered = true;
new_node->semantic_interposition = 0;
}
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index b86d80c..851594a 100644
--- a/gcc/config/aarch64/aarch64-cores.def
+++ b/gcc/config/aarch64/aarch64-cores.def
@@ -229,6 +229,11 @@ AARCH64_CORE("grace", grace, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, SVE2_AES
AARCH64_CORE("neoverse-v3", neoversev3, cortexa57, V9_2A, (SVE2_BITPERM, RNG, LS64, MEMTAG, PROFILE), neoversev3, 0x41, 0xd84, -1)
AARCH64_CORE("neoverse-v3ae", neoversev3ae, cortexa57, V9_2A, (SVE2_BITPERM, RNG, LS64, MEMTAG, PROFILE), neoversev3ae, 0x41, 0xd83, -1)
+AARCH64_CORE("c1-nano", c1nano, cortexa53, V9_3A, (MEMTAG, SVE2_BITPERM, F16FML, SME2, RCPC3), cortexa53, 0x41, 0xd8a, -1)
+AARCH64_CORE("c1-pro", c1pro, cortexa57, V9_3A, (MEMTAG, SVE2_BITPERM, F16FML, PROFILE, SME2, RCPC3), neoversen3, 0x41, 0xd8b, -1)
+AARCH64_CORE("c1-premium", c1premium, cortexa57, V9_3A, (MEMTAG, SVE2_BITPERM, F16FML, PROFILE, SME2, RCPC3), neoversev3, 0x41, 0xd90, -1)
+AARCH64_CORE("c1-ultra", c1ultra, cortexa57, V9_3A, (MEMTAG, SVE2_BITPERM, F16FML, PROFILE, SME2, RCPC3), cortexx925, 0x41, 0xd8c, -1)
+
AARCH64_CORE("demeter", demeter, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1)
/* NVIDIA ('N') cores. */
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 3f9d5f6..c02ffd6 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3544,10 +3544,10 @@
rtx reduc = gen_lowpart (V4SImode, tmp);
rtx res = gen_reg_rtx (V4SImode);
emit_insn (gen_aarch64_uminpv4si (res, reduc, reduc));
- emit_move_insn (tmp, gen_lowpart (<MODE>mode, res));
+ tmp = gen_lowpart (<MODE>mode, res);
}
- rtx val = gen_reg_rtx (DImode);
- emit_move_insn (val, gen_lowpart (DImode, tmp));
+
+ rtx val = force_lowpart_subreg (DImode, tmp, <MODE>mode);
rtx cc_reg = aarch64_gen_compare_reg (EQ, val, constm1_rtx);
rtx cmp = gen_rtx_fmt_ee (EQ, SImode, cc_reg, constm1_rtx);
rtx tmp2 = gen_reg_rtx (SImode);
@@ -3607,10 +3607,10 @@
rtx reduc = gen_lowpart (V4SImode, tmp);
rtx res = gen_reg_rtx (V4SImode);
emit_insn (gen_aarch64_umaxpv4si (res, reduc, reduc));
- emit_move_insn (tmp, gen_lowpart (<MODE>mode, res));
+ tmp = gen_lowpart (<MODE>mode, res);
}
- rtx val = gen_reg_rtx (DImode);
- emit_move_insn (val, gen_lowpart (DImode, tmp));
+
+ rtx val = force_lowpart_subreg (DImode, tmp, <MODE>mode);
rtx cc_reg = aarch64_gen_compare_reg (NE, val, const0_rtx);
rtx cmp = gen_rtx_fmt_ee (NE, SImode, cc_reg, const0_rtx);
rtx tmp2 = gen_reg_rtx (SImode);
diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
index 292796c..d6f1bbc 100644
--- a/gcc/config/aarch64/aarch64-tune.md
+++ b/gcc/config/aarch64/aarch64-tune.md
@@ -1,5 +1,5 @@
;; -*- buffer-read-only: t -*-
;; Generated automatically by gentune.sh from aarch64-cores.def
(define_attr "tune"
- "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88,thunderxt88p1,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,ampere1b,ampere1c,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,fujitsu_monaka,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,oryon1,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexr82ae,applea12,applem1_0,applem1_1,applem1_2,applem1_3,applem2_0,applem2_1,applem2_2,applem2_3,applem3_0,applem3_1,applem3_2,applem4_0,applem4_1,applem4_2,cortexa510,cortexa520,cortexa520ae,cortexa710,cortexa715,cortexa720,cortexa720ae,cortexa725,cortexx2,cortexx3,cortexx4,cortexx925,neoversen2,cobalt100,neoversen3,neoversev2,grace,neoversev3,neoversev3ae,demeter,olympus,gb10,generic,generic_armv8_a,generic_armv9_a"
+ "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88,thunderxt88p1,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,ampere1b,ampere1c,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,fujitsu_monaka,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,oryon1,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexr82ae,applea12,applem1_0,applem1_1,applem1_2,applem1_3,applem2_0,applem2_1,applem2_2,applem2_3,applem3_0,applem3_1,applem3_2,applem4_0,applem4_1,applem4_2,cortexa510,cortexa520,cortexa520ae,cortexa710,cortexa715,cortexa720,cortexa720ae,cortexa725,cortexx2,cortexx3,cortexx4,cortexx925,neoversen2,cobalt100,neoversen3,neoversev2,grace,neoversev3,neoversev3ae,c1nano,c1pro,c1premium,c1ultra,demeter,olympus,gb10,generic,generic_armv8_a,generic_armv9_a"
(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index a729ea4..54abf8c 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -2940,14 +2940,17 @@ gcn_init_cumulative_args (CUMULATIVE_ARGS *cum /* Argument info to init */ ,
if (!caller && cfun->machine->normal_function)
gcn_detect_incoming_pointer_arg (fndecl);
- if ((omp_requires_mask & (OMP_REQUIRES_UNIFIED_SHARED_MEMORY
- | OMP_REQUIRES_SELF_MAPS))
+ static bool warned_xnack = 0;
+ if (!warned_xnack
+ && (omp_requires_mask & (OMP_REQUIRES_UNIFIED_SHARED_MEMORY
+ | OMP_REQUIRES_SELF_MAPS))
&& gcn_devices[gcn_arch].xnack_default != HSACO_ATTR_UNSUPPORTED
&& flag_xnack == HSACO_ATTR_OFF)
{
warning_at (UNKNOWN_LOCATION, 0,
- "Unified Shared Memory is enabled, but XNACK is disabled");
+ "Unified Shared Memory is required, but XNACK is disabled");
inform (UNKNOWN_LOCATION, "Try -foffload-options=-mxnack=any");
+ warned_xnack = 1;
}
reinit_regs ();
diff --git a/gcc/config/gcn/mkoffload.cc b/gcc/config/gcn/mkoffload.cc
index d9d89c6..ac6aae5 100644
--- a/gcc/config/gcn/mkoffload.cc
+++ b/gcc/config/gcn/mkoffload.cc
@@ -627,9 +627,12 @@ process_asm (FILE *in, FILE *out, FILE *cfile, uint32_t omp_requires)
|| TEST_XNACK_ON (elf_flags)
|| xnack_required);
if (TEST_XNACK_OFF (elf_flags) && xnack_required)
- fatal_error (input_location,
- "conflicting settings; XNACK is forced off but Unified "
- "Shared Memory is on");
+ {
+ warning (input_location,
+ "conflicting settings; XNACK is forced off but Unified "
+ "Shared Memory is required");
+ xnack_required = 0;
+ }
/* Start generating the C code. */
if (gcn_stack_size)
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index fd9bcaa..438fa4e 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -4159,12 +4159,18 @@ static bool
ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
rtx cmp_op1, rtx if_true, rtx if_false)
{
- machine_mode mode;
+ machine_mode mode = GET_MODE (dest);
bool is_min;
rtx tmp;
if (code == LT)
;
+ else if (code == LE && !HONOR_NANS (mode))
+ {
+ /* We can swap LE to GE and then invert to LT. */
+ std::swap (cmp_op0, cmp_op1);
+ std::swap (if_true, if_false);
+ }
else if (code == UNGE)
std::swap (if_true, if_false);
else
@@ -4177,7 +4183,6 @@ ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
else
return false;
- mode = GET_MODE (dest);
if (immediate_operand (if_false, mode))
if_false = force_reg (mode, if_false);
if (immediate_operand (if_true, mode))
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index db43045..75a9cb6 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -26397,7 +26397,20 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
(TREE_OPERAND (gimple_assign_rhs1 (def), 0))))))
{
if (fp)
- m_num_sse_needed[where]++;
+ {
+ /* Scalar FP values residing in x87 registers need to be
+ spilled and reloaded. */
+ auto mode2 = TYPE_MODE (TREE_TYPE (op));
+ if (IS_STACK_MODE (mode2))
+ {
+ int cost
+ = (ix86_cost->hard_register.fp_store[mode2 == SFmode
+ ? 0 : 1]
+ + ix86_cost->sse_load[sse_store_index (mode2)]);
+ stmt_cost += COSTS_N_INSNS (cost) / 2;
+ }
+ m_num_sse_needed[where]++;
+ }
else
{
m_num_gpr_needed[where]++;
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 0be898c..fb79b2e 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -4900,7 +4900,8 @@
(match_operand:SI 3 "<cmp_imm_predicate>")]
UNSPEC_PCMP_ITER))]
"TARGET_AVX512F && ix86_pre_reload_split ()
- && rtx_equal_p (operands[1], operands[2])"
+ && rtx_equal_p (operands[1], operands[2])
+ && (!MEM_P (operands[1]) || !MEM_VOLATILE_P (operands[1]))"
"#"
"&& 1"
[(set (match_dup 0) (match_dup 4))]
diff --git a/gcc/config/mingw/winnt.cc b/gcc/config/mingw/winnt.cc
index b51fd8e..fe2fb4c 100644
--- a/gcc/config/mingw/winnt.cc
+++ b/gcc/config/mingw/winnt.cc
@@ -446,8 +446,11 @@ mingw_pe_unique_section (tree decl, int reloc)
prefix = ".text$";
else if (decl_readonly_section (decl, reloc))
prefix = ".rdata$";
+ /* Note that we need two dollar signs for TLS sections
+ because they need to be ASCII-sorted before .tls$ZZZ
+ to be properly laid out by the GNU linker. */
else if (DECL_THREAD_LOCAL_P (decl))
- prefix = ".tls$";
+ prefix = ".tls$$";
else
prefix = ".data$";
len = strlen (name) + strlen (prefix);
@@ -522,9 +525,6 @@ mingw_pe_asm_named_section (const char *name, unsigned int flags,
*f++ = 'e';
#endif
- if (strcmp (name, ".tls$") == 0)
- *f++ = 'd';
-
if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
/* readonly data */
{
@@ -533,6 +533,8 @@ mingw_pe_asm_named_section (const char *name, unsigned int flags,
}
else
{
+ if (startswith (name, ".tls$"))
+ *f++ = 'd';
if (flags & SECTION_CODE)
*f++ = 'x';
if (flags & SECTION_WRITE)
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index cec0113..c694684 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -2302,6 +2302,37 @@
})
;; -------------------------------------------------------------------------
+;; ---- [INT] Mask reductions
+;; -------------------------------------------------------------------------
+
+(define_expand "reduc_sbool_and_scal_<mode>"
+ [(match_operand:QI 0 "register_operand")
+ (match_operand:VB_VLS 1 "register_operand")]
+ "TARGET_VECTOR"
+{
+ riscv_vector::expand_mask_reduction (operands, AND);
+ DONE;
+})
+
+(define_expand "reduc_sbool_ior_scal_<mode>"
+ [(match_operand:QI 0 "register_operand")
+ (match_operand:VB_VLS 1 "register_operand")]
+ "TARGET_VECTOR"
+{
+ riscv_vector::expand_mask_reduction (operands, IOR);
+ DONE;
+})
+
+(define_expand "reduc_sbool_xor_scal_<mode>"
+ [(match_operand:QI 0 "register_operand")
+ (match_operand:VB_VLS 1 "register_operand")]
+ "TARGET_VECTOR"
+{
+ riscv_vector::expand_mask_reduction (operands, XOR);
+ DONE;
+})
+
+;; -------------------------------------------------------------------------
;; ---- [FP] Tree reductions
;; -------------------------------------------------------------------------
;; Includes:
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 3cc954e..5b44165 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -612,7 +612,7 @@
(match_code "eq,ne,le,leu,gt,gtu,lt,ltu"))
(define_predicate "comparison_swappable_operator"
- (match_code "gtu"))
+ (match_code "gtu,gt"))
(define_predicate "ge_operator"
(match_code "ge,geu"))
diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index 4fc0528..24537d5 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -213,6 +213,49 @@ riscv_pragma_intrinsic (cpp_reader *)
error ("unknown %<#pragma riscv intrinsic%> option %qs", name);
}
+/* Implement TARGETM.TARGET_OPTION.PRAGMA_PARSE. */
+
+static bool
+riscv_pragma_target_parse (tree args, tree pop_target)
+{
+ /* If args is not NULL then process it and setup the target-specific
+ information that it specifies. */
+ if (args)
+ {
+ if (!riscv_process_target_attr_for_pragma (args))
+ return false;
+
+ riscv_override_options_internal (&global_options);
+ }
+ /* args is NULL, restore to the state described in pop_target. */
+ else
+ {
+ pop_target = pop_target ? pop_target : target_option_default_node;
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (pop_target));
+ }
+
+ target_option_current_node
+ = build_target_option_node (&global_options, &global_options_set);
+
+ riscv_reset_previous_fndecl ();
+
+ /* For the definitions, ensure all newly defined macros are considered
+ as used for -Wunused-macros. There is no point warning about the
+ compiler predefined macros. */
+ cpp_options *cpp_opts = cpp_get_options (parse_in);
+ unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
+ cpp_opts->warn_unused_macros = 0;
+
+ cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
+ riscv_cpu_cpp_builtins (parse_in);
+ cpp_stop_forcing_token_locations (parse_in);
+
+ cpp_opts->warn_unused_macros = saved_warn_unused_macros;
+
+ return true;
+}
+
/* Implement TARGET_CHECK_BUILTIN_CALL. */
static bool
riscv_check_builtin_call (location_t loc, vec<location_t> arg_loc, tree fndecl,
@@ -272,5 +315,6 @@ riscv_register_pragmas (void)
{
targetm.resolve_overloaded_builtin = riscv_resolve_overloaded_builtin;
targetm.check_builtin_call = riscv_check_builtin_call;
+ targetm.target_option.pragma_parse = riscv_pragma_target_parse;
c_register_pragma ("riscv", "intrinsic", riscv_pragma_intrinsic);
}
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 261c25c..abf9df7 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -664,6 +664,7 @@ bool expand_vec_cmp_float (rtx, rtx_code, rtx, rtx, bool);
void expand_cond_len_unop (unsigned, rtx *);
void expand_cond_len_binop (unsigned, rtx *);
void expand_reduction (unsigned, unsigned, unsigned, rtx *, rtx);
+void expand_mask_reduction (rtx *, rtx_code);
void expand_vec_ceil (rtx, rtx, machine_mode, machine_mode);
void expand_vec_floor (rtx, rtx, machine_mode, machine_mode);
void expand_vec_nearbyint (rtx, rtx, machine_mode, machine_mode);
@@ -848,12 +849,15 @@ riscv_option_valid_attribute_p (tree, tree, tree, int);
extern bool
riscv_option_valid_version_attribute_p (tree, tree, tree, int);
extern bool
+riscv_process_target_attr_for_pragma (tree);
+extern bool
riscv_process_target_version_attr (tree, location_t *);
extern bool
riscv_process_target_version_str (string_slice, location_t *);
extern void
riscv_override_options_internal (struct gcc_options *);
extern void riscv_option_override (void);
+extern void riscv_reset_previous_fndecl (void);
extern rtx riscv_prefetch_cookie (rtx, rtx);
extern bool riscv_prefetch_offset_address_p (rtx, machine_mode);
diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc
index 94f0a29..eb3e688 100644
--- a/gcc/config/riscv/riscv-target-attr.cc
+++ b/gcc/config/riscv/riscv-target-attr.cc
@@ -44,6 +44,7 @@ public:
, m_cpu_info (nullptr)
, m_tune (nullptr)
, m_priority (0)
+ , m_max_vect (false)
{
}
@@ -51,6 +52,7 @@ public:
bool handle_cpu (const char *);
bool handle_tune (const char *);
bool handle_priority (const char *);
+ bool handle_max_vect (const char *);
void update_settings (struct gcc_options *opts) const;
private:
@@ -66,31 +68,35 @@ private:
const riscv_cpu_info *m_cpu_info;
const char *m_tune;
int m_priority;
+ bool m_max_vect;
};
}
/* All the information needed to handle a target attribute.
NAME is the name of the attribute.
- HANDLER is the function that takes the attribute string as an argument. */
+ HANDLER is the function that takes the attribute string as an argument.
+ REQUIRES_ARG indicates whether this attribute requires an argument value. */
struct riscv_attribute_info
{
const char *name;
bool (riscv_target_attr_parser::*handler) (const char *);
+ bool requires_arg;
};
/* The target attributes that we support. */
static const struct riscv_attribute_info riscv_target_attrs[]
- = {{"arch", &riscv_target_attr_parser::handle_arch},
- {"cpu", &riscv_target_attr_parser::handle_cpu},
- {"tune", &riscv_target_attr_parser::handle_tune},
- {NULL, NULL}};
+ = {{"arch", &riscv_target_attr_parser::handle_arch, true},
+ {"cpu", &riscv_target_attr_parser::handle_cpu, true},
+ {"tune", &riscv_target_attr_parser::handle_tune, true},
+ {"max-vectorization", &riscv_target_attr_parser::handle_max_vect, false},
+ {NULL, NULL, false}};
static const struct riscv_attribute_info riscv_target_version_attrs[]
- = {{"arch", &riscv_target_attr_parser::handle_arch},
- {"priority", &riscv_target_attr_parser::handle_priority},
- {NULL, NULL}};
+ = {{"arch", &riscv_target_attr_parser::handle_arch, true},
+ {"priority", &riscv_target_attr_parser::handle_priority, true},
+ {NULL, NULL, false}};
bool
riscv_target_attr_parser::parse_arch (const char *str)
@@ -254,6 +260,17 @@ riscv_target_attr_parser::handle_priority (const char *str)
return true;
}
+/* Handle max-vectorization. There are no further options, just
+ enable it. */
+
+bool
+riscv_target_attr_parser::handle_max_vect (const char *str ATTRIBUTE_UNUSED)
+{
+ m_max_vect = true;
+
+ return true;
+}
+
void
riscv_target_attr_parser::update_settings (struct gcc_options *opts) const
{
@@ -279,6 +296,9 @@ riscv_target_attr_parser::update_settings (struct gcc_options *opts) const
if (m_priority)
opts->x_riscv_fmv_priority = m_priority;
+
+ if (m_max_vect)
+ opts->x_riscv_max_vectorization = true;
}
/* Parse ARG_STR which contains the definition of one target attribute.
@@ -303,33 +323,50 @@ riscv_process_one_target_attr (char *arg_str,
char *str_to_check = buf.get();
strcpy (str_to_check, arg_str);
+ /* Split attribute name from argument (if present). */
char *arg = strchr (str_to_check, '=');
-
- if (!arg)
+ if (arg)
{
- if (loc)
- error_at (*loc, "attribute %<target(\"%s\")%> does not "
- "accept an argument", str_to_check);
- return false;
+ *arg = '\0';
+ ++arg;
+ /* Check for empty argument after '='. */
+ if (*arg == '\0')
+ {
+ if (loc)
+ error_at (*loc, "attribute %<target(\"%s\")%> has empty argument",
+ str_to_check);
+ return false;
+ }
}
- arg[0] = '\0';
- ++arg;
- for (const auto *attr = attrs;
- attr->name;
- ++attr)
+ /* Find matching attribute. */
+ for (const auto *attr = attrs; attr->name; ++attr)
{
- /* If the names don't match up, or the user has given an argument
- to an attribute that doesn't accept one, or didn't give an argument
- to an attribute that expects one, fail to match. */
- if (strncmp (str_to_check, attr->name, strlen (attr->name)) != 0)
+ if (strcmp (str_to_check, attr->name) != 0)
continue;
+ /* Validate argument presence matches expectations. */
+ if (attr->requires_arg && !arg)
+ {
+ if (loc)
+ error_at (*loc, "attribute %<target(\"%s\")%> expects "
+ "an argument", str_to_check);
+ return false;
+ }
+
+ if (!attr->requires_arg && arg)
+ {
+ if (loc)
+ error_at (*loc, "attribute %<target(\"%s\")%> does not "
+ "accept an argument", str_to_check);
+ return false;
+ }
+
return (&attr_parser->*attr->handler) (arg);
}
if (loc)
- error_at (*loc, "Got unknown attribute %<target(\"%s\")%>", str_to_check);
+ error_at (*loc, "unknown attribute %<target(\"%s\")%>", str_to_check);
return false;
}
@@ -489,6 +526,17 @@ riscv_option_valid_attribute_p (tree fndecl, tree, tree args, int)
return ret;
}
+/* Public wrapper for pragma processing.
+ Parse ARGS (a TREE_LIST of target attributes) and update global_options.
+ This is used by #pragma GCC target. */
+
+bool
+riscv_process_target_attr_for_pragma (tree args)
+{
+ location_t loc = UNKNOWN_LOCATION;
+ return riscv_process_target_attr (args, &loc, riscv_target_attrs);
+}
+
/* Parse the tree in ARGS that contains the target_version attribute
information and update the global target options space. If LOC is nonnull,
report diagnostics against *LOC, otherwise remain silent. */
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index c0f0b99..f3c4431 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -4885,6 +4885,54 @@ expand_reduction (unsigned unspec, unsigned unspec_for_vl0_safe,
emit_insn (gen_pred_extract_first (m1_mode, scalar_dest, m1_tmp2));
}
+/* Expand mask reductions. OPS are {dest, src} where DEST's mode
+ is QImode and SRC's mode is a mask mode.
+ CODE is one of AND, IOR, XOR. */
+
+void
+expand_mask_reduction (rtx *ops, rtx_code code)
+{
+ machine_mode mode = GET_MODE (ops[1]);
+ rtx dest = ops[0];
+ gcc_assert (GET_MODE (dest) == QImode);
+
+ rtx tmp = gen_reg_rtx (Xmode);
+ rtx cpop_ops[] = {tmp, ops[1]};
+ emit_vlmax_insn (code_for_pred_popcount (mode, Xmode), CPOP_OP, cpop_ops);
+
+ bool eq_zero = false;
+
+ /* AND reduction is popcount (mask) == len,
+ IOR reduction is popcount (mask) != 0,
+ XOR reduction is popcount (mask) & 1 != 0. */
+ if (code == AND)
+ {
+ rtx len = gen_int_mode (GET_MODE_NUNITS (mode), HImode);
+ tmp = expand_binop (Xmode, sub_optab, tmp, len, NULL, true,
+ OPTAB_DIRECT);
+ eq_zero = true;
+ }
+ else if (code == IOR)
+ ;
+ else if (code == XOR)
+ tmp = expand_binop (Xmode, and_optab, tmp, GEN_INT (1), NULL, true,
+ OPTAB_DIRECT);
+ else
+ gcc_unreachable ();
+
+ rtx els = gen_label_rtx ();
+ rtx end = gen_label_rtx ();
+
+ riscv_expand_conditional_branch (els, eq_zero ? EQ : NE, tmp, const0_rtx);
+ emit_move_insn (dest, const0_rtx);
+ emit_jump_insn (gen_jump (end));
+ emit_barrier ();
+
+ emit_label (els);
+ emit_move_insn (dest, const1_rtx);
+ emit_label (end);
+}
+
/* Prepare ops for ternary operations.
It can be called before or after RA. */
void
@@ -5869,6 +5917,8 @@ get_swapped_cmp_rtx_code (rtx_code code)
{
case GTU:
return LTU;
+ case GT:
+ return LT;
default:
gcc_unreachable ();
}
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 7b6a29d..96519c9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -12225,6 +12225,12 @@ riscv_override_options_internal (struct gcc_options *opts)
/* Convert -march and -mrvv-vector-bits to a chunks count. */
riscv_vector_chunks = riscv_convert_vector_chunks (opts);
+ /* Set scalar costing to a high value such that we always pick
+ vectorization. Increase scalar costing by 100x. */
+ if (opts->x_riscv_max_vectorization)
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_vect_scalar_cost_multiplier, 10000);
+
if (opts->x_flag_cf_protection != CF_NONE)
{
if ((opts->x_flag_cf_protection & CF_RETURN) == CF_RETURN
@@ -12462,6 +12468,39 @@ riscv_option_restore (struct gcc_options *opts,
static GTY (()) tree riscv_previous_fndecl;
+/* Reset the previous function declaration. */
+
+void
+riscv_reset_previous_fndecl (void)
+{
+ riscv_previous_fndecl = NULL;
+}
+
+/* Implement TARGET_OPTION_SAVE. */
+
+static void
+riscv_option_save (struct cl_target_option *ptr,
+ struct gcc_options *opts,
+ struct gcc_options * /* opts_set */)
+{
+ ptr->x_riscv_arch_string = opts->x_riscv_arch_string;
+ ptr->x_riscv_tune_string = opts->x_riscv_tune_string;
+ ptr->x_riscv_cpu_string = opts->x_riscv_cpu_string;
+}
+
+/* Implement TARGET_OPTION_PRINT. */
+
+static void
+riscv_option_print (FILE *file, int indent, struct cl_target_option *ptr)
+{
+ fprintf (file, "%*sarch = %s\n", indent, "",
+ ptr->x_riscv_arch_string ? ptr->x_riscv_arch_string : "default");
+ fprintf (file, "%*stune = %s\n", indent, "",
+ ptr->x_riscv_tune_string ? ptr->x_riscv_tune_string : "default");
+ if (ptr->x_riscv_cpu_string)
+ fprintf (file, "%*scpu = %s\n", indent, "", ptr->x_riscv_cpu_string);
+}
+
/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
static void
@@ -12798,7 +12837,7 @@ riscv_get_interrupt_type (tree decl)
/* Implement `TARGET_SET_CURRENT_FUNCTION'. Unpack the codegen decisions
like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET
of the function, if such exists. This function may be called multiple
- times on a single function so use aarch64_previous_fndecl to avoid
+ times on a single function so use riscv_previous_fndecl to avoid
setting up identical state. */
/* Sanity checking for above function attributes. */
@@ -16309,9 +16348,15 @@ riscv_prefetch_offset_address_p (rtx x, machine_mode mode)
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE riscv_option_override
+#undef TARGET_OPTION_SAVE
+#define TARGET_OPTION_SAVE riscv_option_save
+
#undef TARGET_OPTION_RESTORE
#define TARGET_OPTION_RESTORE riscv_option_restore
+#undef TARGET_OPTION_PRINT
+#define TARGET_OPTION_PRINT riscv_option_print
+
#undef TARGET_OPTION_VALID_ATTRIBUTE_P
#define TARGET_OPTION_VALID_ATTRIBUTE_P riscv_option_valid_attribute_p
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index b334e6c..452062c 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -341,6 +341,10 @@ Target Undocumented RejectNegative Joined Enum(vsetvl_strategy) Var(vsetvl_strat
Target Undocumented Uinteger Var(riscv_two_source_permutes) Init(0)
-param=riscv-two-source-permutes Enable permutes with two source vectors.
+mmax-vectorization
+Target Var(riscv_max_vectorization) Save
+Override the scalar cost model such that vectorization is always profitable.
+
Enum
Name(stringop_strategy) Type(enum stringop_strategy_enum)
Valid arguments to -mstringop-strategy=:
diff --git a/gcc/config/riscv/riscv.opt.urls b/gcc/config/riscv/riscv.opt.urls
index fe88ec8..bfb1a2d 100644
--- a/gcc/config/riscv/riscv.opt.urls
+++ b/gcc/config/riscv/riscv.opt.urls
@@ -96,6 +96,8 @@ UrlSuffix(gcc/RISC-V-Options.html#index-minline-strncmp)
minline-strlen
UrlSuffix(gcc/RISC-V-Options.html#index-minline-strlen)
+; skipping UrlSuffix for 'mmax-vectorization' due to finding no URLs
+
; skipping UrlSuffix for 'mtls-dialect=' due to finding no URLs
mfence-tso
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index c4f60bf..ba4a43b 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -4199,6 +4199,7 @@
"TARGET_VECTOR"
"vw<plus_minus:insn><any_extend:u>.wx\t%0,%3,%z4%p1"
[(set_attr "type" "vi<widen_binop_insn_type>")
+ (set_attr "mode_idx" "3")
(set_attr "mode" "<V_DOUBLE_TRUNC>")])
(define_insn "@pred_single_widen_add<any_extend:su><mode>_extended_scalar"
@@ -4465,6 +4466,7 @@
"TARGET_VECTOR"
"v<insn>.vx\t%0,%3,%4%p1"
[(set_attr "type" "<int_binop_insn_type>")
+ (set_attr "mode_idx" "3")
(set_attr "mode" "<MODE>")])
(define_insn "@pred_<optab><mode>_scalar"
@@ -4486,6 +4488,7 @@
"TARGET_VECTOR"
"v<insn>.vx\t%0,%3,%4%p1"
[(set_attr "type" "<int_binop_insn_type>")
+ (set_attr "mode_idx" "3")
(set_attr "mode" "<MODE>")])
(define_expand "@pred_<optab><mode>_scalar"
@@ -4540,6 +4543,7 @@
"TARGET_VECTOR"
"v<insn>.vx\t%0,%3,%4%p1"
[(set_attr "type" "<int_binop_insn_type>")
+ (set_attr "mode_idx" "3")
(set_attr "mode" "<MODE>")])
(define_insn "*pred_<optab><mode>_extended_scalar"
@@ -4562,6 +4566,7 @@
"TARGET_VECTOR && !TARGET_64BIT"
"v<insn>.vx\t%0,%3,%4%p1"
[(set_attr "type" "<int_binop_insn_type>")
+ (set_attr "mode_idx" "3")
(set_attr "mode" "<MODE>")])
(define_expand "@pred_<optab><mode>_scalar"
@@ -4616,6 +4621,7 @@
"TARGET_VECTOR"
"v<insn>.vx\t%0,%3,%z4%p1"
[(set_attr "type" "<int_binop_insn_type>")
+ (set_attr "mode_idx" "3")
(set_attr "mode" "<MODE>")])
(define_insn "*pred_<optab><mode>_extended_scalar"
@@ -4638,6 +4644,7 @@
"TARGET_VECTOR && !TARGET_64BIT"
"v<insn>.vx\t%0,%3,%z4%p1"
[(set_attr "type" "<int_binop_insn_type>")
+ (set_attr "mode_idx" "3")
(set_attr "mode" "<MODE>")])
(define_insn "@pred_<sat_op><mode>"
@@ -4683,6 +4690,7 @@
"TARGET_VECTOR"
"v<sat_op>.vx\t%0,%3,%z4%p1"
[(set_attr "type" "<sat_insn_type>")
+ (set_attr "mode_idx" "3")
(set_attr "mode" "<MODE>")])
(define_insn "@pred_<sat_op><mode>_scalar"
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 647e89a..5133dac 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -2166,3 +2166,8 @@
(and (match_code "subreg")
(match_test "subreg_lowpart_offset (mode, GET_MODE (SUBREG_REG (op)))
== SUBREG_BYTE (op)")))
+
+; Else operand for LEN_LOAD.
+(define_predicate "lxvl_else_operand"
+ (and (match_code "const_vector")
+ (match_test "op == CONST0_RTX (GET_MODE (op))")))
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index dd3573b..4d47833 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -5798,13 +5798,14 @@
(define_expand "len_load_v16qi"
[(match_operand:V16QI 0 "vlogical_operand")
(match_operand:V16QI 1 "memory_operand")
- (match_operand:QI 2 "gpc_reg_operand")
- (match_operand:QI 3 "zero_constant")]
+ (match_operand:V16QI 2 "lxvl_else_operand")
+ (match_operand:QI 3 "gpc_reg_operand")
+ (match_operand:QI 4 "zero_constant")]
"TARGET_P9_VECTOR && TARGET_64BIT"
{
rtx mem = XEXP (operands[1], 0);
mem = force_reg (DImode, mem);
- rtx len = gen_lowpart (DImode, operands[2]);
+ rtx len = gen_lowpart (DImode, operands[3]);
emit_insn (gen_lxvl (operands[0], mem, len));
DONE;
})
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index c7b93bd..e181399 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -614,3 +614,8 @@
(define_predicate "vll_bias_operand"
(and (match_code "const_int")
(match_test "op == CONSTM1_RTX (QImode)")))
+
+; Else operand for LEN_LOAD.
+(define_predicate "vll_else_operand"
+ (and (match_code "const_vector")
+ (match_test "op == CONST0_RTX (GET_MODE (op))")))
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 375e3e8..367389c 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -3557,15 +3557,16 @@
(define_expand "len_load_v16qi"
[(match_operand:V16QI 0 "register_operand")
(match_operand:V16QI 1 "memory_operand")
- (match_operand:QI 2 "register_operand")
- (match_operand:QI 3 "vll_bias_operand")
+ (match_operand:V16QI 2 "vll_else_operand")
+ (match_operand:QI 3 "register_operand")
+ (match_operand:QI 4 "vll_bias_operand")
]
"TARGET_VX && TARGET_64BIT"
{
rtx mem = adjust_address (operands[1], BLKmode, 0);
rtx len = gen_reg_rtx (SImode);
- emit_move_insn (len, gen_rtx_ZERO_EXTEND (SImode, operands[2]));
+ emit_move_insn (len, gen_rtx_ZERO_EXTEND (SImode, operands[3]));
emit_insn (gen_vllv16qi (operands[0], len, mem));
DONE;
})
diff --git a/gcc/configure b/gcc/configure
index d707435..f349c1d 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -635,7 +635,6 @@ LIBOBJS
CET_HOST_FLAGS
LD_PICFLAG
PICFLAG
-enable_default_pie
libgccjit_version
enable_host_bind_now
LIBGDIAGNOSTICS
@@ -21877,7 +21876,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21880 "configure"
+#line 21879 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -21983,7 +21982,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21986 "configure"
+#line 21985 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -34939,7 +34938,6 @@ $as_echo "#define ENABLE_DEFAULT_PIE 1" >>confdefs.h
fi
-
# Check if -fno-PIE works.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fno-PIE option" >&5
$as_echo_n "checking for -fno-PIE option... " >&6; }
diff --git a/gcc/configure.ac b/gcc/configure.ac
index b6d9608..c652257 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -7765,7 +7765,6 @@ if test x$enable_default_pie = xyes ; then
AC_DEFINE(ENABLE_DEFAULT_PIE, 1,
[Define if your target supports default PIE and it is enabled.])
fi
-AC_SUBST([enable_default_pie])
# Check if -fno-PIE works.
AC_CACHE_CHECK([for -fno-PIE option],
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3ad8d16..b4c2b70 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2025-12-08 Egas Ribeiro <egas.g.ribeiro@tecnico.ulisboa.pt>
+
+ * pt.cc (tsubst_expr): Add TARGET_EXPR case with explanatory
+ comment and gcc_unreachable.
+
+2025-12-08 Egas Ribeiro <egas.g.ribeiro@tecnico.ulisboa.pt>
+
+ PR c++/119343
+ * pt.cc (resolve_nondeduced_context): Remove mark_used call.
+
2025-12-06 Jakub Jelinek <jakub@redhat.com>
* decl2.cc (is_late_template_attribute): Call lookup_attribute_spec
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8498730..ce30b52 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -22562,6 +22562,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
in response to the saved STMT_IS_FULL_EXPR_P setting. */
gcc_unreachable ();
+ case TARGET_EXPR:
+ /* TARGET_EXPR represents temporary objects and should not appear in
+ templated trees. */
+ gcc_unreachable ();
+
case OFFSET_REF:
{
/* We should only get here for an OFFSET_REF like A::m; a .* in a
@@ -24816,8 +24821,6 @@ resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain)
}
if (good == 1)
{
- if (!mark_used (goodfn, complain) && !(complain & tf_error))
- return error_mark_node;
expr = goodfn;
if (baselink)
expr = build_baselink (BASELINK_BINFO (baselink),
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 11f6b02..5f36510 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -6007,6 +6007,16 @@ Specifies the core for which to tune the performance of this function and also
whose architectural features to use. The behavior and valid arguments are the
same as for the @option{-mcpu=} command-line option.
+@cindex @code{max-vectorization} function attribute, RISC-V
+@item max-vectorization
+@itemx no-max-vectorization
+@code{max-vectorization} tells GCC's vectorizer to treat all vector
+loops as being more profitable than the original scalar loops when
+optimizing the current function. @code{no-max-vectorization} disables
+this behavior.
+This corresponds to the behavior of the command-line options
+@option{-mmax-vectorization} and @option{-mno-max-vectorization}.
+
@end table
The above target attributes can be specified as follows:
@@ -10722,7 +10732,7 @@ for more information about the @code{target} attribute and the attribute
syntax.
The @code{#pragma GCC target} pragma is presently implemented for
-x86, ARM, AArch64, PowerPC, and S/390 targets only.
+x86, ARM, AArch64, PowerPC, RISC-V, and S/390 targets only.
@cindex pragma GCC optimize
@item #pragma GCC optimize (@var{string}, @dots{})
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ac36fda..813403a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -22761,7 +22761,8 @@ performance of the code. Permissible values for this option are:
@samp{cortex-a520}, @samp{cortex-a520ae}, @samp{cortex-a710}, @samp{cortex-a715},
@samp{cortex-a720}, @samp{cortex-a720ae}, @samp{ampere1}, @samp{ampere1a},
@samp{ampere1b}, @samp{ampere1c}, @samp{cobalt-100}, @samp{apple-m1},
-@samp{apple-m2}, @samp{apple-m3}, @samp{apple-m4} and @samp{native}.
+@samp{apple-m2}, @samp{apple-m3}, @samp{apple-m4}, @samp{c1-nano},
+@samp{c1-pro}, @samp{c1-premium} @samp{c1-ultra} and @samp{native}.
The values @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53},
@samp{cortex-a73.cortex-a35}, @samp{cortex-a73.cortex-a53},
@@ -32162,6 +32163,12 @@ Do not or do generate unaligned vector memory accesses. The default is set
to off unless the processor we are optimizing for explicitly supports
element-misaligned vector memory access.
+@item -mmax-vectorization
+@itemx -mno-max-vectorization
+Enable or disable an override to vectorizer cost model making vectorization
+always appear profitable. Unlike @option{-fno-vect-cost-model} or
+@option{-fvect-cost-model=unlimited} this option does not turn off cost
+comparison between different vector modes.
@opindex mcmodel=
@opindex mcmodel=medlow
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 7bf2cc0..86ed4ff 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -5408,18 +5408,20 @@ This pattern is not allowed to @code{FAIL}.
@cindex @code{len_load_@var{m}} instruction pattern
@item @samp{len_load_@var{m}}
-Load (operand 2 + operand 3) elements from memory operand 1
-into vector register operand 0, setting the other elements of
-operand 0 to undefined values. Operands 0 and 1 have mode @var{m},
-which must be a vector mode. Operand 2 has whichever integer mode the
-target prefers. Operand 3 conceptually has mode @code{QI}.
-
-Operand 2 can be a variable or a constant amount. Operand 3 specifies a
+Load (operand 3 + operand 4) elements from memory operand 1
+into vector register operand 0. Operands 0 and 1 have mode @var{m},
+which must be a vector mode. Operand 3 has whichever integer mode the
+target prefers. Operand 2 (the “else value”) is of mode @var{m} and
+specifies which value is loaded for the remaining elements. The predicate
+of operand 2 must only accept the else values that the target actually
+supports. Operand 4 conceptually has mode @code{QI}.
+
+Operand 3 can be a variable or a constant amount. Operand 4 specifies a
constant bias: it is either a constant 0 or a constant -1. The predicate on
-operand 3 must only accept the bias values that the target actually supports.
+operand 4 must only accept the bias values that the target actually supports.
GCC handles a bias of 0 more efficiently than a bias of -1.
-If (operand 2 + operand 3) exceeds the number of elements in mode
+If (operand 3 + operand 4) exceeds the number of elements in mode
@var{m}, the behavior is undefined.
If the target prefers the length to be measured in bytes rather than
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 724da5b..4fd2183 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,12 @@
+2025-12-08 Harald Anlauf <anlauf@gmx.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/123025
+ * decl.cc (match_char_length): Add a check for the
+ obsolete '*' style of character declarations in the
+ alternate branch of checking so we dont miss two
+ use cases:
+
2025-12-06 Paul Thomas <pault@gcc.gnu.org>
PR fortran/122693
diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index dfedb96..0e55171 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -1217,6 +1217,10 @@ match_char_length (gfc_expr **expr, bool *deferred, bool obsolescent_check)
goto syntax;
}
+ if (obsolescent_check
+ && !gfc_notify_std (GFC_STD_F95_OBS, "Old-style character length at %C"))
+ return MATCH_ERROR;
+
return MATCH_YES;
syntax:
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 3fc7631..5542318 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -5757,50 +5757,112 @@ arith_overflowed_p (enum tree_code code, const_tree type,
return wi::min_precision (wres, sign) > TYPE_PRECISION (type);
}
-/* If IFN_{MASK,LEN,MASK_LEN}_LOAD/STORE call CALL is unconditional,
- return a MEM_REF for the memory it references, otherwise return null.
- VECTYPE is the type of the memory vector. MASK_P indicates it's for
- MASK if true, otherwise it's for LEN. */
+/* Mask state for partial load/store operations (mask and length). */
+enum mask_load_store_state {
+ MASK_ALL_INACTIVE, /* All lanes/elements are inactive (can be elided). */
+ MASK_ALL_ACTIVE, /* All lanes/elements are active (unconditional). */
+ MASK_UNKNOWN
+};
-static tree
-gimple_fold_partial_load_store_mem_ref (gcall *call, tree vectype, bool mask_p)
+/* Check the mask/length state of IFN_{MASK,LEN,MASK_LEN}_LOAD/STORE call CALL.
+ Returns whether all elements are active, all inactive, or mixed.
+ VECTYPE is the vector type of the operation. */
+
+static enum mask_load_store_state
+partial_load_store_mask_state (gcall *call, tree vectype)
{
- tree ptr = gimple_call_arg (call, 0);
- tree alias_align = gimple_call_arg (call, 1);
- if (!tree_fits_uhwi_p (alias_align))
- return NULL_TREE;
+ internal_fn ifn = gimple_call_internal_fn (call);
+ int mask_index = internal_fn_mask_index (ifn);
+ int len_index = internal_fn_len_index (ifn);
+
+ /* Extract length and mask arguments up front. */
+ tree len = len_index != -1 ? gimple_call_arg (call, len_index) : NULL_TREE;
+ tree bias = len ? gimple_call_arg (call, len_index + 1) : NULL_TREE;
+ tree mask = mask_index != -1 ? gimple_call_arg (call, mask_index) : NULL_TREE;
+
+ poly_int64 nelts = GET_MODE_NUNITS (TYPE_MODE (vectype));
- if (mask_p)
+ poly_widest_int wlen = -1;
+ bool full_length_p = !len; /* No length means full length. */
+
+ /* Compute effective length. */
+ if (len && poly_int_tree_p (len))
{
- tree mask = gimple_call_arg (call, 2);
- if (!integer_all_onesp (mask))
- return NULL_TREE;
+ gcc_assert (TREE_CODE (bias) == INTEGER_CST);
+ wlen = wi::to_poly_widest (len) + wi::to_widest (bias);
+
+ if (known_eq (wlen, 0))
+ return MASK_ALL_INACTIVE;
+
+ if (known_eq (wlen, nelts))
+ full_length_p = true;
+ else
+ full_length_p = false;
}
- else
+
+ /* Check mask for early return cases. */
+ if (mask)
{
- internal_fn ifn = gimple_call_internal_fn (call);
- int len_index = internal_fn_len_index (ifn);
- tree basic_len = gimple_call_arg (call, len_index);
- if (!poly_int_tree_p (basic_len))
- return NULL_TREE;
- tree bias = gimple_call_arg (call, len_index + 1);
- gcc_assert (TREE_CODE (bias) == INTEGER_CST);
- /* For LEN_LOAD/LEN_STORE/MASK_LEN_LOAD/MASK_LEN_STORE,
- we don't fold when (bias + len) != VF. */
- if (maybe_ne (wi::to_poly_widest (basic_len) + wi::to_widest (bias),
- GET_MODE_NUNITS (TYPE_MODE (vectype))))
- return NULL_TREE;
+ if (integer_zerop (mask))
+ return MASK_ALL_INACTIVE;
+
+ if (full_length_p && integer_all_onesp (mask))
+ return MASK_ALL_ACTIVE;
+ }
+ else if (full_length_p)
+ /* No mask and full length means all active. */
+ return MASK_ALL_ACTIVE;
+
+ /* For VLA vectors, we can't do much more. */
+ if (!nelts.is_constant ())
+ return MASK_UNKNOWN;
+
+ /* Same for VLS vectors with non-constant mask. */
+ if (mask && TREE_CODE (mask) != VECTOR_CST)
+ return MASK_UNKNOWN;
- /* For MASK_LEN_{LOAD,STORE}, we should also check whether
- the mask is all ones mask. */
- if (ifn == IFN_MASK_LEN_LOAD || ifn == IFN_MASK_LEN_STORE)
+ /* Check VLS vector elements. */
+ gcc_assert (wlen.is_constant ());
+
+ HOST_WIDE_INT active_len = wlen.to_constant ().to_shwi ();
+ if (active_len == -1)
+ active_len = nelts.to_constant ();
+
+ /* Check if all elements in the active range match the mask. */
+ for (HOST_WIDE_INT i = 0; i < active_len; i++)
+ {
+ bool elt_active = !mask || !integer_zerop (vector_cst_elt (mask, i));
+ if (!elt_active)
{
- tree mask = gimple_call_arg (call, internal_fn_mask_index (ifn));
- if (!integer_all_onesp (mask))
- return NULL_TREE;
+ /* Found an inactive element. Check if all are inactive. */
+ for (HOST_WIDE_INT j = 0; j < active_len; j++)
+ if (!mask || !integer_zerop (vector_cst_elt (mask, j)))
+ return MASK_UNKNOWN; /* Mixed state. */
+ return MASK_ALL_INACTIVE;
}
}
+ /* All elements in active range are active. */
+ return full_length_p ? MASK_ALL_ACTIVE : MASK_UNKNOWN;
+}
+
+
+/* If IFN_{MASK,LEN,MASK_LEN}_LOAD/STORE call CALL is unconditional
+ (all lanes active), return a MEM_REF for the memory it references.
+ Otherwise return NULL_TREE. VECTYPE is the type of the memory vector. */
+
+static tree
+gimple_fold_partial_load_store_mem_ref (gcall *call, tree vectype)
+{
+ /* Only fold if all lanes are active (unconditional). */
+ if (partial_load_store_mask_state (call, vectype) != MASK_ALL_ACTIVE)
+ return NULL_TREE;
+
+ tree ptr = gimple_call_arg (call, 0);
+ tree alias_align = gimple_call_arg (call, 1);
+ if (!tree_fits_uhwi_p (alias_align))
+ return NULL_TREE;
+
unsigned HOST_WIDE_INT align = tree_to_uhwi (alias_align);
if (TYPE_ALIGN (vectype) != align)
vectype = build_aligned_type (vectype, align);
@@ -5808,41 +5870,68 @@ gimple_fold_partial_load_store_mem_ref (gcall *call, tree vectype, bool mask_p)
return fold_build2 (MEM_REF, vectype, ptr, offset);
}
-/* Try to fold IFN_{MASK,LEN}_LOAD call CALL. Return true on success.
- MASK_P indicates it's for MASK if true, otherwise it's for LEN. */
+/* Try to fold IFN_{MASK,LEN}_LOAD/STORE call CALL. Return true on success. */
static bool
-gimple_fold_partial_load (gimple_stmt_iterator *gsi, gcall *call, bool mask_p)
+gimple_fold_partial_load_store (gimple_stmt_iterator *gsi, gcall *call)
{
+ internal_fn ifn = gimple_call_internal_fn (call);
tree lhs = gimple_call_lhs (call);
- if (!lhs)
- return false;
+ bool is_load = (lhs != NULL_TREE);
+ tree vectype;
- if (tree rhs
- = gimple_fold_partial_load_store_mem_ref (call, TREE_TYPE (lhs), mask_p))
+ if (is_load)
+ vectype = TREE_TYPE (lhs);
+ else
{
- gassign *new_stmt = gimple_build_assign (lhs, rhs);
- gimple_set_location (new_stmt, gimple_location (call));
- gimple_move_vops (new_stmt, call);
- gsi_replace (gsi, new_stmt, false);
- return true;
+ tree rhs = gimple_call_arg (call, internal_fn_stored_value_index (ifn));
+ vectype = TREE_TYPE (rhs);
}
- return false;
-}
-/* Try to fold IFN_{MASK,LEN}_STORE call CALL. Return true on success.
- MASK_P indicates it's for MASK if true, otherwise it's for LEN. */
+ enum mask_load_store_state state
+ = partial_load_store_mask_state (call, vectype);
-static bool
-gimple_fold_partial_store (gimple_stmt_iterator *gsi, gcall *call,
- bool mask_p)
-{
- internal_fn ifn = gimple_call_internal_fn (call);
- tree rhs = gimple_call_arg (call, internal_fn_stored_value_index (ifn));
- if (tree lhs
- = gimple_fold_partial_load_store_mem_ref (call, TREE_TYPE (rhs), mask_p))
+ /* Handle all-inactive case. */
+ if (state == MASK_ALL_INACTIVE)
{
- gassign *new_stmt = gimple_build_assign (lhs, rhs);
+ if (is_load)
+ {
+ /* Replace load with else value. */
+ int else_index = internal_fn_else_index (ifn);
+ tree else_value = gimple_call_arg (call, else_index);
+ gassign *new_stmt = gimple_build_assign (lhs, else_value);
+ gimple_set_location (new_stmt, gimple_location (call));
+ gsi_replace (gsi, new_stmt, false);
+ return true;
+ }
+ else
+ {
+ /* Remove inactive store altogether. */
+ unlink_stmt_vdef (call);
+ release_defs (call);
+ gsi_replace (gsi, gimple_build_nop (), true);
+ return true;
+ }
+ }
+
+ /* We cannot simplify a gather/scatter or load/store lanes further. */
+ if (internal_gather_scatter_fn_p (ifn)
+ || TREE_CODE (vectype) == ARRAY_TYPE)
+ return false;
+
+ /* Handle all-active case by folding to regular memory operation. */
+ if (tree mem_ref = gimple_fold_partial_load_store_mem_ref (call, vectype))
+ {
+ gassign *new_stmt;
+ if (is_load)
+ new_stmt = gimple_build_assign (lhs, mem_ref);
+ else
+ {
+ tree rhs
+ = gimple_call_arg (call, internal_fn_stored_value_index (ifn));
+ new_stmt = gimple_build_assign (mem_ref, rhs);
+ }
+
gimple_set_location (new_stmt, gimple_location (call));
gimple_move_vops (new_stmt, call);
gsi_replace (gsi, new_stmt, false);
@@ -6075,19 +6164,21 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
cplx_result = true;
uaddc_usubc = true;
break;
- case IFN_MASK_LOAD:
- changed |= gimple_fold_partial_load (gsi, stmt, true);
- break;
- case IFN_MASK_STORE:
- changed |= gimple_fold_partial_store (gsi, stmt, true);
- break;
case IFN_LEN_LOAD:
+ case IFN_MASK_LOAD:
case IFN_MASK_LEN_LOAD:
- changed |= gimple_fold_partial_load (gsi, stmt, false);
- break;
+ case IFN_MASK_GATHER_LOAD:
+ case IFN_MASK_LEN_GATHER_LOAD:
+ case IFN_MASK_LOAD_LANES:
+ case IFN_MASK_LEN_LOAD_LANES:
case IFN_LEN_STORE:
+ case IFN_MASK_STORE:
case IFN_MASK_LEN_STORE:
- changed |= gimple_fold_partial_store (gsi, stmt, false);
+ case IFN_MASK_SCATTER_STORE:
+ case IFN_MASK_LEN_SCATTER_STORE:
+ case IFN_MASK_STORE_LANES:
+ case IFN_MASK_LEN_STORE_LANES:
+ changed |= gimple_fold_partial_load_store (gsi, stmt);
break;
default:
break;
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 13fbd2c..8df4f50 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -5006,6 +5006,7 @@ internal_fn_len_index (internal_fn fn)
switch (fn)
{
case IFN_LEN_LOAD:
+ return 3;
case IFN_LEN_STORE:
return 2;
@@ -5071,6 +5072,9 @@ internal_fn_else_index (internal_fn fn)
case IFN_COND_LEN_NOT:
return 2;
+ case IFN_LEN_LOAD:
+ return 2;
+
case IFN_COND_ADD:
case IFN_COND_SUB:
case IFN_COND_MUL:
@@ -5401,7 +5405,7 @@ internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
{
optab optab = direct_internal_fn_optab (ifn);
insn_code icode = direct_optab_handler (optab, mode);
- int bias_no = 3;
+ int bias_idx = internal_fn_len_index (ifn) + 1;
if (icode == CODE_FOR_nothing)
{
@@ -5412,22 +5416,23 @@ internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
{
/* Try MASK_LEN_LOAD. */
optab = direct_internal_fn_optab (IFN_MASK_LEN_LOAD);
+ bias_idx = internal_fn_len_index (IFN_MASK_LEN_LOAD) + 1;
}
else
{
/* Try MASK_LEN_STORE. */
optab = direct_internal_fn_optab (IFN_MASK_LEN_STORE);
+ bias_idx = internal_fn_len_index (IFN_MASK_LEN_STORE) + 1;
}
icode = convert_optab_handler (optab, mode, mask_mode);
- bias_no = 4;
}
if (icode != CODE_FOR_nothing)
{
/* For now we only support biases of 0 or -1. Try both of them. */
- if (insn_operand_matches (icode, bias_no, GEN_INT (0)))
+ if (insn_operand_matches (icode, bias_idx, GEN_INT (0)))
return 0;
- if (insn_operand_matches (icode, bias_no, GEN_INT (-1)))
+ if (insn_operand_matches (icode, bias_idx, GEN_INT (-1)))
return -1;
}
diff --git a/gcc/optabs-tree.cc b/gcc/optabs-tree.cc
index 0de74c7..53788b9 100644
--- a/gcc/optabs-tree.cc
+++ b/gcc/optabs-tree.cc
@@ -615,28 +615,27 @@ target_supports_len_load_store_p (machine_mode mode, bool is_load,
{
optab op = is_load ? len_load_optab : len_store_optab;
optab masked_op = is_load ? mask_len_load_optab : mask_len_store_optab;
+ internal_fn which_ifn;
- if (direct_optab_handler (op, mode))
+ enum insn_code icode;
+ if ((icode = direct_optab_handler (op, mode)) != CODE_FOR_nothing)
{
- if (ifn)
- *ifn = is_load ? IFN_LEN_LOAD : IFN_LEN_STORE;
- return true;
+ which_ifn = is_load ? IFN_LEN_LOAD : IFN_LEN_STORE;
}
machine_mode mask_mode;
- enum insn_code icode;
- if (targetm.vectorize.get_mask_mode (mode).exists (&mask_mode)
+ if (!icode
+ && targetm.vectorize.get_mask_mode (mode).exists (&mask_mode)
&& ((icode = convert_optab_handler (masked_op, mode, mask_mode))
!= CODE_FOR_nothing))
- {
- if (ifn)
- *ifn = is_load ? IFN_MASK_LEN_LOAD : IFN_MASK_LEN_STORE;
- if (elsvals && is_load)
- get_supported_else_vals (icode,
- internal_fn_else_index (IFN_MASK_LEN_LOAD),
- *elsvals);
- return true;
- }
- return false;
+ which_ifn = is_load ? IFN_MASK_LEN_LOAD : IFN_MASK_LEN_STORE;
+
+ if (icode && elsvals && is_load)
+ get_supported_else_vals (icode, internal_fn_else_index (which_ifn),
+ *elsvals);
+
+ if (icode && ifn)
+ *ifn = which_ifn;
+ return icode;
}
/* If target supports vector load/store with length for vector mode MODE,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8f13d2c..f8a8fba 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,236 @@
+2025-12-08 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ PR tree-optimization/46555
+ * gcc.dg/tree-ssa/pr46555.c: New test.
+
+2025-12-08 Harald Anlauf <anlauf@gmx.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/123025
+ * gfortran.dg/assumed_charlen_dummy.f90: These tests failed
+ with the change because of the default -pedantic option
+ used by the dg.exp mechanisms. Overide this default.
+ * gfortran.dg/automatic_char_len_1.f90: Ditto.
+ * gfortran.dg/entry_23.f: Ditto.
+ * gfortran.dg/finalize_59.f90: Dito.
+ * gfortran.dg/g77/f90-intrinsic-bit.f: Ditto.
+ * gfortran.dg/g77/f90-intrinsic-mathematical.f: Ditto.
+ * gfortran.dg/g77/f90-intrinsic-numeric.f: Ditto.
+ * gfortran.dg/g77/intrinsic-unix-bessel.f: Ditto.
+ * gfortran.dg/g77/intrinsic-unix-erf.f: Ditto.
+ * gfortran.dg/initialization_9.f90: Ditto.
+ * gfortran.dg/intrinsic_actual_4.f90: Ditto.
+ * gfortran.dg/namelist_assumed_char.f90: Ditto.
+ * gfortran.dg/pr15140.f90: Ditto.
+
+2025-12-08 Egas Ribeiro <egas.g.ribeiro@tecnico.ulisboa.pt>
+
+ PR c++/119343
+ * g++.dg/template/sfinae-deleted-pr119343.C: New test.
+
+2025-12-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/tls/data-sections-1.c: New test.
+
+2025-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/123040
+ * g++.dg/torture/pr123040.C: New testcase.
+
+2025-12-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/123038
+ * gcc.dg/vect/pr123038.c: New testcase.
+
+2025-12-08 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/123026
+ * gcc.target/aarch64/pr123026.c: New test.
+
+2025-12-08 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/122343
+ * gcc.target/i386/avx2-vpcmpgtq-1.c: Compile with
+ -fno-fuse-ops-with-volatile-access.
+
+2025-12-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/reduce3.adb: New test.
+
+2025-12-07 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/122343
+ * gcc.target/i386/20040112-1.c: Add -fomit-frame-pointer and use
+ check-function-bodies to check for loop.
+ * gcc.target/i386/avx-ne-convert-1.c: Compile with
+ -fno-fuse-ops-with-volatile-access.
+ * gcc.target/i386/avx10_2-bf16-1.c: Likewise.
+ * gcc.target/i386/avx10_2-convert-1.c: Likewise.
+ * gcc.target/i386/avx10_2-satcvt-1.c: Likewise.
+ * gcc.target/i386/avx512bf16-vcvtneps2bf16-1.c: Likewise.
+ * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1a.c: Likewise.
+ * gcc.target/i386/avx512bf16vl-vcvtneps2bf16-1b.c: Likewise.
+ * gcc.target/i386/avx512bitalg-vpshufbitqmb.c: Likewise.
+ * gcc.target/i386/avx512bw-vpcmpb-1.c: Likewise.
+ * gcc.target/i386/avx512bw-vpcmpub-1.c: Likewise.
+ * gcc.target/i386/avx512bw-vpcmpuw-1.c: Likewise.
+ * gcc.target/i386/avx512bw-vpcmpw-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vcvtps2qq-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vcvtps2uqq-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vcvtqq2pd-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vcvtqq2ps-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vcvttps2qq-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vcvttps2uqq-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vcvtuqq2pd-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vcvtuqq2ps-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vextractf32x8-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vextractf64x2-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vextracti64x2-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vfpclasspd-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vfpclassps-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vfpclasssd-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vfpclassss-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vpmullq-1.c: Likewise.
+ * gcc.target/i386/avx512dq-vpmullq-3.c: Likewise.
+ * gcc.target/i386/avx512f-pr100267-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcmppd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcmpps-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtps2pd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtsd2si-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtsd2si64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtsd2usi-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtsd2usi64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtsi2ss-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtss2si-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtss2si64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtss2usi-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvtss2usi64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvttsd2si-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvttsd2si64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvttsd2usi-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvttsd2usi64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvttss2si-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvttss2si64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvttss2usi-1.c: Likewise.
+ * gcc.target/i386/avx512f-vcvttss2usi64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vextractf32x4-1.c: Likewise.
+ * gcc.target/i386/avx512f-vextractf64x4-1.c: Likewise.
+ * gcc.target/i386/avx512f-vextracti64x4-1.c: Likewise.
+ * gcc.target/i386/avx512f-vmovapd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vmovaps-1.c: Likewise.
+ * gcc.target/i386/avx512f-vmovdqa64-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpandnq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpbroadcastd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpbroadcastq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpeqq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpequq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpged-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpgeq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpgeud-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpgeuq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpled-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpleq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpleud-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpleuq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpltd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpltq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpltud-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpltuq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpneqd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpneqq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpnequd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpnequq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpud-1.c: Likewise.
+ * gcc.target/i386/avx512f-vpcmpuq-1.c: Likewise.
+ * gcc.target/i386/avx512f-vrndscalepd-1.c: Likewise.
+ * gcc.target/i386/avx512f-vrndscaleps-1.c: Likewise.
+ * gcc.target/i386/avx512fp16-complex-fma.c: Likewise.
+ * gcc.target/i386/avx512fp16-vaddph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtpd2ph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtph2dq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtph2pd-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtph2psx-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtph2qq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtph2udq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtph2uqq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtph2uw-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtph2w-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtps2ph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtqq2ph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvttph2dq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvttph2qq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvttph2udq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvttph2uqq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvttph2uw-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvttph2w-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vcvtuqq2ph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfcmaddcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfcmulcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfmaddcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfmulcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfpclassph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfpclasssh-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vmulph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vrcpph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vrsqrtph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vsqrtph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vaddph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtpd2ph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtph2dq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtph2psx-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtph2qq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtph2udq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtph2uqq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtph2uw-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtph2w-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtps2ph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtqq2ph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvttph2dq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvttph2udq-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvttph2uw-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvttph2w-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vcvtuqq2ph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfcmaddcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfmaddcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfmulcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfpclassph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vmulph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vrcpph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vrsqrtph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vsqrtph-1a.c: Likewise.
+ * gcc.target/i386/avx512vl-pr100267-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vcmppd-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vcmpps-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vcvtpd2ps-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vcvtpd2udq-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vcvttpd2udq-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vcvttps2udq-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vextractf32x4-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vmovapd-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vmovaps-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vmovdqa64-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vpcmpd-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vpcmpeqq-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vpcmpequq-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vpcmpq-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vpcmpud-1.c: Likewise.
+ * gcc.target/i386/avx512vl-vpcmpuq-1.c: Likewise.
+ * gcc.target/i386/pr122343-1a.c: New test.
+ * gcc.target/i386/pr122343-1b.c: Likewise.
+ * gcc.target/i386/pr122343-2a.c: Likewise.
+ * gcc.target/i386/pr122343-2b.c: Likewise.
+ * gcc.target/i386/pr122343-3.c: Likewise.
+ * gcc.target/i386/pr122343-4a.c: Likewise.
+ * gcc.target/i386/pr122343-4b.c: Likewise.
+ * gcc.target/i386/pr122343-5a.c: Likewise.
+ * gcc.target/i386/pr122343-5b.c: Likewise.
+ * gcc.target/i386/pr122343-6a.c: Likewise.
+ * gcc.target/i386/pr122343-6b.c: Likewise.
+ * gcc.target/i386/pr122343-7.c: Likewise.
+
2025-12-06 Alexandre Oliva <oliva@adacore.com>
PR rtl-optimization/122947
diff --git a/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C b/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C
new file mode 100644
index 0000000..065ad60
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C
@@ -0,0 +1,31 @@
+// { dg-do compile { target c++11 } }
+// PR c++/119343 - No SFINAE for deleted explicit specializations
+
+struct true_type { static constexpr bool value = true; };
+struct false_type { static constexpr bool value = false; };
+
+struct X {
+ static void f()=delete;
+ template<int> static void g();
+};
+template<> void X::g<0>()=delete;
+struct Y {
+ static void f();
+ template<int> static void g();
+};
+
+template<class T,class=void>
+struct has_f : false_type {};
+template<class T>
+struct has_f<T,decltype(void(T::f))> : true_type {};
+
+static_assert(!has_f<X>::value, "");
+static_assert(has_f<Y>::value, "");
+
+template<class T,class=void>
+struct has_g0 : false_type {};
+template<class T>
+struct has_g0<T,decltype(void(T::template g<0>))> : true_type {};
+
+static_assert(!has_g0<X>::value, "");
+static_assert(has_g0<Y>::value, "");
diff --git a/gcc/testsuite/g++.dg/torture/pr123040.C b/gcc/testsuite/g++.dg/torture/pr123040.C
new file mode 100644
index 0000000..3ba2d90
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr123040.C
@@ -0,0 +1,61 @@
+// { dg-do compile }
+
+template <int kBytes, typename From, typename To>
+void CopyBytes(From from, To to) {
+ __builtin_memcpy(to, from, kBytes);
+}
+template <typename From, typename To> void CopySameSize(From *from, To to) {
+ CopyBytes<sizeof(From)>(from, to);
+}
+template <typename> using MakeUnsigned = char;
+template <typename Lane, int N> struct Simd {
+ using T = Lane;
+ static constexpr int kPrivateLanes = N;
+ template <typename NewT> using Rebind = Simd<NewT, 0>;
+};
+template <class D> using TFromD = D::T;
+template <class T, class D> using Rebind = D::template Rebind<T>;
+template <class D> using RebindToUnsigned = Rebind<MakeUnsigned<D>, D>;
+template <typename T, int> struct Vec128 {
+ using PrivateT = T;
+ static constexpr int kPrivateN = 6;
+ T raw[16];
+};
+template <class V> using DFromV = Simd<typename V::PrivateT, V::kPrivateN>;
+template <class D> Vec128<TFromD<D>, D::kPrivateLanes> Zero(D);
+template <class D> using VFromD = decltype(Zero(D()));
+template <class D, class VFrom> VFromD<D> BitCast(D, VFrom v) {
+ VFromD<D> to;
+ CopySameSize(&v, to.raw);
+ return to;
+}
+template <int N> Vec128<signed char, N> And(Vec128<signed char, N> b) {
+ Vec128<signed char, N> a;
+ DFromV<decltype(a)> d;
+ RebindToUnsigned<decltype(d)> du;
+ auto au(a);
+ auto bu = BitCast(du, b);
+ for (int i = 0; i < N; ++i)
+ au.raw[i] &= bu.raw[i];
+ return au;
+}
+void Or(Vec128<signed char, 16>);
+template <int N> void IfVecThenElse(Vec128<signed char, N> yes) {
+ Vec128 __trans_tmp_2 = And(yes);
+ Or(__trans_tmp_2);
+}
+template <int N> void IfThenElseZero(Vec128<signed char, N> yes) {
+ IfVecThenElse(yes);
+}
+Vec128<signed char, 16> Abs_a;
+char MaskedAbs___trans_tmp_5;
+void MaskedAbs() {
+ Vec128<signed char, 16> __trans_tmp_4;
+ for (int i = 0; i < 16; ++i) {
+ MaskedAbs___trans_tmp_5 = Abs_a.raw[i] ? -Abs_a.raw[i] : 0;
+ Abs_a.raw[i] = MaskedAbs___trans_tmp_5;
+ }
+ __trans_tmp_4 = Abs_a;
+ Vec128 __trans_tmp_3 = __trans_tmp_4;
+ IfThenElseZero(__trans_tmp_3);
+}
diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-pr122982.c b/gcc/testsuite/gcc.dg/pointer-counted-by-pr122982.c
new file mode 100644
index 0000000..1bad7f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-pr122982.c
@@ -0,0 +1,19 @@
+/* PR c/122982 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+int* f (int);
+
+struct __bounded_ptr {
+ int k;
+ int *buf __attribute__ ((counted_by (k)));
+};
+
+int*
+f1 (int n) { return f (n); }
+
+void h1 (void)
+{
+ int *p = (struct __bounded_ptr) {3, f1 (3)}.buf;
+ __builtin_memset (p, 0, 3 * sizeof p);
+}
diff --git a/gcc/testsuite/gcc.dg/pr123018.c b/gcc/testsuite/gcc.dg/pr123018.c
new file mode 100644
index 0000000..f1f701b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr123018.c
@@ -0,0 +1,17 @@
+/* PR c/123018 */
+/* { dg-do compile } */
+
+struct A {
+ int x : 8 __attribute__ ((vector_size (8))); /* { dg-error "bit-field 'x' has invalid type" } */
+};
+struct B {
+ float x : 8; /* { dg-error "bit-field 'x' has invalid type" } */
+};
+struct C {
+ int : 8 __attribute__ ((vector_size (8))); /* { dg-error "bit-field '\[^\n\r]*anonymous\[^\n\r]*' has invalid type" } */
+ int x;
+};
+struct D {
+ float : 8; /* { dg-error "bit-field '\[^\n\r]*anonymous\[^\n\r]*' has invalid type" } */
+ int x;
+};
diff --git a/gcc/testsuite/gcc.dg/tls/data-sections-1.c b/gcc/testsuite/gcc.dg/tls/data-sections-1.c
new file mode 100644
index 0000000..c829256
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tls/data-sections-1.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-require-effective-target tls_runtime } */
+/* { dg-options "-fdata-sections" } */
+/* { dg-add-options tls } */
+
+__thread int i = 1;
+
+int main (void)
+{
+ if (i != 1)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr123027.c b/gcc/testsuite/gcc.dg/torture/pr123027.c
new file mode 100644
index 0000000..cba4cc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr123027.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-ffinite-math-only" } */
+/* { dg-add-options ieee } */
+
+double a = 0.0;
+double b = -0.0;
+
+int main()
+{
+ double min1 = a < b ? a : b;
+ double max1 = a > b ? a : b;
+ double min2 = b < a ? b : a;
+ double max2 = b > a ? b : a;
+ if (__builtin_copysign (1., min1) != -1.
+ || __builtin_copysign (1., max1) != -1.
+ || __builtin_copysign (1., min2) != 1.
+ || __builtin_copysign (1., max2) != 1.)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr46555.c b/gcc/testsuite/gcc.dg/tree-ssa/pr46555.c
new file mode 100644
index 0000000..d4de7c2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr46555.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized-details -fdump-rtl-pro_and_epilogue" } */
+/* PR tree-optimization/46555 */
+/* Here should not remove the forwarder block (or rather recreate it and not
+ remove it again). This improves expansion to RTL as there is one less copy
+ (or constant formation) in some cases. In this case we also get the ability
+ to shrink wrap the function. */
+
+int h(void);
+int f(int a, int b, int c)
+{
+ if (a)
+ return 2;
+ h();
+ if (b)
+ return 2;
+ h();
+ if (c)
+ return 2;
+ h();
+ return 4;
+}
+
+/* { dg-final { scan-tree-dump-times "New forwarder block for edge" 1 "optimized" } } */
+/* Make sure we only have a PHI with 2 arguments here, 2 and 4. */
+/* { dg-final { scan-tree-dump "PHI <2..., 4...>|PHI <4..., 2...>" "optimized" } } */
+/* Make sure we can shrink wrap the function now too. */
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" { target { { { i?86-*-* x86_64-*-* } && { ! ia32 } } || { powerpc*-*-* aarch64*-*-* riscv*-*-* arm*-*-* } } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr123038.c b/gcc/testsuite/gcc.dg/vect/pr123038.c
new file mode 100644
index 0000000..bca831f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr123038.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+
+unsigned char f(int b)
+{
+ for (int a = 0; a < 10; a += 1)
+ b = __builtin_ffs(b);
+ return b;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr123026.c b/gcc/testsuite/gcc.target/aarch64/pr123026.c
new file mode 100644
index 0000000..4dcce8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr123026.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O3 -march=armv8-a -std=c99" } */
+
+#include <stdbool.h>
+
+int g;
+
+__attribute__ ((noipa)) void
+foo(bool a) {
+ for (int i = 0; i < 4; i++)
+ if (!i || a)
+ g += 1;
+}
+
+int main()
+{
+ foo(0);
+ if (g != 1)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c
index 1539f58..39db13b 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c
@@ -46,8 +46,5 @@ ALL_DATA (st2, x2_t)
ALL_DATA (st3, x3_t)
ALL_DATA (st4, x4_t)
-/* FIXME: Currently, st1/2/3/4 are not folded with a pfalse
- predicate, which is the reason for the 48 missing cases below. Once
- folding is implemented for these intrinsics, the sum should be 60. */
-/* { dg-final { scan-assembler-times {\t.cfi_startproc\n\tret\n} 12 } } */
+/* { dg-final { scan-assembler-times {\t.cfi_startproc\n\tret\n} 60 } } */
/* { dg-final { scan-assembler-times {\t.cfi_startproc\n} 60 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c b/gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c
index 7a98380..5e6f431 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mavx2 -O2" } */
+/* { dg-options "-mavx2 -O2 -fno-fuse-ops-with-volatile-access" } */
/* { dg-final { scan-assembler "vpcmpgtq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr121230.c b/gcc/testsuite/gcc.target/i386/pr121230.c
new file mode 100644
index 0000000..67c9c5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121230.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O3 -march=athlon-xp -mfpmath=387 -fexcess-precision=standard" } */
+
+typedef struct {
+ float a;
+ float b;
+} f32_2;
+
+f32_2 add32_2(f32_2 x, f32_2 y) {
+ return (f32_2){ x.a + y.a, x.b + y.b};
+}
+
+/* We do not want the vectorizer to vectorize the store and/or the
+ conversion (with IA32 we do not support V2SF add) given that spills
+ FP regs to reload them to XMM. */
+/* { dg-final { scan-assembler-not "movss\[ \\t\]+\[0-9\]*\\\(%esp\\\), %xmm" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr123027.c b/gcc/testsuite/gcc.target/i386/pr123027.c
new file mode 100644
index 0000000..b7effac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr123027.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mfpmath=sse -ffinite-math-only" } */
+
+float foo (float a, float b)
+{
+ return a < b ? a : b;
+}
+
+float bar (float a, float b)
+{
+ return a > b ? a : b;
+}
+
+/* { dg-final { scan-assembler-times "minss" 1 } } */
+/* { dg-final { scan-assembler-times "maxss" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-vec-length-epil-8.c b/gcc/testsuite/gcc.target/powerpc/p9-vec-length-epil-8.c
index 34a2c8e..5dff0d0 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-vec-length-epil-8.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-vec-length-epil-8.c
@@ -13,5 +13,5 @@
#include "p9-vec-length-8.h"
-/* { dg-final { scan-assembler-times {\mlxvl\M} 16 } } */
+/* { dg-final { scan-assembler-times {\mlxvl\M} 14 } } */
/* { dg-final { scan-assembler-times {\mstxvl\M} 7 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/pragma-target-1.c b/gcc/testsuite/gcc.target/riscv/pragma-target-1.c
new file mode 100644
index 0000000..d1a0600
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pragma-target-1.c
@@ -0,0 +1,59 @@
+/* Test for #pragma GCC target and push/pop options support in RISC-V */
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O2" } */
+
+/* Default compilation options - no vector */
+void default_func(void) {
+#ifdef __riscv_vector
+ __builtin_abort(); /* Should not have vector by default */
+#endif
+}
+
+/* Change target to enable vector */
+#pragma GCC push_options
+#pragma GCC target("arch=rv64gcv")
+void vector_func(void) {
+#ifndef __riscv_vector
+ __builtin_abort(); /* Should have vector here */
+#endif
+}
+#pragma GCC pop_options
+
+/* Back to default - no vector */
+void after_pop_func(void) {
+#ifdef __riscv_vector
+ __builtin_abort(); /* Should not have vector after pop */
+#endif
+}
+
+/* Test multiple push/pop levels */
+#pragma GCC push_options
+#pragma GCC target("arch=rv64gc")
+void base_func(void) {
+#ifdef __riscv_vector
+ __builtin_abort(); /* Should not have vector */
+#endif
+}
+
+#pragma GCC push_options
+#pragma GCC target("arch=rv64gcv")
+void nested_vector_func(void) {
+#ifndef __riscv_vector
+ __builtin_abort(); /* Should have vector here */
+#endif
+}
+#pragma GCC pop_options
+
+void after_nested_pop_func(void) {
+#ifdef __riscv_vector
+ __builtin_abort(); /* Should not have vector after nested pop */
+#endif
+}
+#pragma GCC pop_options
+
+/* Final function should be back to original default */
+void final_func(void) {
+#ifdef __riscv_vector
+ __builtin_abort(); /* Should not have vector */
+#endif
+}
diff --git a/gcc/testsuite/gcc.target/riscv/pragma-target-2.c b/gcc/testsuite/gcc.target/riscv/pragma-target-2.c
new file mode 100644
index 0000000..077bcdd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pragma-target-2.c
@@ -0,0 +1,26 @@
+/* Test for #pragma GCC target with tune parameter */
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=rocket -O2" } */
+
+void default_tune(void) {
+ /* Default tune is rocket */
+}
+
+#pragma GCC push_options
+#pragma GCC target("tune=sifive-7-series")
+void sifive_tune(void) {
+ /* Tune should be sifive-7-series */
+}
+#pragma GCC pop_options
+
+void back_to_rocket(void) {
+ /* Tune should be back to rocket */
+}
+
+#pragma GCC target("arch=rv64gcv;tune=generic")
+void combined_options(void) {
+#ifndef __riscv_vector
+ __builtin_abort(); /* Should have vector */
+#endif
+ /* Tune should be generic */
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-1.c
new file mode 100644
index 0000000..923c1f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+void __attribute__ (( target ("max-vectorization")))
+foo (char *restrict a, int *restrict b, short *restrict c,
+ int *restrict d, int stride)
+{
+ if (stride <= 1)
+ return;
+
+ for (int i = 0; i < 3; i++)
+ {
+ int res = c[i];
+ int t = b[d[i]];
+ if (a[c[i]] != 0)
+ res = t * b[d[i]];
+ c[i] = res;
+ }
+}
+
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-2.c
new file mode 100644
index 0000000..fc5c2ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -mmax-vectorization -fdump-tree-vect-details" } */
+
+void
+foo (char *restrict a, int *restrict b, short *restrict c,
+ int *restrict d, int stride)
+{
+ if (stride <= 1)
+ return;
+
+ for (int i = 0; i < 3; i++)
+ {
+ int res = c[i];
+ int t = b[d[i]];
+ if (a[c[i]] != 0)
+ res = t * b[d[i]];
+ c[i] = res;
+ }
+}
+
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122635-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122635-1.c
new file mode 100644
index 0000000..0beb3d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122635-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv64gcv_zvl256b -mabi=lp64d -mrvv-vector-bits=zvl -mno-autovec-segment" } */
+
+typedef struct {
+ int a[6];
+ float b[3];
+} c;
+
+int d(c *e) {
+ int f =0;
+ for (; f < 3; f++) {
+ e->a[2 * f] = e->b[f];
+ e->a[2 * f + 1] = -e->a[2 * f];
+ e->a[2 * f] = f + 3 * e->a[2 * f];
+ e->a[2 * f + 1] = f + 3 * e->a[2 * f + 1];
+ }
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "vsetivli.*zero,0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122635-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122635-2.c
new file mode 100644
index 0000000..0de69b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122635-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv64gcv_zvl256b -mabi=lp64d -mrvv-vector-bits=zvl -mno-autovec-segment" } */
+
+typedef struct {
+ int A[6];
+ float b[];
+} a;
+
+int b(a *a) {
+ int b = 0;
+ for (; b < 3; b++) {
+ a->A[2 * b] = a->b[b] - b + a->A[2 * b];
+ a->A[2 * b + 1] = b * a->A[2 * b + 1];
+ }
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "vsetivli.*zero,0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123022-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123022-2.c
new file mode 100644
index 0000000..0562b56
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123022-2.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv64gcv_zvl512b -mabi=lp64d -mrvv-vector-bits=zvl -fsigned-char" } */
+
+#include "pr123022.c"
+
+/* { dg-final { scan-assembler-not "vset.*zero,1," } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123022.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123022.c
new file mode 100644
index 0000000..1f5f165
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123022.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-require-effective-target rvv_zvl512b_ok } */
+/* { dg-options "-O3 -march=rv64gcv_zvl512b -mabi=lp64d -mrvv-vector-bits=zvl -fsigned-char" } */
+unsigned e[2][2];
+long a;
+char c[2];
+
+int
+main ()
+{
+ long long b;
+ c[1] = 3;
+ for (unsigned h = 0; h < 2; h++)
+ for (int i = c[0]; i < 5; i += 5)
+ for (int j = 0; j < 219; j++)
+ a = c[h] ? e[h][h] + 3326195747 : 0;
+
+ b = a;
+ if (b != 3326195747)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123074.C b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123074.C
new file mode 100644
index 0000000..d203477
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123074.C
@@ -0,0 +1,124 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv64gcv_zvl256b -mabi=lp64d -mrvv-vector-bits=zvl -mrvv-max-lmul=m2 -fpermissive -Wno-return-type" } */
+
+namespace std {
+template <typename _Iterator> _Iterator __miter_base(_Iterator);
+template <typename _Default, typename, template <typename> class>
+struct __detector {
+ using type = _Default;
+};
+template <typename _Default, template <typename> class _Op>
+using __detected_or = __detector<_Default, void, _Op>;
+template <typename _Default, template <typename> class _Op>
+using __detected_or_t = typename __detected_or<_Default, _Op>::type;
+template <typename _Tp> class allocator {
+public:
+ typedef _Tp value_type;
+};
+template <typename> struct pointer_traits {
+ template <typename _Up> using rebind = _Up *;
+};
+} // namespace std
+namespace __gnu_cxx {
+template <typename _Iterator, typename> class __normal_iterator {
+public:
+ _Iterator base();
+};
+} // namespace __gnu_cxx
+namespace std {
+template <bool, typename _OutIter, typename _InIter>
+void __assign_one(_OutIter __out, _InIter __in) {
+ *__out = *__in;
+}
+template <bool _IsMove, typename _BI1, typename _BI2>
+__copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result) { /* { dg-warning "with no type" "" } */
+ while (__first != __last) {
+ --__last;
+ --__result;
+ __assign_one<_IsMove>(__result, __last);
+ }
+}
+template <bool _IsMove, typename _BI1, typename _BI2>
+__copy_move_backward_a1(_BI1 __first, _BI1 __last, _BI2 __result) { /* { dg-warning "with no type" "" } */
+ __copy_move_backward_a2<_IsMove>(__first, __last, __result);
+}
+template <bool _IsMove, typename _II, typename _OI>
+__copy_move_backward_a(_II __first, _II __last, _OI __result) { /* { dg-warning "with no type" "" } */
+ __copy_move_backward_a1<_IsMove>(__first, __last, __result);
+}
+template <typename _BI1, typename _BI2>
+move_backward(_BI1 __first, _BI1 __last, _BI2 __result) { /* { dg-warning "with no type" "" } */
+ __copy_move_backward_a<true>(__first, __miter_base(__last), __result);
+}
+struct __allocator_traits_base {
+ template <typename _Tp> using __pointer = typename _Tp::pointer;
+ template <typename _Tp> using __c_pointer = typename _Tp::const_pointer;
+};
+template <typename _Alloc> struct allocator_traits : __allocator_traits_base {
+ typedef typename _Alloc::value_type value_type;
+ using pointer = __detected_or_t<value_type *, __pointer>;
+ template <template <typename> class, typename _Tp> struct _Ptr {
+ using type = typename pointer_traits<pointer>::rebind<_Tp>;
+ };
+ using const_pointer = typename _Ptr<__c_pointer, value_type>::type;
+};
+} // namespace std
+namespace __gnu_cxx {
+template <typename _Alloc>
+struct __alloc_traits : std::allocator_traits<_Alloc> {};
+} // namespace __gnu_cxx
+namespace std {
+template <typename, typename _Alloc> struct _Vector_base {
+ typedef __gnu_cxx::__alloc_traits<_Alloc> _Tp_alloc_type;
+ typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer;
+ struct {
+ pointer _M_finish;
+ } _M_impl;
+};
+template <typename _Tp, typename _Alloc = allocator<_Tp>>
+class vector : _Vector_base<_Tp, _Alloc> {
+ typedef _Vector_base<_Tp, _Alloc> _Base;
+ typedef typename _Base::_Tp_alloc_type _Alloc_traits;
+
+public:
+ typedef _Tp value_type;
+ typedef typename _Base::pointer pointer;
+ typedef typename _Alloc_traits::const_pointer const_pointer;
+ typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
+ typedef __gnu_cxx::__normal_iterator<const_pointer, vector> const_iterator;
+ iterator begin();
+ iterator insert(const_iterator, const value_type &);
+ struct _Temporary_value {};
+ template <typename _Arg> void _M_insert_aux(iterator, _Arg &&);
+};
+template <typename _Tp, typename _Alloc>
+typename vector<_Tp, _Alloc>::iterator
+vector<_Tp, _Alloc>::insert(const_iterator, const value_type &) {
+ auto __pos = begin();
+ _Temporary_value __x_copy;
+ _M_insert_aux(__pos, __x_copy);
+}
+template <typename _Tp, typename _Alloc>
+template <typename _Arg>
+void vector<_Tp, _Alloc>::_M_insert_aux(iterator __position, _Arg &&) {
+ move_backward(__position.base(), this->_M_impl._M_finish,
+ this->_M_impl._M_finish);
+}
+namespace internals {
+struct distributing {
+ distributing &operator=(const distributing &);
+ int global_row;
+ *constraints; /* { dg-warning "with no type" "" } */
+};
+distributing &distributing::operator=(const distributing &in) {
+ global_row = in.global_row;
+ return; /* { dg-warning "return-statement with no value" "" } */
+}
+insert_index(vector<distributing> my_indices) { /* { dg-warning "with no type" "" } */
+ typedef vector<distributing>::iterator index_iterator;
+ index_iterator pos;
+ distributing row_value;
+ my_indices.insert(pos, row_value);
+}
+} // namespace internals
+} // namespace std
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-1-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-1-run.c
new file mode 100644
index 0000000..b3bf8da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-1-run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+
+char p[128];
+
+bool __attribute__((noipa))
+fand (int n)
+{
+ bool r = true;
+ for (int i = 0; i < n; ++i)
+ r &= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fior (int n)
+{
+ bool r = false;
+ for (int i = 0; i < n; ++i)
+ r |= (p[i] != 0);
+ return r;
+}
+
+int main()
+{
+ __builtin_memset (p, 1, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (!fand (n))
+ __builtin_abort ();
+
+ p[0] = 0;
+ for (int n = 1; n < 77; ++n)
+ if (fand (n))
+ __builtin_abort ();
+
+ __builtin_memset (p, 0, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (fior (n))
+ __builtin_abort ();
+
+ p[0] = 1;
+ for (int n = 1; n < 77; ++n)
+ if (!fior (n))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-1.c
new file mode 100644
index 0000000..b8c4f22
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-1.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+char p[128];
+
+bool __attribute__((noipa))
+fand (int n)
+{
+ bool r = true;
+ for (int i = 0; i < 16; ++i)
+ r &= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fior (int n)
+{
+ bool r = false;
+ for (int i = 0; i < 16; ++i)
+ r |= (p[i] != 0);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" } } */
+/* { dg-final { scan-assembler-times {vcpop\.m\s+[atx][0-9]+,\s*v[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-2-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-2-run.c
new file mode 100644
index 0000000..1a64b2b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-2-run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+
+short p[128];
+
+bool __attribute__((noipa))
+fand (int n)
+{
+ bool r = true;
+ for (int i = 0; i < n; ++i)
+ r &= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fior (int n)
+{
+ bool r = false;
+ for (int i = 0; i < n; ++i)
+ r |= (p[i] != 0);
+ return r;
+}
+
+int main()
+{
+ __builtin_memset (p, 1, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (!fand (n))
+ __builtin_abort ();
+
+ p[0] = 0;
+ for (int n = 1; n < 77; ++n)
+ if (fand (n))
+ __builtin_abort ();
+
+ __builtin_memset (p, 0, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (fior (n))
+ __builtin_abort ();
+
+ p[0] = 1;
+ for (int n = 1; n < 77; ++n)
+ if (!fior (n))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-2.c
new file mode 100644
index 0000000..868f91b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-2.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+short p[128];
+
+bool __attribute__((noipa))
+fand ()
+{
+ bool r = true;
+ for (int i = 0; i < 16; ++i)
+ r &= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fior ()
+{
+ bool r = false;
+ for (int i = 0; i < 16; ++i)
+ r |= (p[i] != 0);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" } } */
+/* { dg-final { scan-assembler-times {vcpop\.m\s+[atx][0-9]+,\s*v[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-3-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-3-run.c
new file mode 100644
index 0000000..693a9118
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-3-run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+
+int p[128];
+
+bool __attribute__((noipa))
+fand (int n)
+{
+ bool r = true;
+ for (int i = 0; i < n; ++i)
+ r &= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fior (int n)
+{
+ bool r = false;
+ for (int i = 0; i < n; ++i)
+ r |= (p[i] != 0);
+ return r;
+}
+
+int main()
+{
+ __builtin_memset (p, 1, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (!fand (n))
+ __builtin_abort ();
+
+ p[0] = 0;
+ for (int n = 1; n < 77; ++n)
+ if (fand (n))
+ __builtin_abort ();
+
+ __builtin_memset (p, 0, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (fior (n))
+ __builtin_abort ();
+
+ p[0] = 1;
+ for (int n = 1; n < 77; ++n)
+ if (!fior (n))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-3.c
new file mode 100644
index 0000000..d1a286b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-3.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+int p[128];
+
+bool __attribute__((noipa))
+fand ()
+{
+ bool r = true;
+ for (int i = 0; i < 16; ++i)
+ r &= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fior ()
+{
+ bool r = false;
+ for (int i = 0; i < 16; ++i)
+ r |= (p[i] != 0);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" } } */
+/* { dg-final { scan-assembler-times {vcpop\.m\s+[atx][0-9]+,\s*v[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-4-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-4-run.c
new file mode 100644
index 0000000..b55925e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-4-run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+
+long long p[128];
+
+bool __attribute__((noipa))
+fand (int n)
+{
+ bool r = true;
+ for (int i = 0; i < n; ++i)
+ r &= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fior (int n)
+{
+ bool r = false;
+ for (int i = 0; i < n; ++i)
+ r |= (p[i] != 0);
+ return r;
+}
+
+int main()
+{
+ __builtin_memset (p, 1, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (!fand (n))
+ __builtin_abort ();
+
+ p[0] = 0;
+ for (int n = 1; n < 77; ++n)
+ if (fand (n))
+ __builtin_abort ();
+
+ __builtin_memset (p, 0, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (fior (n))
+ __builtin_abort ();
+
+ p[0] = 1;
+ for (int n = 1; n < 77; ++n)
+ if (!fior (n))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-4.c
new file mode 100644
index 0000000..34a44b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-4.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+long long p[128];
+
+bool __attribute__((noipa))
+fand ()
+{
+ bool r = true;
+ for (int i = 0; i < 16; ++i)
+ r &= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fior ()
+{
+ bool r = false;
+ for (int i = 0; i < 16; ++i)
+ r |= (p[i] != 0);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" } } */
+/* { dg-final { scan-assembler-times {vcpop\.m\s+[atx][0-9]+,\s*v[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-5-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-5-run.c
new file mode 100644
index 0000000..95570ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-5-run.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+
+char p[128];
+
+bool __attribute__((noipa))
+fxort (int n)
+{
+ bool r = true;
+ for (int i = 0; i < n; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fxorf (int n)
+{
+ bool r = false;
+ for (int i = 0; i < n; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+int main()
+{
+ __builtin_memset (p, 1, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (fxort (n) != !(n & 1))
+ __builtin_abort ();
+
+ for (int n = 0; n < 77; ++n)
+ if (fxorf (n) != (n & 1))
+ __builtin_abort ();
+
+ __builtin_memset (p, 0, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (!fxort (n))
+ __builtin_abort ();
+
+ for (int n = 0; n < 77; ++n)
+ if (fxorf (n))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-5.c
new file mode 100644
index 0000000..f179970
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-5.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+char p[128];
+
+bool __attribute__((noipa))
+fxort ()
+{
+ bool r = true;
+ for (int i = 0; i < 16; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fxorf ()
+{
+ bool r = false;
+ for (int i = 0; i < 16; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" } } */
+/* { dg-final { scan-assembler-times {vcpop\.m\s+[atx][0-9]+,\s*v[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-6-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-6-run.c
new file mode 100644
index 0000000..267485b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-6-run.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+
+short p[128];
+
+bool __attribute__((noipa))
+fxort (int n)
+{
+ bool r = true;
+ for (int i = 0; i < n; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fxorf (int n)
+{
+ bool r = false;
+ for (int i = 0; i < n; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+int main()
+{
+ __builtin_memset (p, 1, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (fxort (n) != !(n & 1))
+ __builtin_abort ();
+
+ for (int n = 0; n < 77; ++n)
+ if (fxorf (n) != (n & 1))
+ __builtin_abort ();
+
+ __builtin_memset (p, 0, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (!fxort (n))
+ __builtin_abort ();
+
+ for (int n = 0; n < 77; ++n)
+ if (fxorf (n))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-6.c
new file mode 100644
index 0000000..8486c6b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-6.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+short p[128];
+
+bool __attribute__((noipa))
+fxort ()
+{
+ bool r = true;
+ for (int i = 0; i < 16; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fxorf ()
+{
+ bool r = false;
+ for (int i = 0; i < 16; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" } } */
+/* { dg-final { scan-assembler-times {vcpop\.m\s+[atx][0-9]+,\s*v[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-7-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-7-run.c
new file mode 100644
index 0000000..242147b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-7-run.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+
+int p[128];
+
+bool __attribute__((noipa))
+fxort (int n)
+{
+ bool r = true;
+ for (int i = 0; i < n; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fxorf (int n)
+{
+ bool r = false;
+ for (int i = 0; i < n; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+int main()
+{
+ __builtin_memset (p, 1, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (fxort (n) != !(n & 1))
+ __builtin_abort ();
+
+ for (int n = 0; n < 77; ++n)
+ if (fxorf (n) != (n & 1))
+ __builtin_abort ();
+
+ __builtin_memset (p, 0, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (!fxort (n))
+ __builtin_abort ();
+
+ for (int n = 0; n < 77; ++n)
+ if (fxorf (n))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-7.c
new file mode 100644
index 0000000..cc14996
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-7.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+int p[128];
+
+bool __attribute__((noipa))
+fxort ()
+{
+ bool r = true;
+ for (int i = 0; i < 16; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fxorf ()
+{
+ bool r = false;
+ for (int i = 0; i < 16; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" } } */
+/* { dg-final { scan-assembler-times {vcpop\.m\s+[atx][0-9]+,\s*v[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-8-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-8-run.c
new file mode 100644
index 0000000..bf73da5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-8-run.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+
+long long p[128];
+
+bool __attribute__((noipa))
+fxort (int n)
+{
+ bool r = true;
+ for (int i = 0; i < n; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fxorf (int n)
+{
+ bool r = false;
+ for (int i = 0; i < n; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+int main()
+{
+ __builtin_memset (p, 1, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (fxort (n) != !(n & 1))
+ __builtin_abort ();
+
+ for (int n = 0; n < 77; ++n)
+ if (fxorf (n) != (n & 1))
+ __builtin_abort ();
+
+ __builtin_memset (p, 0, sizeof(p));
+
+ for (int n = 0; n < 77; ++n)
+ if (!fxort (n))
+ __builtin_abort ();
+
+ for (int n = 0; n < 77; ++n)
+ if (fxorf (n))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-8.c
new file mode 100644
index 0000000..6842f39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc-bool-8.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+long long p[128];
+
+bool __attribute__((noipa))
+fxort ()
+{
+ bool r = true;
+ for (int i = 0; i < 16; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+bool __attribute__((noipa))
+fxorf ()
+{
+ bool r = false;
+ for (int i = 0; i < 16; ++i)
+ r ^= (p[i] != 0);
+ return r;
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 2 "vect" } } */
+/* { dg-final { scan-assembler-times {vcpop\.m\s+[atx][0-9]+,\s*v[0-9]+} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
index 14a961d..1b7a0d8 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-times {vnmsub.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmseq.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmsne.vx} 1 } } */
+/* { dg-final { scan-assembler-times {vmslt.vx} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
index 738caa8..8e2c631 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-times {vnmsub.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmseq.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmsne.vx} 1 } } */
+/* { dg-final { scan-assembler-times {vmslt.vx} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
index 1e7a977..a16623e 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
@@ -32,3 +32,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-times {vnmsub.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmseq.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmsne.vx} 1 } } */
+/* { dg-final { scan-assembler-times {vmslt.vx} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
index 70257d3..be50b83 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-times {vnmsub.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmseq.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmsne.vx} 1 } } */
+/* { dg-final { scan-assembler-times {vmslt.vx} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
index bced156..fb50bae 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-not {vnmsub.vx} } } */
/* { dg-final { scan-assembler-not {vmseq.vx} } } */
/* { dg-final { scan-assembler-not {vmsne.vx} } } */
+/* { dg-final { scan-assembler-not {vmslt.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
index cfb52fb..d79e0e0 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-not {vnmsub.vx} } } */
/* { dg-final { scan-assembler-not {vmseq.vx} } } */
/* { dg-final { scan-assembler-not {vmsne.vx} } } */
+/* { dg-final { scan-assembler-not {vmslt.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
index 31846ef..6cdaf5d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-not {vnmsub.vx} } } */
/* { dg-final { scan-assembler-not {vmseq.vx} } } */
/* { dg-final { scan-assembler-not {vmsne.vx} } } */
+/* { dg-final { scan-assembler-not {vmslt.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
index ea28e2b..9e3879a 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-not {vnmsub.vx} } } */
/* { dg-final { scan-assembler-not {vmseq.vx} } } */
/* { dg-final { scan-assembler-not {vmsne.vx} } } */
+/* { dg-final { scan-assembler-not {vmslt.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
index e3cddc4..e3ef3e3 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-not {vnmsub.vx} } } */
/* { dg-final { scan-assembler-not {vmseq.vx} } } */
/* { dg-final { scan-assembler-not {vmsne.vx} } } */
+/* { dg-final { scan-assembler-not {vmslt.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
index c5cce62..20039c7 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
@@ -28,4 +28,5 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-not {vmadd.vx} } } */
/* { dg-final { scan-assembler-not {vnmsub.vx} } } */
/* { dg-final { scan-assembler-not {vmseq.vx} } } */
+/* { dg-final { scan-assembler-not {vmslt.vx} } } */
/* { dg-final { scan-assembler-not {vmsne.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
index 6ef8681..c973ea7 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-not {vnmsub.vx} } } */
/* { dg-final { scan-assembler-not {vmseq.vx} } } */
/* { dg-final { scan-assembler-not {vmsne.vx} } } */
+/* { dg-final { scan-assembler-not {vmslt.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
index cc78959..e781c62 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
@@ -29,3 +29,4 @@ TEST_TERNARY_VX_SIGNED_0(T)
/* { dg-final { scan-assembler-not {vnmsub.vx} } } */
/* { dg-final { scan-assembler-not {vmseq.vx} } } */
/* { dg-final { scan-assembler-not {vmsne.vx} } } */
+/* { dg-final { scan-assembler-not {vmslt.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h
index 764f301..a9bba40 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h
@@ -404,6 +404,7 @@ DEF_AVG_CEIL(int32_t, int64_t)
DEF_VX_BINARY_CASE_0_WRAP(T, %, rem) \
DEF_VX_BINARY_CASE_0_WRAP(T, ==, eq) \
DEF_VX_BINARY_CASE_0_WRAP(T, !=, ne) \
+ DEF_VX_BINARY_CASE_0_WRAP(T, <, lt) \
DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_0_WARP(T), max) \
DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_1_WARP(T), max) \
DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_0_WARP(T), min) \
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
index d4834c7..fad479a 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
@@ -6566,4 +6566,140 @@ uint64_t TEST_BINARY_DATA(uint64_t, ltu)[][3][N] =
},
};
+int8_t TEST_BINARY_DATA(int8_t, lt)[][3][N] =
+{
+ {
+ { 127 },
+ {
+ 0, 0, 0, 0,
+ -1, -1, -1, -1,
+ 127, 127, 127, 127,
+ -128, -128, -128, -128,
+ },
+ {
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ },
+ },
+ {
+ { -1 },
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -2, -2, -2, -2,
+ -128, -128, -128, -128,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ },
+ },
+};
+
+int16_t TEST_BINARY_DATA(int16_t, lt)[][3][N] =
+{
+ {
+ { 32767 },
+ {
+ 0, 0, 0, 0,
+ -1, -1, -1, -1,
+ 32767, 32767, 32767, 32767,
+ -32768, -32768, -32768, -32768,
+ },
+ {
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ },
+ },
+ {
+ { -1 },
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -2, -2, -2, -2,
+ -32768, -32768, -32768, -32768,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ },
+ },
+};
+
+int32_t TEST_BINARY_DATA(int32_t, lt)[][3][N] =
+{
+ {
+ { 2147483647 },
+ {
+ 0, 0, 0, 0,
+ -1, -1, -1, -1,
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ },
+ {
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ },
+ },
+ {
+ { -1 },
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -2, -2, -2, -2,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ },
+ },
+};
+
+int64_t TEST_BINARY_DATA(int64_t, lt)[][3][N] =
+{
+ {
+ { 9223372036854775807ll },
+ {
+ 0, 0, 0, 0,
+ -1, -1, -1, -1,
+ 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ },
+ {
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ },
+ },
+ {
+ { -1 },
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -2, -2, -2, -2,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ },
+ },
+};
+
#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i16.c
new file mode 100644
index 0000000..865a2f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i16.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+
+#include "vx_binary.h"
+#include "vx_binary_data.h"
+
+#define T int16_t
+#define NAME lt
+
+DEF_VX_BINARY_CASE_0_WRAP(T, <, NAME)
+
+#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VX_BINARY_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vx_binary_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i32.c
new file mode 100644
index 0000000..eeb2a66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i32.c
@@ -0,0 +1,16 @@
+
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+
+#include "vx_binary.h"
+#include "vx_binary_data.h"
+
+#define T int32_t
+#define NAME lt
+
+DEF_VX_BINARY_CASE_0_WRAP(T, <, NAME)
+
+#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VX_BINARY_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vx_binary_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i64.c
new file mode 100644
index 0000000..c3a2052
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i64.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+
+#include "vx_binary.h"
+#include "vx_binary_data.h"
+
+#define T int64_t
+#define NAME lt
+
+DEF_VX_BINARY_CASE_0_WRAP(T, <, NAME)
+
+#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VX_BINARY_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vx_binary_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i8.c
new file mode 100644
index 0000000..92a84f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vmslt-run-1-i8.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+
+#include "vx_binary.h"
+#include "vx_binary_data.h"
+
+#define T int8_t
+#define NAME lt
+
+DEF_VX_BINARY_CASE_0_WRAP(T, <, NAME)
+
+#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VX_BINARY_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vx_binary_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
index 877cc55..e128b17 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
+++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
@@ -47,7 +47,7 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/xandesvector/*.\[cS\]]] \
"" $CFLAGS
gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vsetvl/*.\[cS\]]] \
"" $CFLAGS
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/*.\[cS\]]] \
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/*.\[cCS\]]] \
"-O3 -ftree-vectorize" $CFLAGS
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/vls/*.\[cS\]]] \
"-O3 -ftree-vectorize -mrvv-vector-bits=scalable" $CFLAGS
diff --git a/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90 b/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90
index 04f0b9f..2e0e77c 100644
--- a/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90
@@ -1,4 +1,5 @@
! { dg-do compile }
+! { dg-options " " }
! Test the fix for PR fortran/39893.
! Original testcase provided by Deji Akingunola.
! Reduced testcase provided by Dominique d'Humieres.
diff --git a/gcc/testsuite/gfortran.dg/automatic_char_len_1.f90 b/gcc/testsuite/gfortran.dg/automatic_char_len_1.f90
index 3ccfcb7..7f102b7 100644
--- a/gcc/testsuite/gfortran.dg/automatic_char_len_1.f90
+++ b/gcc/testsuite/gfortran.dg/automatic_char_len_1.f90
@@ -1,4 +1,5 @@
! { dg-do compile }
+! { dg-options " " }
! PR18082 - Compiler would get stuck in loop, whilst treating
! the assignments.
! Test is one of PR cases.
diff --git a/gcc/testsuite/gfortran.dg/entry_23.f b/gcc/testsuite/gfortran.dg/entry_23.f
index ebc5f66..d10ea92 100644
--- a/gcc/testsuite/gfortran.dg/entry_23.f
+++ b/gcc/testsuite/gfortran.dg/entry_23.f
@@ -1,4 +1,5 @@
! { dg-do run }
+! { dg-options " " }
! PR 97799 - this used to segfault intermittently.
! Test case by George Hockney.
PROGRAM MAIN
diff --git a/gcc/testsuite/gfortran.dg/finalize_59.f90 b/gcc/testsuite/gfortran.dg/finalize_59.f90
index 8be5f71..e9e68d4 100644
--- a/gcc/testsuite/gfortran.dg/finalize_59.f90
+++ b/gcc/testsuite/gfortran.dg/finalize_59.f90
@@ -187,7 +187,7 @@ Program Cds_Principal
Type(Uef_Vector) :: Cds_Mod_Les_materiaux
Type (Cds_Materiau_Acier_EC) :: acier_ec
Class (Cds_Materiau), pointer :: pt_materiau
- Character *(8) :: nom_materiau
+ Character(len=8) :: nom_materiau
!-------------------------------------------------------------------------------------------------
CaLL Cds_Mod_Les_materiaux%Add (acier_ec)
nom_materiau = "12345678"
@@ -199,7 +199,7 @@ Function Get_Pt_Materiau_nom (vecteur, nom_materiau)
! Fonction :
!--------------------
! Parametres en entree
- Character *(8), Intent (in) :: nom_materiau
+ Character(len=8), Intent (in) :: nom_materiau
Type (Uef_Vector) , Intent (inout) :: vecteur
! Parametres en sortie
diff --git a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f
index 0ce45de..2f03db1 100644
--- a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f
+++ b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f
@@ -1,4 +1,5 @@
c { dg-do run }
+c { dg-options " " }
c f90-intrinsic-bit.f
c
c Test Fortran 90
diff --git a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f
index d151fd0..f07336e 100644
--- a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f
+++ b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f
@@ -1,4 +1,5 @@
c { dg-do run }
+c { dg-options " " }
c f90-intrinsic-mathematical.f
c
c Test Fortran 90 intrinsic mathematical functions - Section 13.10.3 and
diff --git a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f
index c8d7c56..c01efe6 100644
--- a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f
+++ b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f
@@ -1,4 +1,5 @@
c { dg-do run }
+c { dg-options " " }
c f90-intrinsic-numeric.f
c
c Test Fortran 90 intrinsic numeric functions - Section 13.10.2 and 13.13
diff --git a/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f b/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f
index b388806..406a8e4 100644
--- a/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f
+++ b/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f
@@ -1,4 +1,5 @@
c { dg-do run }
+c { dg-options " " }
c intrinsic-unix-bessel.f
c
c Test Bessel function intrinsics.
diff --git a/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f b/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f
index 250519a..6ed9590 100644
--- a/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f
+++ b/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f
@@ -1,4 +1,5 @@
c { dg-do run }
+c { dg-options " " }
c intrinsic-unix-erf.f
c
c Test Bessel function intrinsics.
diff --git a/gcc/testsuite/gfortran.dg/initialization_9.f90 b/gcc/testsuite/gfortran.dg/initialization_9.f90
index d904047..fe7ca63 100644
--- a/gcc/testsuite/gfortran.dg/initialization_9.f90
+++ b/gcc/testsuite/gfortran.dg/initialization_9.f90
@@ -1,4 +1,5 @@
! { dg-do compile }
+! { dg-options " " }
!
! PR fortran/31639
! Contributed by Martin Michlmayr <tbm AT cyrius DOT com>
diff --git a/gcc/testsuite/gfortran.dg/intrinsic_actual_4.f90 b/gcc/testsuite/gfortran.dg/intrinsic_actual_4.f90
index 4521c96..3358b4a 100644
--- a/gcc/testsuite/gfortran.dg/intrinsic_actual_4.f90
+++ b/gcc/testsuite/gfortran.dg/intrinsic_actual_4.f90
@@ -1,4 +1,5 @@
! { dg-do run }
+! { dg-options " " }
! Tests the fix for PR27900, in which an ICE would be caused because
! the actual argument LEN had no type.
!
diff --git a/gcc/testsuite/gfortran.dg/namelist_assumed_char.f90 b/gcc/testsuite/gfortran.dg/namelist_assumed_char.f90
index b7d063c..25edf64 100644
--- a/gcc/testsuite/gfortran.dg/namelist_assumed_char.f90
+++ b/gcc/testsuite/gfortran.dg/namelist_assumed_char.f90
@@ -8,7 +8,7 @@
! Add -std=f95, add bar()
!
subroutine foo(c)
- character*(*) c
+ character*(*) c ! { dg-warning "Old-style character length" }
namelist /abc/ c ! { dg-error "nonconstant character length in namelist" }
end subroutine
diff --git a/gcc/testsuite/gfortran.dg/pr15140.f90 b/gcc/testsuite/gfortran.dg/pr15140.f90
index 80c08dd..7f9af4f 100644
--- a/gcc/testsuite/gfortran.dg/pr15140.f90
+++ b/gcc/testsuite/gfortran.dg/pr15140.f90
@@ -1,4 +1,5 @@
! { dg-do run }
+! { dg-options "-std=legacy" }
! PR 15140: we used to fail an assertion, because we don't use the
! argument of the subroutine directly, but instead use a copy of it.
function M(NAMES)
diff --git a/gcc/testsuite/gnat.dg/reduce3.adb b/gcc/testsuite/gnat.dg/reduce3.adb
new file mode 100644
index 0000000..55934d0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/reduce3.adb
@@ -0,0 +1,17 @@
+-- { dg-do run }
+-- { dg-options "-gnat2022" }
+
+with Ada.Containers.Vectors;
+
+procedure Reduce3 is
+
+ package Qs is new
+ Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Positive);
+
+ V : Qs.Vector;
+ Sum : Positive;
+
+begin
+ V.Append (1);
+ Sum := V'Reduce ("+", 0);
+end;
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index 1d20e6a..f0a5e05 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -10173,6 +10173,224 @@ make_pass_fixup_cfg (gcc::context *ctxt)
return new pass_fixup_cfg (ctxt);
}
+
+/* Sort PHI argument values for make_forwarders_with_degenerate_phis. */
+
+static int
+sort_phi_args (const void *a_, const void *b_)
+{
+ auto *a = (const std::pair<edge, hashval_t> *) a_;
+ auto *b = (const std::pair<edge, hashval_t> *) b_;
+ hashval_t ha = a->second;
+ hashval_t hb = b->second;
+ if (ha < hb)
+ return -1;
+ else if (ha > hb)
+ return 1;
+ else if (a->first->dest_idx < b->first->dest_idx)
+ return -1;
+ else if (a->first->dest_idx > b->first->dest_idx)
+ return 1;
+ else
+ return 0;
+}
+
+/* Look for a non-virtual PHIs and make a forwarder block when all PHIs
+ have the same argument on a set of edges. This is to not consider
+ control dependences of individual edges for same values but only for
+ the common set. Returns true if changed the CFG. */
+
+bool
+make_forwarders_with_degenerate_phis (function *fn)
+{
+ bool didsomething = false;
+
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, fn)
+ {
+ /* Only PHIs with three or more arguments have opportunities. */
+ if (EDGE_COUNT (bb->preds) < 3)
+ continue;
+ /* Do not touch loop headers or blocks with abnormal predecessors.
+ ??? This is to avoid creating valid loops here, see PR103458.
+ We might want to improve things to either explicitely add those
+ loops or at least consider blocks with no backedges. */
+ if (bb->loop_father->header == bb
+ || bb_has_abnormal_pred (bb))
+ continue;
+
+ /* Take one PHI node as template to look for identical
+ arguments. Build a vector of candidates forming sets
+ of argument edges with equal values. Note optimality
+ depends on the particular choice of the template PHI
+ since equal arguments are unordered leaving other PHIs
+ with more than one set of equal arguments within this
+ argument range unsorted. We'd have to break ties by
+ looking at other PHI nodes. */
+ gphi_iterator gsi = gsi_start_nonvirtual_phis (bb);
+ if (gsi_end_p (gsi))
+ continue;
+ gphi *phi = gsi.phi ();
+ auto_vec<std::pair<edge, hashval_t>, 8> args;
+ bool need_resort = false;
+ for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
+ {
+ edge e = gimple_phi_arg_edge (phi, i);
+ /* Skip abnormal edges since we cannot redirect them. */
+ if (e->flags & EDGE_ABNORMAL)
+ continue;
+ /* Skip loop exit edges when we are in loop-closed SSA form
+ since the forwarder we'd create does not have a PHI node. */
+ if (loops_state_satisfies_p (LOOP_CLOSED_SSA)
+ && loop_exit_edge_p (e->src->loop_father, e))
+ continue;
+
+ tree arg = gimple_phi_arg_def (phi, i);
+ if (!CONSTANT_CLASS_P (arg) && TREE_CODE (arg) != SSA_NAME)
+ need_resort = true;
+ args.safe_push (std::make_pair (e, iterative_hash_expr (arg, 0)));
+ }
+ if (args.length () < 2)
+ continue;
+ args.qsort (sort_phi_args);
+ /* The above sorting can be different between -g and -g0, as e.g. decls
+ can have different uids (-g could have bigger gaps in between them).
+ So, only use that to determine which args are equal, then change
+ second from hash value to smallest dest_idx of the edges which have
+ equal argument and sort again. If all the phi arguments are
+ constants or SSA_NAME, there is no need for the second sort, the hash
+ values are stable in that case. */
+ hashval_t hash = args[0].second;
+ args[0].second = args[0].first->dest_idx;
+ bool any_equal = false;
+ for (unsigned i = 1; i < args.length (); ++i)
+ if (hash == args[i].second
+ && operand_equal_p (PHI_ARG_DEF_FROM_EDGE (phi, args[i - 1].first),
+ PHI_ARG_DEF_FROM_EDGE (phi, args[i].first)))
+ {
+ args[i].second = args[i - 1].second;
+ any_equal = true;
+ }
+ else
+ {
+ hash = args[i].second;
+ args[i].second = args[i].first->dest_idx;
+ }
+ if (!any_equal)
+ continue;
+ if (need_resort)
+ args.qsort (sort_phi_args);
+
+ /* From the candidates vector now verify true candidates for
+ forwarders and create them. */
+ gphi *vphi = get_virtual_phi (bb);
+ unsigned start = 0;
+ while (start < args.length () - 1)
+ {
+ unsigned i;
+ for (i = start + 1; i < args.length (); ++i)
+ if (args[start].second != args[i].second)
+ break;
+ /* args[start]..args[i-1] are equal. */
+ if (start != i - 1)
+ {
+ /* Check all PHI nodes for argument equality
+ except for vops. */
+ bool equal = true;
+ gphi_iterator gsi2 = gsi;
+ gsi_next (&gsi2);
+ for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
+ {
+ gphi *phi2 = gsi2.phi ();
+ if (virtual_operand_p (gimple_phi_result (phi2)))
+ continue;
+ tree start_arg
+ = PHI_ARG_DEF_FROM_EDGE (phi2, args[start].first);
+ for (unsigned j = start + 1; j < i; ++j)
+ {
+ if (!operand_equal_p (start_arg,
+ PHI_ARG_DEF_FROM_EDGE
+ (phi2, args[j].first)))
+ {
+ /* Another PHI might have a shorter set of
+ equivalent args. Go for that. */
+ i = j;
+ if (j == start + 1)
+ equal = false;
+ break;
+ }
+ }
+ if (!equal)
+ break;
+ }
+ if (equal)
+ {
+ /* If we are asked to forward all edges the block
+ has all degenerate PHIs. Do nothing in that case. */
+ if (start == 0
+ && i == args.length ()
+ && args.length () == gimple_phi_num_args (phi))
+ break;
+ /* Instead of using make_forwarder_block we are
+ rolling our own variant knowing that the forwarder
+ does not need PHI nodes apart from eventually
+ a virtual one. */
+ auto_vec<tree, 8> vphi_args;
+ if (vphi)
+ {
+ vphi_args.reserve_exact (i - start);
+ for (unsigned j = start; j < i; ++j)
+ vphi_args.quick_push
+ (PHI_ARG_DEF_FROM_EDGE (vphi, args[j].first));
+ }
+ free_dominance_info (fn, CDI_DOMINATORS);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "New forwarder block for edge ");
+ fprintf (dump_file, "%d -> %d.\n",
+ args[start].first->src->index,
+ args[start].first->dest->index);
+ }
+ basic_block forwarder = split_edge (args[start].first);
+ profile_count count = profile_count::zero ();
+ bool irr = false;
+ for (unsigned j = start + 1; j < i; ++j)
+ {
+ edge e = args[j].first;
+ if (e->flags & EDGE_IRREDUCIBLE_LOOP)
+ irr = true;
+ redirect_edge_and_branch_force (e, forwarder);
+ redirect_edge_var_map_clear (e);
+ count += e->count ();
+ }
+ forwarder->count = count;
+ if (irr)
+ {
+ forwarder->flags |= BB_IRREDUCIBLE_LOOP;
+ single_succ_edge (forwarder)->flags
+ |= EDGE_IRREDUCIBLE_LOOP;
+ }
+
+ if (vphi)
+ {
+ tree def = copy_ssa_name (vphi_args[0]);
+ gphi *vphi_copy = create_phi_node (def, forwarder);
+ for (unsigned j = start; j < i; ++j)
+ add_phi_arg (vphi_copy, vphi_args[j - start],
+ args[j].first, UNKNOWN_LOCATION);
+ SET_PHI_ARG_DEF
+ (vphi, single_succ_edge (forwarder)->dest_idx, def);
+ }
+ didsomething = true;
+ }
+ }
+ /* Continue searching for more opportunities. */
+ start = i;
+ }
+ }
+ return didsomething;
+}
+
/* Garbage collection support for edge_def. */
extern void gt_ggc_mx (tree&);
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index 520bb3a..2e01762 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -114,6 +114,7 @@ extern edge gimple_switch_edge (function *, gswitch *, unsigned);
extern edge gimple_switch_default_edge (function *, gswitch *);
extern bool cond_only_block_p (basic_block);
extern void copy_phi_arg_into_existing_phi (edge, edge, bool = false);
+extern bool make_forwarders_with_degenerate_phis (function *);
/* Return true if the LHS of a call should be removed. */
diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc
index 872ded3..093fde9 100644
--- a/gcc/tree-cfgcleanup.cc
+++ b/gcc/tree-cfgcleanup.cc
@@ -1415,8 +1415,13 @@ execute_cleanup_cfg_post_optimizing (void)
}
maybe_remove_unreachable_handlers ();
cleanup_dead_labels ();
- if (group_case_labels ())
- todo |= TODO_cleanup_cfg;
+ if (group_case_labels () && cleanup_tree_cfg ())
+ todo |= TODO_update_ssa;
+
+ /* When optimizing undo the merging of forwarder blocks
+ that phis for better out of ssa expansion. */
+ if (optimize)
+ make_forwarders_with_degenerate_phis (cfun);
basic_block bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (bb);
diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
index 317a0d6..9a9f6f9 100644
--- a/gcc/tree-ssa-dce.cc
+++ b/gcc/tree-ssa-dce.cc
@@ -1940,214 +1940,6 @@ tree_dce_done (bool aggressive)
worklist.release ();
}
-/* Sort PHI argument values for make_forwarders_with_degenerate_phis. */
-
-static int
-sort_phi_args (const void *a_, const void *b_)
-{
- auto *a = (const std::pair<edge, hashval_t> *) a_;
- auto *b = (const std::pair<edge, hashval_t> *) b_;
- hashval_t ha = a->second;
- hashval_t hb = b->second;
- if (ha < hb)
- return -1;
- else if (ha > hb)
- return 1;
- else if (a->first->dest_idx < b->first->dest_idx)
- return -1;
- else if (a->first->dest_idx > b->first->dest_idx)
- return 1;
- else
- return 0;
-}
-
-/* Look for a non-virtual PHIs and make a forwarder block when all PHIs
- have the same argument on a set of edges. This is to not consider
- control dependences of individual edges for same values but only for
- the common set. */
-
-static unsigned
-make_forwarders_with_degenerate_phis (function *fn)
-{
- unsigned todo = 0;
-
- basic_block bb;
- FOR_EACH_BB_FN (bb, fn)
- {
- /* Only PHIs with three or more arguments have opportunities. */
- if (EDGE_COUNT (bb->preds) < 3)
- continue;
- /* Do not touch loop headers or blocks with abnormal predecessors.
- ??? This is to avoid creating valid loops here, see PR103458.
- We might want to improve things to either explicitely add those
- loops or at least consider blocks with no backedges. */
- if (bb->loop_father->header == bb
- || bb_has_abnormal_pred (bb))
- continue;
-
- /* Take one PHI node as template to look for identical
- arguments. Build a vector of candidates forming sets
- of argument edges with equal values. Note optimality
- depends on the particular choice of the template PHI
- since equal arguments are unordered leaving other PHIs
- with more than one set of equal arguments within this
- argument range unsorted. We'd have to break ties by
- looking at other PHI nodes. */
- gphi_iterator gsi = gsi_start_nonvirtual_phis (bb);
- if (gsi_end_p (gsi))
- continue;
- gphi *phi = gsi.phi ();
- auto_vec<std::pair<edge, hashval_t>, 8> args;
- bool need_resort = false;
- for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
- {
- edge e = gimple_phi_arg_edge (phi, i);
- /* Skip abnormal edges since we cannot redirect them. */
- if (e->flags & EDGE_ABNORMAL)
- continue;
- /* Skip loop exit edges when we are in loop-closed SSA form
- since the forwarder we'd create does not have a PHI node. */
- if (loops_state_satisfies_p (LOOP_CLOSED_SSA)
- && loop_exit_edge_p (e->src->loop_father, e))
- continue;
-
- tree arg = gimple_phi_arg_def (phi, i);
- if (!CONSTANT_CLASS_P (arg) && TREE_CODE (arg) != SSA_NAME)
- need_resort = true;
- args.safe_push (std::make_pair (e, iterative_hash_expr (arg, 0)));
- }
- if (args.length () < 2)
- continue;
- args.qsort (sort_phi_args);
- /* The above sorting can be different between -g and -g0, as e.g. decls
- can have different uids (-g could have bigger gaps in between them).
- So, only use that to determine which args are equal, then change
- second from hash value to smallest dest_idx of the edges which have
- equal argument and sort again. If all the phi arguments are
- constants or SSA_NAME, there is no need for the second sort, the hash
- values are stable in that case. */
- hashval_t hash = args[0].second;
- args[0].second = args[0].first->dest_idx;
- bool any_equal = false;
- for (unsigned i = 1; i < args.length (); ++i)
- if (hash == args[i].second
- && operand_equal_p (PHI_ARG_DEF_FROM_EDGE (phi, args[i - 1].first),
- PHI_ARG_DEF_FROM_EDGE (phi, args[i].first)))
- {
- args[i].second = args[i - 1].second;
- any_equal = true;
- }
- else
- {
- hash = args[i].second;
- args[i].second = args[i].first->dest_idx;
- }
- if (!any_equal)
- continue;
- if (need_resort)
- args.qsort (sort_phi_args);
-
- /* From the candidates vector now verify true candidates for
- forwarders and create them. */
- gphi *vphi = get_virtual_phi (bb);
- unsigned start = 0;
- while (start < args.length () - 1)
- {
- unsigned i;
- for (i = start + 1; i < args.length (); ++i)
- if (args[start].second != args[i].second)
- break;
- /* args[start]..args[i-1] are equal. */
- if (start != i - 1)
- {
- /* Check all PHI nodes for argument equality. */
- bool equal = true;
- gphi_iterator gsi2 = gsi;
- gsi_next (&gsi2);
- for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
- {
- gphi *phi2 = gsi2.phi ();
- if (virtual_operand_p (gimple_phi_result (phi2)))
- continue;
- tree start_arg
- = PHI_ARG_DEF_FROM_EDGE (phi2, args[start].first);
- for (unsigned j = start + 1; j < i; ++j)
- {
- if (!operand_equal_p (start_arg,
- PHI_ARG_DEF_FROM_EDGE
- (phi2, args[j].first)))
- {
- /* Another PHI might have a shorter set of
- equivalent args. Go for that. */
- i = j;
- if (j == start + 1)
- equal = false;
- break;
- }
- }
- if (!equal)
- break;
- }
- if (equal)
- {
- /* If we are asked to forward all edges the block
- has all degenerate PHIs. Do nothing in that case. */
- if (start == 0
- && i == args.length ()
- && args.length () == gimple_phi_num_args (phi))
- break;
- /* Instead of using make_forwarder_block we are
- rolling our own variant knowing that the forwarder
- does not need PHI nodes apart from eventually
- a virtual one. */
- auto_vec<tree, 8> vphi_args;
- if (vphi)
- {
- vphi_args.reserve_exact (i - start);
- for (unsigned j = start; j < i; ++j)
- vphi_args.quick_push
- (PHI_ARG_DEF_FROM_EDGE (vphi, args[j].first));
- }
- free_dominance_info (fn, CDI_DOMINATORS);
- basic_block forwarder = split_edge (args[start].first);
- profile_count count = profile_count::zero ();
- bool irr = false;
- for (unsigned j = start + 1; j < i; ++j)
- {
- edge e = args[j].first;
- if (e->flags & EDGE_IRREDUCIBLE_LOOP)
- irr = true;
- redirect_edge_and_branch_force (e, forwarder);
- redirect_edge_var_map_clear (e);
- count += e->count ();
- }
- forwarder->count = count;
- if (irr)
- {
- forwarder->flags |= BB_IRREDUCIBLE_LOOP;
- single_succ_edge (forwarder)->flags
- |= EDGE_IRREDUCIBLE_LOOP;
- }
-
- if (vphi)
- {
- tree def = copy_ssa_name (vphi_args[0]);
- gphi *vphi_copy = create_phi_node (def, forwarder);
- for (unsigned j = start; j < i; ++j)
- add_phi_arg (vphi_copy, vphi_args[j - start],
- args[j].first, UNKNOWN_LOCATION);
- SET_PHI_ARG_DEF
- (vphi, single_succ_edge (forwarder)->dest_idx, def);
- }
- todo |= TODO_cleanup_cfg;
- }
- }
- /* Continue searching for more opportunities. */
- start = i;
- }
- }
- return todo;
-}
/* Main routine to eliminate dead code.
@@ -2174,8 +1966,8 @@ perform_tree_ssa_dce (bool aggressive)
scev_initialize ();
}
- if (aggressive)
- todo |= make_forwarders_with_degenerate_phis (cfun);
+ if (aggressive && make_forwarders_with_degenerate_phis (cfun))
+ todo |= TODO_cleanup_cfg;
calculate_dominance_info (CDI_DOMINATORS);
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 09f92b2..0c519cf 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -2527,7 +2527,10 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert,
else
{
tree val = vn_lookup_simplify_result (res_op);
- if (!val && insert)
+ /* ??? In weird cases we can end up with internal-fn calls,
+ but this isn't expected so throw the result away. See
+ PR123040 for an example. */
+ if (!val && insert && res_op->code.is_tree_code ())
{
gimple_seq stmts = NULL;
result = maybe_push_res_to_seq (res_op, &stmts);
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 53923c0..f9dd88e 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -2682,6 +2682,7 @@ again:
= saved_can_use_partial_vectors_p;
LOOP_VINFO_MUST_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo) = false;
+ LOOP_VINFO_USING_SELECT_VL_P (loop_vinfo) = false;
if (loop_vinfo->scan_map)
loop_vinfo->scan_map->empty ();
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index 555986b..af64cb8 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -1914,6 +1914,9 @@ vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
&& val_new == prec)
|| (ifnnew == IFN_POPCOUNT && ifn == IFN_CTZ))
{
+ if (vect_is_reduction (stmt_vinfo))
+ return NULL;
+
/* .CTZ (X) = PREC - .CLZ ((X - 1) & ~X)
.CTZ (X) = .POPCOUNT ((X - 1) & ~X). */
if (ifnnew == IFN_CLZ)
@@ -1952,6 +1955,9 @@ vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
}
else if (ifnnew == IFN_CLZ)
{
+ if (vect_is_reduction (stmt_vinfo))
+ return NULL;
+
/* .CTZ (X) = (PREC - 1) - .CLZ (X & -X)
.FFS (X) = PREC - .CLZ (X & -X). */
sub = prec - (ifn == IFN_CTZ);
@@ -1971,6 +1977,9 @@ vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
}
else if (ifnnew == IFN_POPCOUNT)
{
+ if (vect_is_reduction (stmt_vinfo))
+ return NULL;
+
/* .CTZ (X) = PREC - .POPCOUNT (X | -X)
.FFS (X) = (PREC + 1) - .POPCOUNT (X | -X). */
sub = prec + (ifn == IFN_FFS);
@@ -1993,6 +2002,11 @@ vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
/* .FFS (X) = .CTZ (X) + 1. */
add = 1;
val_cmp++;
+
+ if (vect_is_reduction (stmt_vinfo)
+ && defined_at_zero
+ && (!defined_at_zero_new || val != val_cmp))
+ return NULL;
}
/* Create B = .IFNNEW (A). */
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index dc155dc..56ff1c8 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -9920,36 +9920,35 @@ vectorizable_load (vec_info *vinfo,
bool hoist_p = (LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo)
&& !nested_in_vect_loop);
- /* It is unsafe to hoist a conditional load over the conditions that make
- it valid. When early break this means that any invariant load can't be
- hoisted unless it's in the loop header or if we know something else has
- verified the load is valid to do. Alignment peeling would do this
- since getting through the prologue means the load was done at least
- once and so the vector main body is free to hoist it. However today
- GCC will hoist the load above the PFA loop. As such that makes it
- still invalid and so we can't allow it today. */
- auto stmt_bb
- = gimple_bb (STMT_VINFO_STMT (
- vect_orig_stmt (SLP_TREE_SCALAR_STMTS (slp_node)[0])));
- if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo)
- && !DR_SCALAR_KNOWN_BOUNDS (dr_info)
- && stmt_bb != loop->header)
- {
- if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)
- && dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ bool uniform_p = true;
+ for (stmt_vec_info sinfo : SLP_TREE_SCALAR_STMTS (slp_node))
+ {
+ /* It is unsafe to hoist a conditional load over the conditions that
+ make it valid. When early break this means that any invariant load
+ can't be hoisted unless it's in the loop header or if we know
+ something else has verified the load is valid to do. Alignment
+ peeling would do this since getting through the prologue means the
+ load was done at least once and so the vector main body is free to
+ hoist it. However today GCC will hoist the load above the PFA
+ loop. As such that makes it still invalid and so we can't allow it
+ today. */
+ if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo)
+ && !DR_SCALAR_KNOWN_BOUNDS (STMT_VINFO_DR_INFO (sinfo))
+ && gimple_bb (STMT_VINFO_STMT (vect_orig_stmt (sinfo)))
+ != loop->header)
+ {
+ if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)
+ && dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not hoisting invariant load due to early break"
"constraints\n");
- else if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
+ else if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
"not hoisting invariant load due to early break"
"constraints\n");
- hoist_p = false;
- }
+ hoist_p = false;
+ }
- bool uniform_p = true;
- for (stmt_vec_info sinfo : SLP_TREE_SCALAR_STMTS (slp_node))
- {
hoist_p = hoist_p && hoist_defs_of_uses (sinfo->stmt, loop, false);
if (sinfo != SLP_TREE_SCALAR_STMTS (slp_node)[0])
uniform_p = false;
@@ -11393,10 +11392,18 @@ vectorizable_load (vec_info *vinfo,
{
tree ptr = build_int_cst (ref_type, align * BITS_PER_UNIT);
gcall *call;
+
+ /* Need conversion if the vectype is punned by VnQI. */
+ els_vectype = vectype;
+ if (vmode != new_vmode)
+ els_vectype
+ = build_vector_type_for_mode (unsigned_intQI_type_node,
+ new_vmode);
+ vec_els = vect_get_mask_load_else (maskload_elsval,
+ els_vectype);
+
if (partial_ifn == IFN_MASK_LEN_LOAD)
{
- vec_els = vect_get_mask_load_else (maskload_elsval,
- vectype);
if (type_mode_padding_p
&& maskload_elsval != MASK_LOAD_ELSE_ZERO)
need_zeroing = true;
@@ -11406,9 +11413,10 @@ vectorizable_load (vec_info *vinfo,
final_len, bias);
}
else
- call = gimple_build_call_internal (IFN_LEN_LOAD, 4,
+ call = gimple_build_call_internal (IFN_LEN_LOAD, 5,
dataref_ptr, ptr,
- final_len, bias);
+ vec_els, final_len,
+ bias);
gimple_call_set_nothrow (call, true);
new_stmt = call;
data_ref = NULL_TREE;
diff --git a/libatomic/Makefile.in b/libatomic/Makefile.in
index 95f9c72..c9e53e1 100644
--- a/libatomic/Makefile.in
+++ b/libatomic/Makefile.in
@@ -108,6 +108,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/clang-plugin.m4 \
$(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/gcc-plugin.m4 \
+ $(top_srcdir)/../config/gthr.m4 \
$(top_srcdir)/../config/lead-dot.m4 \
$(top_srcdir)/../config/lthostflags.m4 \
$(top_srcdir)/../config/multi.m4 \
@@ -171,7 +172,7 @@ libatomic_la_OBJECTS = $(am_libatomic_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
-am__v_lt_1 =
+am__v_lt_1 =
libatomic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libatomic_la_LDFLAGS) $(LDFLAGS) -o $@
@@ -192,11 +193,11 @@ am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
+am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
-am__v_at_1 =
+am__v_at_1 =
depcomp = $(SHELL) $(top_srcdir)/../depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -209,7 +210,7 @@ LTCPPASCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
AM_V_CPPAS = $(am__v_CPPAS_@AM_V@)
am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@)
am__v_CPPAS_0 = @echo " CPPAS " $@;
-am__v_CPPAS_1 =
+am__v_CPPAS_1 =
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -219,7 +220,7 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
-am__v_CC_1 =
+am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -227,7 +228,7 @@ LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
-am__v_CCLD_1 =
+am__v_CCLD_1 =
SOURCES = $(libatomic_la_SOURCES) $(EXTRA_libatomic_la_SOURCES) \
$(libatomic_convenience_la_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
@@ -422,10 +423,10 @@ AM_CCASFLAGS = $(XCFLAGS)
AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS)
toolexeclib_LTLIBRARIES = libatomic.la
noinst_LTLIBRARIES = libatomic_convenience.la
-@LIBAT_BUILD_VERSIONED_SHLIB_FALSE@libatomic_version_script =
+@LIBAT_BUILD_VERSIONED_SHLIB_FALSE@libatomic_version_script =
@LIBAT_BUILD_VERSIONED_SHLIB_GNU_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libatomic_version_script = -Wl,--version-script,$(top_srcdir)/libatomic.map
@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libatomic_version_script = -Wl,-M,libatomic.map-sun
-@LIBAT_BUILD_VERSIONED_SHLIB_FALSE@libatomic_version_dep =
+@LIBAT_BUILD_VERSIONED_SHLIB_FALSE@libatomic_version_dep =
@LIBAT_BUILD_VERSIONED_SHLIB_GNU_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libatomic_version_dep = $(top_srcdir)/libatomic.map
@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libatomic_version_dep = libatomic.map-sun
libatomic_version_info = -version-info $(libtool_VERSION)
@@ -443,7 +444,7 @@ libatomic_la_LDFLAGS = $(libatomic_version_info) $(libatomic_version_script) \
@PARTIAL_VXWORKS_FALSE@SIZEOBJS = load store cas exch fadd fsub fand fior fxor fnand tas
@PARTIAL_VXWORKS_FALSE@EXTRA_libatomic_la_SOURCES = $(addsuffix _n.c,$(SIZEOBJS))
@PARTIAL_VXWORKS_FALSE@libatomic_la_DEPENDENCIES = $(libatomic_la_LIBADD) $(libatomic_version_dep)
-@PARTIAL_VXWORKS_FALSE@empty =
+@PARTIAL_VXWORKS_FALSE@empty =
@PARTIAL_VXWORKS_FALSE@space = $(empty) $(empty)
@PARTIAL_VXWORKS_FALSE@PAT_SPLIT = $(subst _,$(space),$(*F))
@PARTIAL_VXWORKS_FALSE@PAT_BASE = $(word 1,$(PAT_SPLIT))
@@ -452,7 +453,7 @@ libatomic_la_LDFLAGS = $(libatomic_version_info) $(libatomic_version_script) \
@PARTIAL_VXWORKS_FALSE@IFUNC_DEF = -DIFUNC_ALT=$(PAT_S)
@PARTIAL_VXWORKS_FALSE@IFUNC_OPT = $(subst |,$(space),$(word $(PAT_S),$(IFUNC_OPTIONS)))
@PARTIAL_VXWORKS_FALSE@@AMDEP_TRUE@M_DEPS = -MT $@ -MD -MP -MF $(DEPDIR)/$(@F).Ppo
-@PARTIAL_VXWORKS_FALSE@@AMDEP_FALSE@M_DEPS =
+@PARTIAL_VXWORKS_FALSE@@AMDEP_FALSE@M_DEPS =
@PARTIAL_VXWORKS_FALSE@M_SIZE = -DN=$(PAT_N)
@PARTIAL_VXWORKS_FALSE@M_IFUNC = $(if $(PAT_S),$(IFUNC_DEF) $(IFUNC_OPT))
@PARTIAL_VXWORKS_FALSE@M_FILE = $(PAT_BASE)_n.c
@@ -485,10 +486,10 @@ libatomic_convenience_la_LIBADD = $(libatomic_la_LIBADD)
# built after libatomic, which makes RPATH insecure. Removing libatomic.la
# from $gcc_objdir seems to fix the issue.
gcc_objdir = `pwd`/$(MULTIBUILDTOP)../../gcc/
-MULTISRCTOP =
-MULTIBUILDTOP =
-MULTIDIRS =
-MULTISUBDIR =
+MULTISRCTOP =
+MULTIBUILDTOP =
+MULTIDIRS =
+MULTISUBDIR =
MULTIDO = true
MULTICLEAN = true
all: auto-config.h
@@ -538,7 +539,7 @@ auto-config.h: stamp-h1
stamp-h1: $(srcdir)/auto-config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status auto-config.h
-$(srcdir)/auto-config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+$(srcdir)/auto-config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
@@ -592,10 +593,10 @@ clean-toolexeclibLTLIBRARIES:
rm -f $${locs}; \
}
-libatomic.la: $(libatomic_la_OBJECTS) $(libatomic_la_DEPENDENCIES) $(EXTRA_libatomic_la_DEPENDENCIES)
+libatomic.la: $(libatomic_la_OBJECTS) $(libatomic_la_DEPENDENCIES) $(EXTRA_libatomic_la_DEPENDENCIES)
$(AM_V_CCLD)$(libatomic_la_LINK) -rpath $(toolexeclibdir) $(libatomic_la_OBJECTS) $(libatomic_la_LIBADD) $(LIBS)
-libatomic_convenience.la: $(libatomic_convenience_la_OBJECTS) $(libatomic_convenience_la_DEPENDENCIES) $(EXTRA_libatomic_convenience_la_DEPENDENCIES)
+libatomic_convenience.la: $(libatomic_convenience_la_OBJECTS) $(libatomic_convenience_la_DEPENDENCIES) $(EXTRA_libatomic_convenience_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(libatomic_convenience_la_OBJECTS) $(libatomic_convenience_la_LIBADD) $(LIBS)
mostlyclean-compile:
diff --git a/libatomic/aclocal.m4 b/libatomic/aclocal.m4
index 91bff17..4d7c727 100644
--- a/libatomic/aclocal.m4
+++ b/libatomic/aclocal.m4
@@ -1191,6 +1191,7 @@ m4_include([../config/acx.m4])
m4_include([../config/clang-plugin.m4])
m4_include([../config/depstand.m4])
m4_include([../config/gcc-plugin.m4])
+m4_include([../config/gthr.m4])
m4_include([../config/lead-dot.m4])
m4_include([../config/lthostflags.m4])
m4_include([../config/multi.m4])
diff --git a/libatomic/configure b/libatomic/configure
index dd0f086..a6db78e 100755
--- a/libatomic/configure
+++ b/libatomic/configure
@@ -12254,11 +12254,28 @@ libtool_VERSION=3:0:2
# Check for used threading-model
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread model used by GCC" >&5
-$as_echo_n "checking for thread model used by GCC... " >&6; }
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $target_thread_file" >&5
-$as_echo "$target_thread_file" >&6; }
+
+# Specify the threading model for this GCC runtime library
+# Pass with no value to take from compiler's metadata
+# Pass with a value to specify a thread package
+# 'single' means single threaded -- without threads.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the threading model used by GCC" >&5
+$as_echo_n "checking for the threading model used by GCC... " >&6; }
+if ${gcc_cv_target_thread_file+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ # Set new cache variable
+ gcc_cv_target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_target_thread_file" >&5
+$as_echo "$gcc_cv_target_thread_file" >&6; }
+# Set variable name (not prefixed enough to be a good cache variable
+# name) traditionally used for this purpose, to avoid having to change
+# a bunch of configure scripts.
+target_thread_file="$gcc_cv_target_thread_file"
+
case "$target" in
*aarch64*)
diff --git a/libatomic/configure.ac b/libatomic/configure.ac
index 3da2f94..62c2a6b 100644
--- a/libatomic/configure.ac
+++ b/libatomic/configure.ac
@@ -177,9 +177,7 @@ libtool_VERSION=3:0:2
AC_SUBST(libtool_VERSION)
# Check for used threading-model
-AC_MSG_CHECKING([for thread model used by GCC])
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-AC_MSG_RESULT([$target_thread_file])
+GCC_AC_THREAD_MODEL
case "$target" in
*aarch64*)
diff --git a/libatomic/testsuite/Makefile.in b/libatomic/testsuite/Makefile.in
index f540a75..5d6872b0d 100644
--- a/libatomic/testsuite/Makefile.in
+++ b/libatomic/testsuite/Makefile.in
@@ -94,6 +94,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/clang-plugin.m4 \
$(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/gcc-plugin.m4 \
+ $(top_srcdir)/../config/gthr.m4 \
$(top_srcdir)/../config/lead-dot.m4 \
$(top_srcdir)/../config/lthostflags.m4 \
$(top_srcdir)/../config/multi.m4 \
@@ -120,11 +121,11 @@ am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
-am__v_GEN_1 =
+am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
-am__v_at_1 =
+am__v_at_1 =
SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 816b5c4..816983c 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,13 @@
+2025-12-07 Jason Merrill <jason@redhat.com>
+
+ * include/cpplib.h (cpp_get_path, cpp_get_dir): Remove.
+ (_cpp_get_file_path, _cpp_get_file_name, _cpp_get_file_stat)
+ (_cpp_get_file_dir): Move prototypes from...
+ * internal.h: ...here.
+ * files.cc (_cpp_get_file_path): Rename from...
+ (cpp_get_path): ...this.
+ (cpp_get_dir): Remove.
+
2025-11-10 Jakub Jelinek <jakub@redhat.com>
* directives.cc: Implement CWG3053.
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 32a5a15..f0cbcb8 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -298,6 +298,8 @@ override CFLAGS := $(filter-out -fprofile-generate -fprofile-use,$(CFLAGS))
INTERNAL_CFLAGS = $(CFLAGS) $(LIBGCC2_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
$(INCLUDES) @set_have_cc_tls@ @set_use_emutls@
+NO_PIE_CFLAGS = @NO_PIE_CFLAGS@
+
# Options to use when compiling crtbegin/end.
CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
$(NO_PIE_CFLAGS) -finhibit-size-directive -fno-inline -fno-exceptions \
diff --git a/libgcc/config/rs6000/t-slibgcc-aix b/libgcc/config/rs6000/t-slibgcc-aix
index 6333687..4a3d624 100644
--- a/libgcc/config/rs6000/t-slibgcc-aix
+++ b/libgcc/config/rs6000/t-slibgcc-aix
@@ -40,7 +40,9 @@ SHLIB_LINK = \
-Wl,-bE:@shlib_map_file@ -o shr.o \
@multilib_flags@ @shlib_objs@ -lc \
`case @multilib_dir@ in \
- *pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
+ *pthread*) \
+ TARGET_SYSTEM_ROOT=\`$(CC) -print-sysroot\`; \
+ echo -L$$TARGET_SYSTEM_ROOT/usr/lib/threads -lpthreads -lc_r $$TARGET_SYSTEM_ROOT/usr/lib/libc.a ;; \
*) echo -lc ;; esac` ; \
rm -f tmp-@shlib_base_name@.a ; \
$(AR_CREATE_FOR_TARGET) tmp-@shlib_base_name@.a shr.o ; \
@@ -53,7 +55,9 @@ SHLIB_LINK = \
-Wl,-bE:@shlib_map_file@ -o $$shr.o \
@multilib_flags@ @shlib_objs@ -lc \
`case @multilib_dir@ in \
- *pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
+ *pthread*) \
+ TARGET_SYSTEM_ROOT=\`$(CC) -print-sysroot\`; \
+ echo -L$$TARGET_SYSTEM_ROOT/usr/lib/threads -lpthreads -lc_r $$TARGET_SYSTEM_ROOT/usr/lib/libc.a ;; \
*) echo -lc ;; esac` ; \
$(STRIP_FOR_TARGET) -X32_64 -e $$shr.o ; \
{ echo "\#! $(SHLIB_SONAME)($$shr.o)" ; \
diff --git a/libgcc/configure b/libgcc/configure
index d5e80d2..fe7a21c2 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -610,6 +610,7 @@ accel_dir_suffix
use_tm_clone_registry
force_explicit_eh_registry
CET_FLAGS
+NO_PIE_CFLAGS
fixed_point
enable_decimal_float
decimal_float
@@ -4836,6 +4837,40 @@ $as_echo "$libgcc_cv_fixed_point" >&6; }
fixed_point=$libgcc_cv_fixed_point
+# Check whether the compiler defines __PIE__ by default, so -fno-PIE is needed.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler defines __PIE__" >&5
+$as_echo_n "checking whether the compiler defines __PIE__... " >&6; }
+if ${libgcc_cv_no_pie_cflags+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef __PIE__
+#error __PIE__ defined
+#endif
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libgcc_cv_no_pie_cflags=''
+else
+ libgcc_cv_no_pie_cflags='-fno-PIE'
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_no_pie_cflags" >&5
+$as_echo "$libgcc_cv_no_pie_cflags" >&6; }
+
+NO_PIE_CFLAGS=$libgcc_cv_no_pie_cflags
+
+
# For platforms with the unwind ABI which includes an unwind library,
# libunwind, we can choose to use the system libunwind.
# config.gcc also contains tests of with_system_libunwind.
@@ -5046,11 +5081,28 @@ $as_echo "$acl_cv_prog_gnu_ld" >&6; }
with_gnu_ld=$acl_cv_prog_gnu_ld
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread model used by GCC" >&5
-$as_echo_n "checking for thread model used by GCC... " >&6; }
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $target_thread_file" >&5
-$as_echo "$target_thread_file" >&6; }
+
+# Specify the threading model for this GCC runtime library
+# Pass with no value to take from compiler's metadata
+# Pass with a value to specify a thread package
+# 'single' means single threaded -- without threads.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the threading model used by GCC" >&5
+$as_echo_n "checking for the threading model used by GCC... " >&6; }
+if ${gcc_cv_target_thread_file+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ # Set new cache variable
+ gcc_cv_target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_target_thread_file" >&5
+$as_echo "$gcc_cv_target_thread_file" >&6; }
+# Set variable name (not prefixed enough to be a good cache variable
+# name) traditionally used for this purpose, to avoid having to change
+# a bunch of configure scripts.
+target_thread_file="$gcc_cv_target_thread_file"
+
# Check for assembler CFI support.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether assembler supports CFI directives" >&5
@@ -5737,6 +5789,9 @@ case $target_thread_file in
vxworks) thread_header=config/gthr-vxworks.h ;;
win32) thread_header=config/i386/gthr-win32.h ;;
mcf) thread_header=config/i386/gthr-mcf.h ;;
+ *)
+ as_fn_error $? "No known header for threading model '$target_thread_file'." "$LINENO" 5
+ ;;
esac
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 65cd3c6..5945243 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -258,6 +258,20 @@ AC_CACHE_CHECK([whether fixed-point is supported], [libgcc_cv_fixed_point],
fixed_point=$libgcc_cv_fixed_point
AC_SUBST(fixed_point)
+# Check whether the compiler defines __PIE__ by default, so -fno-PIE is needed.
+AC_CACHE_CHECK([whether the compiler defines __PIE__], [libgcc_cv_no_pie_cflags],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+#ifdef __PIE__
+#error __PIE__ defined
+#endif
+ ]], [[]])],
+ [libgcc_cv_no_pie_cflags=''],
+ [libgcc_cv_no_pie_cflags='-fno-PIE'])])
+
+NO_PIE_CFLAGS=$libgcc_cv_no_pie_cflags
+AC_SUBST([NO_PIE_CFLAGS])
+
# For platforms with the unwind ABI which includes an unwind library,
# libunwind, we can choose to use the system libunwind.
# config.gcc also contains tests of with_system_libunwind.
@@ -305,9 +319,7 @@ AC_SUBST([use_tm_clone_registry])
AC_LIB_PROG_LD_GNU
-AC_MSG_CHECKING([for thread model used by GCC])
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-AC_MSG_RESULT([$target_thread_file])
+GCC_AC_THREAD_MODEL
# Check for assembler CFI support.
AC_CACHE_CHECK([whether assembler supports CFI directives], [libgcc_cv_cfi],
diff --git a/libgomp/testsuite/lib/libgomp.exp b/libgomp/testsuite/lib/libgomp.exp
index 076b775..cce2e93 100644
--- a/libgomp/testsuite/lib/libgomp.exp
+++ b/libgomp/testsuite/lib/libgomp.exp
@@ -725,6 +725,29 @@ int main() {
} } "-lhipblas" ]
}
+# return 1 if OpenMP Unified Shared Memory is supported by offload devices
+
+proc check_effective_target_omp_usm { } {
+ if { [check_effective_target_offload_device_nvptx]
+ || [check_effective_target_offload_target_amdgcn] } {
+ if [check_runtime usm_available_ {
+ #include <omp.h>
+ #pragma omp requires unified_shared_memory
+ int main ()
+ {
+ int a;
+ #pragma omp target map(from: a)
+ a = omp_is_initial_device ();
+ return a;
+ }
+ } ] {
+ return 1
+ }
+ }
+
+ return 0
+}
+
# return 1 if OpenMP Device Managed Memory is supported
proc check_effective_target_omp_managedmem { } {
diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
index 9923783..aa36f71 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C
index 9023ef8..d08ea71 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C
index 863a1de..b30ade4 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C
index 60d5cee..65004b2 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C
index 5057bf9..3cdd44d 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C
index fe37426..b7d3dd8 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C
index 79f9245..f243790 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C
index 2d80756..d869e89 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C
index 54f62e3..5fbf91b2 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C
index 7ef16bf..09f9879 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C
@@ -1,4 +1,5 @@
// { dg-additional-options "-std=c++20" }
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
diff --git a/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C
index 41ec80e..828b67c 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C b/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C
index 967bff3..835f6d5 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define MEM_SHARED
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c
index d0b0cd1..97bb97a 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-implicit-map-4.c
@@ -4,6 +4,7 @@
and for not mapping the stack variables 'A' and 'B' (not mapped
but accessible -> USM makes this tested feature even more important.) */
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory
/* Ensure that defaultmap(default : pointer) uses correct OpenMP 5.2
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-link-3.c b/libgomp/testsuite/libgomp.c-c++-common/target-link-3.c
index c707b38..9664235 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/target-link-3.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-link-3.c
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <omp.h>
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory
int A[3] = {-3,-4,-5};
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-link-4.c b/libgomp/testsuite/libgomp.c-c++-common/target-link-4.c
index 785055e..009c521 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/target-link-4.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-link-4.c
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <omp.h>
+/* { dg-require-effective-target omp_usm } */
#pragma omp requires self_maps
int A[3] = {-3,-4,-5};
diff --git a/libgomp/testsuite/libgomp.fortran/self_maps.f90 b/libgomp/testsuite/libgomp.fortran/self_maps.f90
index 208fd1c..6088968 100644
--- a/libgomp/testsuite/libgomp.fortran/self_maps.f90
+++ b/libgomp/testsuite/libgomp.fortran/self_maps.f90
@@ -1,4 +1,5 @@
! Basic test whether self_maps work
+! { dg-require-effective-target omp_usm }
module m
!$omp requires self_maps
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-1.c b/libgomp/testsuite/libgomp.graphite/force-parallel-1.c
index 0393356..b873d7a 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-1.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-1.c
@@ -2,7 +2,7 @@ void abort (void);
int x[10000000];
-void parloop (int N)
+void __attribute__((noipa)) parloop (int N)
{
int i;
diff --git a/libphobos/configure b/libphobos/configure
index 1b54066..3965e64 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14920,7 +14920,7 @@ case $d_thread_model in
# TODO: These targets need porting.
dce|mipssde|rtems|tpf|vxworks)
DCFG_THREAD_MODEL="Single" ;;
- *) as_fn_error "Thread implementation '$d_thread_model' not recognised" "$LINENO" 5 ;;
+ *) as_fn_error $? "Thread implementation '$d_thread_model' not recognised" "$LINENO" 5 ;;
esac
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ef8ca43..7bb9136 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -32,7 +32,7 @@ case $1 in
# TODO: These targets need porting.
dce|mipssde|rtems|tpf|vxworks)
DCFG_THREAD_MODEL="Single" ;;
- *) as_fn_error "Thread implementation '$1' not recognised" "$LINENO" 5 ;;
+ *) AC_MSG_ERROR([Thread implementation '$1' not recognised]) ;;
esac
AC_SUBST(DCFG_THREAD_MODEL)
])
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index c01d044..c2a99de 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,71 @@
+2025-12-08 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/122946
+ * include/bits/version.def (concepts): Set value to 202207.
+ * include/bits/version.h: Regenerate.
+ * include/std/concepts (__comparison_common_type_with_impl)
+ (__comparison_common_type_with): New helper concepts.
+ (equality_comparable_with): Use __comparison_common_type_with.
+ * libsupc++/compare (three_way_comparable_with): Likewise.
+ (__glibcxx_want_concepts): Define to get __cpp_lib_concepts
+ here.
+ * testsuite/std/concepts/concepts.compare/move_only.cc: New
+ test.
+
+2025-12-08 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/intcmp.h: Replace all uses of
+ __is_standard_integer with __is_signed_or_unsigned_integer.
+ * include/bits/max_size_type.h: Fix outdated comment.
+ * include/bits/sat_arith.h: Replace all uses of
+ __is_standard_integer with __is_signed_or_unsigned_integer.
+ * include/c_compatibility/stdckdint.h: Replace all uses of the
+ __cv_unqual_signed_or_unsigned_integer_type concept with
+ __is_signed_or_unsigned_integer.
+ (__cv_unqual_signed_or_unsigned_integer_type): Remove.
+ * include/ext/numeric_traits.h: Fix outdated comment.
+ * include/std/charconv (from_chars): Replace use of
+ __is_standard_integer with __is_signed_or_unsigned_integer.
+ Do not enable for cv-qualified char.
+ * include/std/mdspan: Likewise.
+ * include/std/type_traits (__is_unsigned_integer): Include
+ unsigned __int128 in type list.
+ (__is_signed_integer): Include signed __int128 in type list.
+ (__is_standard_integer): Rename to ...
+ (__is_signed_or_unsigned_integer): ... this.
+ * testsuite/23_containers/mdspan/extents/ctor_ints.cc: Test
+ with 128-bit integers.
+ * testsuite/23_containers/mdspan/submdspan/strided_slice.cc:
+ Likewise.
+ * testsuite/20_util/integer_comparisons/extended.cc: New test.
+ * testsuite/26_numerics/saturation/extended.cc: New test.
+ * testsuite/26_numerics/stdckdint/extended.cc: New test.
+
+2025-12-08 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ PR libstdc++/112591
+ * include/std/variant (_Variadic_union): Separate specializations for
+ for union of only trivially destructible types (true as first template
+ argument). Unconditionally define destructor for _Variadic_union<false,
+ _First, _Rest...>.
+ * testsuite/20_util/variant/87619.cc: Add limit for the template depth.
+ * testsuite/20_util/variant/112591.cc: New test.
+
+2025-12-08 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/iterator_concepts.h: Remove diagnostic pragmas.
+
+2025-12-08 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/Makefile.am: Add new header.
+ * include/Makefile.in: Regenerate.
+ * include/std/latch: Include <bits/intcmp.h> instead of
+ <utility>.
+ * include/std/utility: Include <bits/intcmp.h>.
+ (cmp_equal, cmp_not_equal, cmp_less, cmp_greater)
+ (cmp_less_equal, cmp_greater_equal, in_range): Move to ...
+ * include/bits/intcmp.h: New file.
+
2025-12-06 Jason Merrill <jason@redhat.com>
* src/c++23/std.cc.in: Add more #if.
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index e4eb773..103515c 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4193,9 +4193,7 @@ dnl Substs:
dnl thread_header
dnl
AC_DEFUN([GLIBCXX_ENABLE_THREADS], [
- AC_MSG_CHECKING([for thread model used by GCC])
- target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
- AC_MSG_RESULT([$target_thread_file])
+ AC_REQUIRE([GCC_AC_THREAD_MODEL])
GCC_AC_THREAD_HEADER([$target_thread_file])
])
@@ -4208,6 +4206,7 @@ dnl
dnl GLIBCXX_ENABLE_SYMVERS must be done before this.
dnl
AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
+ AC_REQUIRE([GCC_AC_THREAD_MODEL])
GLIBCXX_ENABLE(libstdcxx-threads,auto,,[enable C++11 threads support])
if test x$enable_libstdcxx_threads = xauto ||
@@ -4220,7 +4219,6 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
CXXFLAGS="$CXXFLAGS -fno-exceptions \
-I${toplevel_srcdir}/libgcc -I${toplevel_builddir}/libgcc"
- target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
case $target_thread_file in
posix)
CXXFLAGS="$CXXFLAGS -DSUPPORTS_WEAK -DGTHREAD_USE_WEAK -D_PTHREADS"
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index b1e1275..5f1f18c 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -16330,11 +16330,29 @@ $as_echo "$enable_libstdcxx_pch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread model used by GCC" >&5
-$as_echo_n "checking for thread model used by GCC... " >&6; }
- target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $target_thread_file" >&5
-$as_echo "$target_thread_file" >&6; }
+# Specify the threading model for this GCC runtime library
+# Pass with no value to take from compiler's metadata
+# Pass with a value to specify a thread package
+# 'single' means single threaded -- without threads.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the threading model used by GCC" >&5
+$as_echo_n "checking for the threading model used by GCC... " >&6; }
+if ${gcc_cv_target_thread_file+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ # Set new cache variable
+ gcc_cv_target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_target_thread_file" >&5
+$as_echo "$gcc_cv_target_thread_file" >&6; }
+# Set variable name (not prefixed enough to be a good cache variable
+# name) traditionally used for this purpose, to avoid having to change
+# a bunch of configure scripts.
+target_thread_file="$gcc_cv_target_thread_file"
+
+
+
case $target_thread_file in
aix) thread_header=config/rs6000/gthr-aix.h ;;
@@ -16349,6 +16367,9 @@ case $target_thread_file in
vxworks) thread_header=config/gthr-vxworks.h ;;
win32) thread_header=config/i386/gthr-win32.h ;;
mcf) thread_header=config/i386/gthr-mcf.h ;;
+ *)
+ as_fn_error $? "No known header for threading model '$target_thread_file'." "$LINENO" 5
+ ;;
esac
@@ -16422,7 +16443,7 @@ $as_echo "$glibcxx_cv_atomic_word" >&6; }
# Fake what AC_TRY_COMPILE does.
cat > conftest.$ac_ext << EOF
-#line 16425 "configure"
+#line 16446 "configure"
#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
int main()
{
@@ -16568,7 +16589,7 @@ $as_echo "mutex" >&6; }
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 16571 "configure"
+#line 16592 "configure"
int main()
{
_Decimal32 d1;
@@ -16610,7 +16631,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 16613 "configure"
+#line 16634 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -52252,6 +52273,7 @@ done
# For gthread support. Depends on GLIBCXX_ENABLE_SYMVERS.
+
# Check whether --enable-libstdcxx-threads was given.
if test "${enable_libstdcxx_threads+set}" = set; then :
enableval=$enable_libstdcxx_threads;
@@ -52281,7 +52303,6 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
CXXFLAGS="$CXXFLAGS -fno-exceptions \
-I${toplevel_srcdir}/libgcc -I${toplevel_builddir}/libgcc"
- target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
case $target_thread_file in
posix)
CXXFLAGS="$CXXFLAGS -DSUPPORTS_WEAK -DGTHREAD_USE_WEAK -D_PTHREADS"
@@ -53969,7 +53990,7 @@ $as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; }
CXXFLAGS='-O0 -S'
cat > conftest.$ac_ext << EOF
-#line 53972 "configure"
+#line 53993 "configure"
#include <stddef.h>
int main()
{
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 7d65c6f..847fc13 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -134,6 +134,7 @@ bits_freestanding = \
${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/functexcept.h \
${bits_srcdir}/functional_hash.h \
+ ${bits_srcdir}/intcmp.h \
${bits_srcdir}/invoke.h \
${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/max_size_type.h \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index acf8ae9..1d6171b 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -492,6 +492,7 @@ bits_freestanding = \
${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/functexcept.h \
${bits_srcdir}/functional_hash.h \
+ ${bits_srcdir}/intcmp.h \
${bits_srcdir}/invoke.h \
${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/max_size_type.h \
diff --git a/libstdc++-v3/include/bits/intcmp.h b/libstdc++-v3/include/bits/intcmp.h
new file mode 100644
index 0000000..bb9c7f2
--- /dev/null
+++ b/libstdc++-v3/include/bits/intcmp.h
@@ -0,0 +1,120 @@
+// Integer comparison functions -*- C++ -*-
+
+// Copyright (C) 2020-2025 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/intcmp.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{utility}
+ */
+
+#ifndef _GLIBCXX_INTCMP_H
+#define _GLIBCXX_INTCMP_H 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <bits/version.h>
+
+#ifdef __glibcxx_integer_comparison_functions // C++ >= 20
+
+#include <type_traits>
+#include <ext/numeric_traits.h> // __int_traits
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_equal(_Tp __t, _Up __u) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Up>::value);
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
+ return __t == __u;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u;
+ else
+ return __u >= 0 && __t == make_unsigned_t<_Up>(__u);
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_not_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_equal(__t, __u); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_less(_Tp __t, _Up __u) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Up>::value);
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
+ return __t < __u;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t < 0 || make_unsigned_t<_Tp>(__t) < __u;
+ else
+ return __u >= 0 && __t < make_unsigned_t<_Up>(__u);
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_greater(_Tp __t, _Up __u) noexcept
+ { return std::cmp_less(__u, __t); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_less_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_less(__u, __t); }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ cmp_greater_equal(_Tp __t, _Up __u) noexcept
+ { return !std::cmp_less(__t, __u); }
+
+ template<typename _Res, typename _Tp>
+ constexpr bool
+ in_range(_Tp __t) noexcept
+ {
+ static_assert(__is_signed_or_unsigned_integer<_Res>::value);
+ static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
+ using __gnu_cxx::__int_traits;
+
+ if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>)
+ return __int_traits<_Res>::__min <= __t
+ && __t <= __int_traits<_Res>::__max;
+ else if constexpr (is_signed_v<_Tp>)
+ return __t >= 0
+ && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max;
+ else
+ return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max);
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // __glibcxx_integer_comparison_functions
+#endif // _GLIBCXX_INTCMP_H
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index fd91b22..40ac808 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -39,9 +39,6 @@
#include <bits/ptr_traits.h> // to_address
#include <bits/ranges_cmp.h> // identity, ranges::less
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpedantic" // __int128
-
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -1032,6 +1029,5 @@ namespace ranges
#endif // C++20 library concepts
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
-#pragma GCC diagnostic pop
#endif // C++20
#endif // _ITERATOR_CONCEPTS_H
diff --git a/libstdc++-v3/include/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h
index a34b91a..537acee 100644
--- a/libstdc++-v3/include/bits/max_size_type.h
+++ b/libstdc++-v3/include/bits/max_size_type.h
@@ -44,10 +44,8 @@
// [iterator.concept.winc]) that are one bit wider than the widest supported
// integer type.
//
-// The set of integer types we consider includes __int128 and unsigned __int128
-// (when they exist), even though they are really integer types only in GNU
-// mode. This is to obtain a consistent ABI for these integer-class types
-// across strict mode and GNU mode.
+// The set of integer types we consider includes the extended integer types
+// __int128 and unsigned __int128 (when they exist).
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/sat_arith.h b/libstdc++-v3/include/bits/sat_arith.h
index e036fc8..bce86d9 100644
--- a/libstdc++-v3/include/bits/sat_arith.h
+++ b/libstdc++-v3/include/bits/sat_arith.h
@@ -46,7 +46,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Add two integers, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
add_sat(_Tp __x, _Tp __y) noexcept
{
@@ -62,7 +62,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// Subtract one integer from another, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
sub_sat(_Tp __x, _Tp __y) noexcept
{
@@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// Multiply two integers, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
mul_sat(_Tp __x, _Tp __y) noexcept
{
@@ -94,7 +94,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// Divide one integer by another, with saturation in case of overflow.
- template<typename _Tp> requires __is_standard_integer<_Tp>::value
+ template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Tp
div_sat(_Tp __x, _Tp __y) noexcept
{
@@ -107,8 +107,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Divide one integer by another, with saturation in case of overflow.
template<typename _Res, typename _Tp>
- requires __is_standard_integer<_Res>::value
- && __is_standard_integer<_Tp>::value
+ requires __is_signed_or_unsigned_integer<_Res>::value
+ && __is_signed_or_unsigned_integer<_Tp>::value
constexpr _Res
saturate_cast(_Tp __x) noexcept
{
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 412b9ce..5c010a4 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -879,8 +879,12 @@ ftms = {
ftms = {
name = concepts;
+ // 201806 P0898R3 Standard Library Concepts
+ // 201907 P1754R1 Rename concepts to standard_case for C++20
+ // 202002 P1964R2 Wording for boolean-testable
+ // 202207 P2404R3 Move-only types for equality_comparable_with, etc.
values = {
- v = 202002;
+ v = 202207;
cxxmin = 20;
extra_cond = "__cpp_concepts >= 201907L";
};
@@ -1090,17 +1094,17 @@ ftms = {
name = padded_layouts;
no_stdname = true; // internal
values = {
- v = 1;
+ v = 202403;
cxxmin = 26;
};
};
ftms = {
name = submdspan;
- no_stdname = true; // TODO: change once complete
values = {
- v = 1;
+ v = 202411;
cxxmin = 26;
+ extra_cond = "__glibcxx_constant_wrapper >= 202506L";
};
};
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 2b96934..26d0689 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -985,9 +985,9 @@
#if !defined(__cpp_lib_concepts)
# if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L)
-# define __glibcxx_concepts 202002L
+# define __glibcxx_concepts 202207L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts)
-# define __cpp_lib_concepts 202002L
+# define __cpp_lib_concepts 202207L
# endif
# endif
#endif /* !defined(__cpp_lib_concepts) */
@@ -1214,7 +1214,7 @@
#if !defined(__cpp_lib_padded_layouts)
# if (__cplusplus > 202302L)
-# define __glibcxx_padded_layouts 1L
+# define __glibcxx_padded_layouts 202403L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_padded_layouts)
# endif
# endif
@@ -1222,9 +1222,10 @@
#undef __glibcxx_want_padded_layouts
#if !defined(__cpp_lib_submdspan)
-# if (__cplusplus > 202302L)
-# define __glibcxx_submdspan 1L
+# if (__cplusplus > 202302L) && (__glibcxx_constant_wrapper >= 202506L)
+# define __glibcxx_submdspan 202411L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_submdspan)
+# define __cpp_lib_submdspan 202411L
# endif
# endif
#endif /* !defined(__cpp_lib_submdspan) */
@@ -2037,7 +2038,7 @@
# define __cpp_lib_common_reference 202302L
# endif
# endif
-#endif /* !defined(__cpp_lib_common_reference) && defined(__glibcxx_want_common_reference) */
+#endif /* !defined(__cpp_lib_common_reference) */
#undef __glibcxx_want_common_reference
#if !defined(__cpp_lib_common_reference_wrapper)
@@ -2047,7 +2048,7 @@
# define __cpp_lib_common_reference_wrapper 202302L
# endif
# endif
-#endif /* !defined(__cpp_lib_common_reference_wrapper) && defined(__glibcxx_want_common_reference_wrapper) */
+#endif /* !defined(__cpp_lib_common_reference_wrapper) */
#undef __glibcxx_want_common_reference_wrapper
#if !defined(__cpp_lib_formatters)
diff --git a/libstdc++-v3/include/c_compatibility/stdckdint.h b/libstdc++-v3/include/c_compatibility/stdckdint.h
index 1de2d18..5bdf4dc 100644
--- a/libstdc++-v3/include/c_compatibility/stdckdint.h
+++ b/libstdc++-v3/include/c_compatibility/stdckdint.h
@@ -40,15 +40,6 @@
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
#endif
-/// @cond undocumented
-namespace __detail
-{
- template<typename _Tp>
- concept __cv_unqual_signed_or_unsigned_integer_type
- = std::same_as<_Tp, std::remove_cv_t<_Tp>>
- && std::__is_standard_integer<_Tp>::value;
-}
-/// @endcond
/** Checked integer arithmetic
*
@@ -71,10 +62,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_add(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_add_overflow(__a, __b, __result);
}
@@ -82,10 +72,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_sub(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_sub_overflow(__a, __b, __result);
}
@@ -93,15 +82,14 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
inline bool
ckd_mul(_Tp1* __result, _Tp2 __a, _Tp3 __b)
{
- using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
- static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
+ static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
return __builtin_mul_overflow(__a, __b, __result);
}
/// @}
#ifndef _GLIBCXX_DOXYGEN
-}
+} // namespace __gnu_cxx
using __gnu_cxx::ckd_add;
using __gnu_cxx::ckd_sub;
diff --git a/libstdc++-v3/include/ext/numeric_traits.h b/libstdc++-v3/include/ext/numeric_traits.h
index 6786dc6..78cb8e3 100644
--- a/libstdc++-v3/include/ext/numeric_traits.h
+++ b/libstdc++-v3/include/ext/numeric_traits.h
@@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// or is_signed, digits10, max_digits10, or max_exponent10 for floats.
// Unlike __is_integer (and std::is_integral) this trait is true for
- // non-standard built-in integer types such as __int128 and __int20.
+ // non-standard built-in integer types such as __int20.
template<typename _Tp>
struct __is_integer_nonstrict
: public std::__is_integer<_Tp>
diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv
index 8cf2c0b..47f5aaa 100644
--- a/libstdc++-v3/include/std/charconv
+++ b/libstdc++-v3/include/std/charconv
@@ -554,10 +554,10 @@ namespace __detail
} // namespace __detail
- /// std::from_chars for integral types.
+ /// std::from_chars for integer types.
template<typename _Tp,
- enable_if_t<__or_<__is_standard_integer<_Tp>,
- is_same<char, remove_cv_t<_Tp>>>::value, int> = 0>
+ enable_if_t<__or_<__is_signed_or_unsigned_integer<_Tp>,
+ is_same<char, _Tp>>::value, int> = 0>
_GLIBCXX23_CONSTEXPR from_chars_result
from_chars(const char* __first, const char* __last, _Tp& __value,
int __base = 10)
diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts
index d9920a8..870b0a4 100644
--- a/libstdc++-v3/include/std/concepts
+++ b/libstdc++-v3/include/std/concepts
@@ -296,6 +296,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; };
} // namespace __detail
+ // [concept.comparisoncommontype], helpers for comparison common types
+ namespace __detail
+ {
+ template<typename _Tp, typename _Up,
+ typename _Cref = common_reference_t<const _Tp&, const _Up&>>
+ concept __comparison_common_type_with_impl
+ = same_as<common_reference_t<const _Tp&, const _Up&>,
+ common_reference_t<const _Up&, const _Tp&>>
+ && requires {
+ requires convertible_to<const _Tp&, const _Cref&>
+ || convertible_to<_Tp, const _Cref&>;
+ requires convertible_to<const _Up&, const _Cref&>
+ || convertible_to<_Up, const _Cref&>;
+ };
+
+ template<typename _Tp, typename _Up>
+ concept __comparison_common_type_with
+ = __comparison_common_type_with_impl<remove_cvref_t<_Tp>,
+ remove_cvref_t<_Up>>;
+ } // namespace __detail
+
// [concept.equalitycomparable], concept equality_comparable
namespace __detail
@@ -316,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Up>
concept equality_comparable_with
= equality_comparable<_Tp> && equality_comparable<_Up>
- && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>>
+ && __detail::__comparison_common_type_with<_Tp, _Up>
&& equality_comparable<common_reference_t<__detail::__cref<_Tp>,
__detail::__cref<_Up>>>
&& __detail::__weakly_eq_cmp_with<_Tp, _Up>;
diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch
index 9504df0..df126c6 100644
--- a/libstdc++-v3/include/std/latch
+++ b/libstdc++-v3/include/std/latch
@@ -41,7 +41,7 @@
#ifdef __cpp_lib_latch // C++ >= 20 && atomic_wait
#include <bits/atomic_base.h>
#include <ext/numeric_traits.h>
-#include <utility> // cmp_equal, cmp_less_equal, etc.
+#include <bits/intcmp.h> // cmp_equal, cmp_less_equal, etc.
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 03cc4f0..dc0aa4f 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -271,7 +271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
requires (_Extents.size() > 0)
{
return {_M_dyn_exts + _S_dynamic_index(__begin),
- _M_dyn_exts + _S_dynamic_index(__end)};
+ _S_dynamic_index(__end) - _S_dynamic_index(__begin)};
}
private:
@@ -352,11 +352,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _OffsetType, typename _ExtentType, typename _StrideType>
struct strided_slice
{
- static_assert(__is_standard_integer<_OffsetType>::value
+ static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value
|| __detail::__integral_constant_like<_OffsetType>);
- static_assert(__is_standard_integer<_ExtentType>::value
+ static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value
|| __detail::__integral_constant_like<_ExtentType>);
- static_assert(__is_standard_integer<_StrideType>::value
+ static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
|| __detail::__integral_constant_like<_StrideType>);
using offset_type = _OffsetType;
@@ -374,12 +374,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[no_unique_address]] _Mapping mapping = _Mapping();
size_t offset{};
};
+
+ template<typename _Tp>
+ constexpr bool __is_submdspan_mapping_result = false;
+
+ template<typename _Mapping>
+ constexpr bool __is_submdspan_mapping_result<submdspan_mapping_result<_Mapping>> = true;
+
+ template<typename _Mapping>
+ concept __submdspan_mapping_result = __is_submdspan_mapping_result<_Mapping>;
+
#endif // __glibcxx_submdspan
template<typename _IndexType, size_t... _Extents>
class extents
{
- static_assert(__is_standard_integer<_IndexType>::value,
+ static_assert(__is_signed_or_unsigned_integer<_IndexType>::value,
"IndexType must be a signed or unsigned integer type");
static_assert(
(__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
@@ -589,6 +599,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
+ template<typename _IndexType, size_t _Nm>
+ consteval _IndexType
+ __fwd_prod(span<const _IndexType, _Nm> __values)
+ {
+ _IndexType __ret = 1;
+ for(auto __value : __values)
+ __ret *= __value;
+ return __ret;
+ }
+
// Preconditions: _r < _Extents::rank()
template<typename _Extents>
constexpr typename _Extents::index_type
@@ -792,6 +812,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Mapping>
constexpr bool __is_right_padded_mapping = __padded_mapping_of<
layout_right_padded, _Mapping>;
+
+ template<typename _Mapping>
+ constexpr bool __is_padded_mapping = __is_left_padded_mapping<_Mapping>
+ || __is_right_padded_mapping<_Mapping>;
#endif
template<typename _PaddedMapping>
@@ -866,6 +890,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__exts.extent(_Index)};
}
+ template<typename _Slice, typename _IndexType>
+ concept __acceptable_slice_type = same_as<_Slice, full_extent_t>
+ || same_as<_Slice, _IndexType> || __is_constant_wrapper<_Slice>
+ || __is_strided_slice<_Slice>;
+
template<typename _IndexType, typename... _Slices>
consteval auto
__subrank()
@@ -890,6 +919,547 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__map[__i++] = __k;
return __map;
}
+
+ template<typename _Slice>
+ constexpr auto
+ __slice_begin(_Slice __slice)
+ {
+ if constexpr (same_as<_Slice, full_extent_t>)
+ return 0;
+ else if constexpr (__is_strided_slice<_Slice>)
+ return __slice.offset;
+ else
+ return __slice; // collapsing slice
+ }
+
+ template<typename _Mapping, typename... _Slices>
+ constexpr size_t
+ __suboffset(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ auto __any_past_the_end = [&]<size_t... _Is>(index_sequence<_Is...>)
+ {
+ auto __is_past_the_end = [](const auto& __slice, const auto& __ext)
+ {
+ using _Slice = remove_cvref_t<decltype(__slice)>;
+ if constexpr (is_convertible_v<_Slice, _IndexType>)
+ return false;
+ else if constexpr (same_as<_Slice, full_extent_t>
+ && __ext.static_extent(0) != 0
+ && __ext.static_extent(0) != dynamic_extent)
+ return false;
+ else
+ return __mdspan::__slice_begin(__slice) == __ext.extent(0);
+ };
+
+ const auto& __exts = __mapping.extents();
+ return ((__is_past_the_end(__slices...[_Is],
+ __mdspan::__extract_extent<_Is>(__exts))) || ...);
+ };
+
+ if constexpr ((same_as<_Slices, full_extent_t> && ...))
+ return __mdspan::__offset(__mapping);
+
+ if (__any_past_the_end(std::make_index_sequence<sizeof...(__slices)>()))
+ return __mapping.required_span_size();
+ return __mapping(__mdspan::__slice_begin(__slices)...);
+ }
+
+ template<typename _IndexType, size_t _Extent, typename _Slice>
+ consteval size_t
+ __static_slice_extent()
+ {
+ if constexpr (same_as<_Slice, full_extent_t>)
+ return _Extent;
+ else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
+ return 0;
+ else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
+ && __is_constant_wrapper<typename _Slice::stride_type>)
+ return 1 + ((typename _Slice::extent_type{}) - 1)
+ / (typename _Slice::stride_type{});
+ else
+ return dynamic_extent;
+ }
+
+ template<size_t _K, typename _Extents, typename _Slice>
+ constexpr typename _Extents::index_type
+ __dynamic_slice_extent(const _Extents& __exts, _Slice __slice)
+ {
+ if constexpr (__is_strided_slice<_Slice>)
+ return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride;
+ else
+ return __exts.extent(_K);
+ }
+
+ template<typename _IndexType, size_t... _Extents, typename... _Slices>
+ requires (sizeof...(_Slices) == sizeof...(_Extents))
+ constexpr auto
+ __subextents(const extents<_IndexType, _Extents...>& __exts,
+ _Slices... __slices)
+ {
+ constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
+ auto __impl = [&]<size_t... _Indices>(std::index_sequence<_Indices...>)
+ {
+ using _SubExts = extents<_IndexType,
+ __mdspan::__static_slice_extent<_IndexType,
+ _Extents...[__inv_map[_Indices]],
+ _Slices...[__inv_map[_Indices]]>()...>;
+ if constexpr (_SubExts::rank_dynamic() == 0)
+ return _SubExts{};
+ else
+ {
+ using _StaticSubExtents = __mdspan::_StaticExtents<
+ __mdspan::__static_extents<_SubExts>()>;
+ auto __create = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ constexpr auto __slice_idx = [__inv_map](size_t __i) consteval
+ {
+ return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
+ };
+
+ return _SubExts{__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
+ __exts, __slices...[__slice_idx(_Is)])...};
+ };
+ constexpr auto __dyn_subrank = _SubExts::rank_dynamic();
+ return __create(std::make_index_sequence<__dyn_subrank>());
+ }
+ };
+
+ return __impl(std::make_index_sequence<__inv_map.size()>());
+ }
+
+ enum class _LayoutSide
+ {
+ __left,
+ __right,
+ __unknown
+ };
+
+ template<typename _Mapping>
+ consteval _LayoutSide
+ __mapping_side()
+ {
+ if constexpr (__is_left_padded_mapping<_Mapping>
+ || __mapping_of<layout_left, _Mapping>)
+ return _LayoutSide::__left;
+ if constexpr (__is_right_padded_mapping<_Mapping>
+ || __mapping_of<layout_right, _Mapping>)
+ return _LayoutSide::__right;
+ else
+ return _LayoutSide::__unknown;
+ }
+
+ template<_LayoutSide _Side, size_t _Rank>
+ struct _StridesTrait
+ {
+ static constexpr const _LayoutSide _S_side = _Side;
+
+ static constexpr size_t
+ _S_idx(size_t __k) noexcept
+ {
+ if constexpr (_Side == _LayoutSide::__left)
+ return __k;
+ else
+ return _Rank - 1 - __k;
+ }
+
+ // Unifies the formulas for computing strides for padded and unpadded
+ // layouts.
+ template<typename _Mapping>
+ static constexpr typename _Mapping::index_type
+ _S_padded_extent(const _Mapping& __mapping, size_t __k)
+ {
+ if (__k == 0)
+ return __mapping.stride(_S_idx(1));
+ else
+ return __mapping.extents().extent(_S_idx(__k));
+ }
+
+ template<typename _IndexType, typename... _Slices>
+ static consteval auto
+ _S_inv_map()
+ {
+ static_assert(_Side != _LayoutSide::__unknown);
+ auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ return __mdspan::__inv_map_rank<_IndexType, _Slices...[_S_idx(_Is)]...>();
+ };
+ return __impl(std::make_index_sequence<_Rank>());
+ }
+ };
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides_generic(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ if constexpr (_SubExts::rank() == 0)
+ return array<_IndexType, _SubExts::rank()>{};
+ else
+ {
+ auto __stride = [&__mapping](size_t __k, auto __slice) -> _IndexType
+ {
+ if constexpr (__is_strided_slice<decltype(__slice)>)
+ if (__slice.stride < __slice.extent)
+ return __mapping.stride(__k) * __slice.stride;
+ return __mapping.stride(__k);
+ };
+
+ auto __impl = [&]<size_t... _Is>(std::index_sequence<_Is...>)
+ {
+ constexpr auto __inv_map
+ = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
+ return array<_IndexType, _SubExts::rank()>{
+ __stride(__inv_map[_Is], __slices...[__inv_map[_Is]])...};
+ };
+ return __impl(std::make_index_sequence<_SubExts::rank()>());
+ }
+ };
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides_standardized(const _Mapping& __mapping,
+ const _Slices&... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ using _Trait = _StridesTrait<__mapping_side<_Mapping>(),
+ _Mapping::extents_type::rank()>;
+ using _SubTrait = _StridesTrait<__mapping_side<_Mapping>(), _SubExts::rank()>;
+
+ constexpr size_t __sub_rank = _SubExts::rank();
+
+ std::array<_IndexType, __sub_rank> __ret;
+ if constexpr (__sub_rank > 0)
+ {
+ constexpr auto __inv_map
+ = _Trait::template _S_inv_map<_IndexType, _Slices...>();
+ auto __loop = [&]<size_t... _Ks>(std::index_sequence<_Ks...>)
+ {
+ size_t __i0 = 0;
+ size_t __stride = 1;
+ auto __body = [&](size_t __k, auto __slice)
+ {
+ for (size_t __i = __i0; __i < __inv_map[__k]; ++__i)
+ __stride *= _Trait::_S_padded_extent(__mapping, __i);
+
+ size_t __krev = _SubTrait::_S_idx(__k);
+ if constexpr (__is_strided_slice<decltype(__slice)>)
+ {
+ if (__slice.stride < __slice.extent)
+ __ret[__krev] = __stride * __slice.stride;
+ else
+ __ret[__krev] = __stride;
+ }
+ else
+ __ret[__krev] = __stride;
+
+ __i0 = __inv_map[__k];
+ };
+
+ ((__body(_Ks, __slices...[_Trait::_S_idx(__inv_map[_Ks])])),...);
+ };
+ __loop(std::make_index_sequence<__sub_rank>());
+ }
+ return __ret;
+ }
+
+
+ template<typename _SubExts, typename _Mapping, typename... _Slices>
+ constexpr auto
+ __substrides(const _Mapping& __mapping, const _Slices&... __slices)
+ {
+ if constexpr (__mdspan::__mapping_side<_Mapping>() == _LayoutSide::__unknown)
+ return __mdspan::__substrides_generic<_SubExts>(__mapping, __slices...);
+ else
+ return __mdspan::__substrides_standardized<_SubExts>(__mapping, __slices...);
+ }
+
+ template<typename _Slice>
+ concept __is_unit_stride_slice = (__mdspan::__is_strided_slice<_Slice>
+ && __mdspan::__is_constant_wrapper<typename _Slice::stride_type>
+ && _Slice::stride_type::value == 1)
+ || std::same_as<_Slice, full_extent_t>;
+
+ // These are (forced) exclusive categories:
+ // - full & collapsing: obvious,
+ // - unit_strided_slice: strided_slice{a, b, cw<1>}, but not `full`,
+ // - strided_slice: strided_slice{a, b, c} with c != cw<1>.
+ enum class _SliceKind
+ {
+ __strided_slice,
+ __unit_strided_slice,
+ __full,
+ __collapsing
+ };
+
+ template<typename _Slice>
+ consteval _SliceKind
+ __make_slice_kind()
+ {
+ if constexpr (std::same_as<_Slice, full_extent_t>)
+ return _SliceKind::__full;
+ else if constexpr (__mdspan::__is_strided_slice<_Slice>)
+ {
+ if constexpr (__mdspan::__is_unit_stride_slice<_Slice>)
+ return _SliceKind::__unit_strided_slice;
+ else
+ return _SliceKind::__strided_slice;
+ }
+ else
+ return _SliceKind::__collapsing;
+ }
+
+ template<typename... _Slices>
+ consteval array<_SliceKind, sizeof...(_Slices)>
+ __make_slice_kind_array()
+ {
+ return array<_SliceKind, sizeof...(_Slices)>{
+ __mdspan::__make_slice_kind<_Slices>()...};
+ }
+
+ // __block_size - 1
+ // [full, ..., full, unit_slice , *]
+ consteval bool
+ __is_block(span<const _SliceKind> __slice_kinds, size_t __block_size)
+ {
+ if (__block_size == 0)
+ return false;
+
+ if (__block_size > __slice_kinds.size())
+ return false;
+
+ for (size_t __i = 0; __i < __block_size - 1; ++__i)
+ if (__slice_kinds[__i] != _SliceKind::__full)
+ return false;
+
+ auto __last = __slice_kinds[__block_size - 1];
+ return __last == _SliceKind::__full
+ || __last == _SliceKind::__unit_strided_slice;
+ }
+
+ // __u __u + __sub_rank-2
+ // [unit_slice, i, ..., k, full, ..., full, unit_slice, *]
+ static consteval size_t
+ __padded_block_begin_generic(span<const _SliceKind> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__slice_kinds[0] != _SliceKind::__full
+ && __slice_kinds[0] != _SliceKind::__unit_strided_slice)
+ return dynamic_extent;
+ else if (__slice_kinds.size() == 1)
+ return dynamic_extent;
+ else
+ {
+ size_t __u = 1;
+ while(__u < __slice_kinds.size()
+ && __slice_kinds[__u] == _SliceKind::__collapsing)
+ ++__u;
+
+ if (__mdspan::__is_block(__slice_kinds.subspan(__u), __sub_rank -1))
+ return __u;
+ return dynamic_extent;
+ }
+ }
+
+ template<_LayoutSide _Side, size_t _Nm>
+ static consteval size_t
+ __padded_block_begin(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank)
+ {
+ if constexpr (_Side == _LayoutSide::__left)
+ return __mdspan::__padded_block_begin_generic(__slice_kinds, __sub_rank);
+ else
+ {
+ std::array<_SliceKind, _Nm> __rev_slices;
+ for(size_t __i = 0; __i < _Nm; ++__i)
+ __rev_slices[__i] = __slice_kinds[_Nm - 1 - __i];
+ auto __rev_slice_kinds = span<const _SliceKind>(__rev_slices);
+
+ auto __u = __mdspan::__padded_block_begin_generic(__rev_slice_kinds,
+ __sub_rank);
+ return __u == dynamic_extent ? dynamic_extent : _Nm - 1 - __u;
+ }
+ }
+
+ template<_LayoutSide _Side, bool _Padded>
+ struct _SubMdspanMapping;
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__left, false>
+ {
+ using _Layout = layout_left;
+ template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __sta_exts = __mdspan::__static_extents<_Extents>(0, _Us);
+ if constexpr (!__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds, size_t __sub_rank)
+ { return __mdspan::__is_block(__slice_kinds, __sub_rank); }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__left, true>
+ {
+ using _Layout = layout_left;
+ template<size_t _Pad> using _PaddedLayout = layout_left_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(1, _Us);
+ constexpr auto __sta_padstride
+ = __mdspan::__get_static_stride<_Mapping>();
+ if constexpr (__sta_padstride == dynamic_extent
+ || !__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__sub_rank == 1)
+ return __slice_kinds[0] == _SliceKind::__unit_strided_slice
+ || __slice_kinds[0] == _SliceKind::__full;
+ else
+ return false;
+ }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__right, false>
+ {
+ using _Layout = layout_right;
+ template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __rank = _Extents::rank();
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(_Us + 1, __rank);
+ if constexpr (!__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ auto __rev_slice_kinds = array<_SliceKind, _Nm>{};
+ for(size_t __i = 0; __i < _Nm; ++__i)
+ __rev_slice_kinds[__i] = __slice_kinds[_Nm - 1 - __i];
+ return __mdspan::__is_block(span(__rev_slice_kinds), __sub_rank);
+ }
+ };
+
+ template<>
+ struct _SubMdspanMapping<_LayoutSide::__right, true>
+ {
+ using _Layout = layout_right;
+ template<size_t _Pad> using _PaddedLayout = layout_right_padded<_Pad>;
+
+ template<typename _Mapping, size_t _Us>
+ static consteval size_t
+ _S_pad()
+ {
+ using _Extents = typename _Mapping::extents_type;
+ constexpr auto __rank = _Extents::rank();
+ constexpr auto __sta_exts
+ = __mdspan::__static_extents<_Extents>(_Us + 1, __rank - 1);
+ constexpr auto __sta_padstride
+ = __mdspan::__get_static_stride<_Mapping>();
+ if constexpr (__sta_padstride == dynamic_extent
+ || !__mdspan::__all_static(__sta_exts))
+ return dynamic_extent;
+ else
+ return __sta_padstride * __mdspan::__fwd_prod(__sta_exts);
+ }
+
+ template<size_t _Nm>
+ static consteval bool
+ _S_is_unpadded_submdspan(span<const _SliceKind, _Nm> __slice_kinds,
+ size_t __sub_rank)
+ {
+ if (__sub_rank == 1)
+ return __slice_kinds[_Nm - 1] == _SliceKind::__unit_strided_slice
+ || __slice_kinds[_Nm - 1] == _SliceKind::__full;
+ else
+ return false;
+ }
+ };
+
+
+ template<typename _Mapping>
+ constexpr auto
+ __submdspan_mapping_impl(const _Mapping& __mapping)
+ { return submdspan_mapping_result{__mapping, 0}; }
+
+ template<typename _Mapping, typename... _Slices>
+ requires (sizeof...(_Slices) > 0)
+ constexpr auto
+ __submdspan_mapping_impl(const _Mapping& __mapping, _Slices... __slices)
+ {
+ using _IndexType = typename _Mapping::index_type;
+ static_assert((__acceptable_slice_type<_Slices, _IndexType> && ...));
+
+ constexpr auto __side = __mdspan::__mapping_side<_Mapping>();
+ constexpr auto __rank = sizeof...(_Slices);
+ using _Trait = _SubMdspanMapping<__side, __is_padded_mapping<_Mapping>>;
+ using _SliceView = span<const _SliceKind, __rank>;
+
+ constexpr auto __slice_kinds = __mdspan::__make_slice_kind_array<_Slices...>();
+ auto __offset = __mdspan::__suboffset(__mapping, __slices...);
+ auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
+ using _SubExts = decltype(__sub_exts);
+ constexpr auto __sub_rank = _SubExts::rank();
+ if constexpr (__sub_rank == 0)
+ return submdspan_mapping_result{
+ typename _Trait::_Layout::mapping(__sub_exts), __offset};
+ else if constexpr (_Trait::_S_is_unpadded_submdspan(
+ _SliceView(__slice_kinds), __sub_rank))
+ return submdspan_mapping_result{
+ typename _Trait::_Layout::mapping(__sub_exts), __offset};
+ else if constexpr (
+ constexpr auto __u = __padded_block_begin<__side>(
+ _SliceView(__slice_kinds), __sub_rank);
+ __u != dynamic_extent)
+ {
+ constexpr auto __pad = _Trait::template _S_pad<_Mapping, __u>();
+ using _Layout = typename _Trait::template _PaddedLayout<__pad>;
+ return submdspan_mapping_result{
+ typename _Layout::mapping(__sub_exts, __mapping.stride(__u)),
+ __offset};
+ }
+ else
+ {
+ auto __sub_strides
+ = __mdspan::__substrides<_SubExts>(__mapping, __slices...);
+ return submdspan_mapping_result{
+ layout_stride::mapping(__sub_exts, __sub_strides), __offset};
+ }
+ }
#endif // __glibcxx_submdspan
}
@@ -1032,6 +1602,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
}
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
+
[[no_unique_address]] extents_type _M_extents{};
};
@@ -1208,6 +1786,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
}
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
+
[[no_unique_address]] extents_type _M_extents{};
};
@@ -1418,6 +2004,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
private:
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ {
+ if constexpr (sizeof...(_Slices) == 0)
+ return submdspan_mapping_result{__mapping, 0};
+ else
+ {
+ auto __offset = __mdspan::__suboffset(__mapping, __slices...);
+ auto __sub_exts = __mdspan::__subextents(__mapping.extents(), __slices...);
+ auto __sub_strides
+ = __mdspan::__substrides<decltype(__sub_exts)>(__mapping, __slices...);
+ return submdspan_mapping_result{
+ layout_stride::mapping(__sub_exts, __sub_strides), __offset};
+ }
+ }
+#endif
+
using _Strides = typename __array_traits<index_type,
extents_type::rank()>::_Type;
[[no_unique_address]] extents_type _M_extents;
@@ -2028,6 +2634,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const mapping& __self, const _LeftpadMapping& __other)
noexcept
{ return __self._M_storage._M_equal(__other); }
+
+ private:
+#if __glibcxx_submdspan
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
};
template<size_t _PaddingValue>
@@ -2197,6 +2812,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const mapping& __self, const _RightPaddedMapping& __other)
noexcept
{ return __self._M_storage._M_equal(__other); }
+
+#if __glibcxx_submdspan
+ private:
+ template<typename... _Slices>
+ requires (extents_type::rank() == sizeof...(_Slices))
+ friend constexpr auto
+ submdspan_mapping(const mapping& __mapping, _Slices... __slices)
+ { return __mdspan::__submdspan_mapping_impl(__mapping, __slices...); }
+#endif // __glibcxx_submdspan
};
#endif // __glibcxx_padded_layouts
@@ -2700,68 +3324,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__impl(make_index_sequence<__rank>());
}
- template<typename _IndexType, size_t _Extent, typename _Slice>
- consteval size_t
- __static_slice_extent()
- {
- if constexpr (same_as<_Slice, full_extent_t>)
- return _Extent;
- else if constexpr (same_as<_Slice, constant_wrapper<_IndexType(0)>>)
- return 0;
- else if constexpr (__is_constant_wrapper<typename _Slice::extent_type>
- && __is_constant_wrapper<typename _Slice::stride_type>)
- return 1 + ((typename _Slice::extent_type{}) - 1)
- / (typename _Slice::stride_type{});
- else
- return dynamic_extent;
- }
+ template<typename _Slice>
+ using __full_extent_t = std::full_extent_t;
- template<size_t _K, typename _Extents, typename _Slice>
- constexpr typename _Extents::index_type
- __dynamic_slice_extent(const _Extents& __exts, _Slice __slice)
+ // Enables ADL-only calls from submdspan.
+ void submdspan_mapping() = delete;
+
+ template<typename _Mapping, typename... _Slices>
+ concept __sliceable_mapping = requires(const _Mapping __m, _Slices... __slices)
{
- if constexpr (__is_strided_slice<_Slice>)
- return __slice.extent == 0 ? 0 : 1 + (__slice.extent - 1) / __slice.stride;
- else
- return __exts.extent(_K);
- }
+ { submdspan_mapping(__m, __slices...) } -> __submdspan_mapping_result;
+ };
- template<typename _IndexType, size_t... _Extents, typename... _Slices>
- requires (sizeof...(_Slices) == sizeof...(_Extents))
+ template<typename _Mapping, typename... _Slices>
constexpr auto
- __subextents(const extents<_IndexType, _Extents...>& __exts,
- _Slices... __slices)
+ __submapping(const _Mapping& __mapping, _Slices... __slices)
{
- constexpr auto __inv_map = __mdspan::__inv_map_rank<_IndexType, _Slices...>();
- auto __impl = [&]<size_t... _Indices>(index_sequence<_Indices...>)
- {
- using _SubExtents = extents<_IndexType,
- (__mdspan::__static_slice_extent<_IndexType,
- _Extents...[__inv_map[_Indices]],
- _Slices...[__inv_map[_Indices]]>())...>;
- if constexpr (_SubExtents::rank_dynamic() == 0)
- return _SubExtents{};
- else
- {
- using _StaticSubExtents = __mdspan::_StaticExtents<
- __mdspan::__static_extents<_SubExtents>()>;
- auto __create = [&]<size_t... _Is>(index_sequence<_Is...>)
- {
- constexpr auto __slice_idx = [__inv_map](size_t __i) consteval
- {
- return __inv_map[_StaticSubExtents::_S_dynamic_index_inv(__i)];
- };
-
- return _SubExtents{
- (__mdspan::__dynamic_slice_extent<__slice_idx(_Is)>(
- __exts, __slices...[__slice_idx(_Is)]))...};
- };
- constexpr auto __dyn_subrank = _SubExtents::rank_dynamic();
- return __create(make_index_sequence<__dyn_subrank>());
- }
- };
-
- return __impl(make_index_sequence<__inv_map.size()>());
+ __mdspan::__check_valid_slices(__mapping.extents(), __slices...);
+ return submdspan_mapping(__mapping, __slices...);
}
}
@@ -2792,6 +3372,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
return __impl(__mdspan::__slice_cast<_IndexType>(__raw_slices)...);
}
+
+ template<typename _ElementType, typename _Extents, typename _Layout,
+ typename _Accessor, typename... _RawSlices>
+ requires (sizeof...(_RawSlices) == _Extents::rank()
+ && __mdspan::__sliceable_mapping<typename _Layout::mapping<_Extents>,
+ __mdspan::__full_extent_t<_RawSlices>...>)
+ constexpr auto
+ submdspan(
+ const mdspan<_ElementType, _Extents, _Layout, _Accessor>& __md,
+ _RawSlices... __raw_slices)
+ {
+ using _IndexType = typename _Extents::index_type;
+ auto [__mapping, __offset] = __mdspan::__submapping(
+ __md.mapping(), __mdspan::__slice_cast<_IndexType>(__raw_slices)...);
+ return std::mdspan(
+ __md.accessor().offset(__md.data_handle(), __offset),
+ std::move(__mapping),
+ typename _Accessor::offset_policy(__md.accessor()));
+ }
#endif // __glibcxx_submdspan
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 7c157ea..3f0bcc4e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -826,7 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Check if a type is one of the signed integer types.
__extension__
template<typename _Tp>
- using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>,
+ using __is_signed_integer = __is_one_of<_Tp,
signed char, signed short, signed int, signed long,
signed long long
#if defined(__GLIBCXX_TYPE_INT_N_0)
@@ -841,12 +841,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if defined(__GLIBCXX_TYPE_INT_N_3)
, signed __GLIBCXX_TYPE_INT_N_3
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ , signed __int128
+#endif
>;
// Check if a type is one of the unsigned integer types.
__extension__
template<typename _Tp>
- using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>,
+ using __is_unsigned_integer = __is_one_of<_Tp,
unsigned char, unsigned short, unsigned int, unsigned long,
unsigned long long
#if defined(__GLIBCXX_TYPE_INT_N_0)
@@ -861,11 +864,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if defined(__GLIBCXX_TYPE_INT_N_3)
, unsigned __GLIBCXX_TYPE_INT_N_3
#endif
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+ , unsigned __int128
+#endif
>;
// Check if a type is one of the signed or unsigned integer types.
+ // i.e. an integral type except bool, char, wchar_t, and charN_t.
template<typename _Tp>
- using __is_standard_integer
+ using __is_signed_or_unsigned_integer
= __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;
// __void_t (std::void_t for C++11)
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 3ae1852..0f6dd82 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -78,7 +78,7 @@
#include <bits/utility.h>
#if __cplusplus >= 202002L
-#include <ext/numeric_traits.h> // __is_standard_integer, __int_traits
+#include <bits/intcmp.h>
#endif
#if __cplusplus > 202302L
@@ -129,76 +129,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void as_const(const _Tp&&) = delete;
#endif
-#ifdef __cpp_lib_integer_comparison_functions // C++ >= 20
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_equal(_Tp __t, _Up __u) noexcept
- {
- static_assert(__is_standard_integer<_Tp>::value);
- static_assert(__is_standard_integer<_Up>::value);
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
- return __t == __u;
- else if constexpr (is_signed_v<_Tp>)
- return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u;
- else
- return __u >= 0 && __t == make_unsigned_t<_Up>(__u);
- }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_not_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_equal(__t, __u); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_less(_Tp __t, _Up __u) noexcept
- {
- static_assert(__is_standard_integer<_Tp>::value);
- static_assert(__is_standard_integer<_Up>::value);
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
- return __t < __u;
- else if constexpr (is_signed_v<_Tp>)
- return __t < 0 || make_unsigned_t<_Tp>(__t) < __u;
- else
- return __u >= 0 && __t < make_unsigned_t<_Up>(__u);
- }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_greater(_Tp __t, _Up __u) noexcept
- { return std::cmp_less(__u, __t); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_less_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_less(__u, __t); }
-
- template<typename _Tp, typename _Up>
- constexpr bool
- cmp_greater_equal(_Tp __t, _Up __u) noexcept
- { return !std::cmp_less(__t, __u); }
-
- template<typename _Res, typename _Tp>
- constexpr bool
- in_range(_Tp __t) noexcept
- {
- static_assert(__is_standard_integer<_Res>::value);
- static_assert(__is_standard_integer<_Tp>::value);
- using __gnu_cxx::__int_traits;
-
- if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>)
- return __int_traits<_Res>::__min <= __t
- && __t <= __int_traits<_Res>::__max;
- else if constexpr (is_signed_v<_Tp>)
- return __t >= 0
- && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max;
- else
- return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max);
- }
-#endif // __cpp_lib_integer_comparison_functions
-
#ifdef __cpp_lib_to_underlying // C++ >= 23
/// Convert an object of enumeration type to its underlying type.
template<typename _Tp>
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 2f44f97..f2f5583 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -393,8 +393,29 @@ namespace __variant
_Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete;
};
- template<bool __trivially_destructible, typename _First, typename... _Rest>
- union _Variadic_union<__trivially_destructible, _First, _Rest...>
+ template<typename _First, typename... _Rest>
+ union _Variadic_union<true, _First, _Rest...>
+ {
+ constexpr _Variadic_union() : _M_rest() { }
+
+ template<typename... _Args>
+ constexpr
+ _Variadic_union(in_place_index_t<0>, _Args&&... __args)
+ : _M_first(in_place_index<0>, std::forward<_Args>(__args)...)
+ { }
+
+ template<size_t _Np, typename... _Args>
+ constexpr
+ _Variadic_union(in_place_index_t<_Np>, _Args&&... __args)
+ : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
+ { }
+
+ _Uninitialized<_First> _M_first;
+ _Variadic_union<true, _Rest...> _M_rest;
+ };
+
+ template<typename _First, typename... _Rest>
+ union _Variadic_union<false, _First, _Rest...>
{
constexpr _Variadic_union() : _M_rest() { }
@@ -410,24 +431,19 @@ namespace __variant
: _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...)
{ }
-#if __cpp_lib_variant >= 202106L
_Variadic_union(const _Variadic_union&) = default;
_Variadic_union(_Variadic_union&&) = default;
_Variadic_union& operator=(const _Variadic_union&) = default;
_Variadic_union& operator=(_Variadic_union&&) = default;
- ~_Variadic_union() = default;
-
// If any alternative type is not trivially destructible then we need a
// user-provided destructor that does nothing. The active alternative
// will be destroyed by _Variant_storage::_M_reset() instead of here.
- constexpr ~_Variadic_union()
- requires (!__trivially_destructible)
+ _GLIBCXX20_CONSTEXPR ~_Variadic_union()
{ }
-#endif
_Uninitialized<_First> _M_first;
- _Variadic_union<__trivially_destructible, _Rest...> _M_rest;
+ _Variadic_union<(is_trivially_destructible_v<_Rest> && ...), _Rest...> _M_rest;
};
// _Never_valueless_alt is true for variant alternatives that can
diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
index 08f2b2b..5b4f47a 100644
--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -34,6 +34,7 @@
#pragma GCC system_header
#endif
+#define __glibcxx_want_concepts
#define __glibcxx_want_three_way_comparison
#define __glibcxx_want_type_order
#include <bits/version.h>
@@ -499,10 +500,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
template<typename _Tp, typename _Up, typename _Cat = partial_ordering>
concept three_way_comparable_with
- = three_way_comparable<_Tp, _Cat>
- && three_way_comparable<_Up, _Cat>
- && common_reference_with<const remove_reference_t<_Tp>&,
- const remove_reference_t<_Up>&>
+ = three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat>
+ && __detail::__comparison_common_type_with<_Tp, _Up>
&& three_way_comparable<
common_reference_t<const remove_reference_t<_Tp>&,
const remove_reference_t<_Up>&>, _Cat>
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index 4962d4f..ef0da5d 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -1899,8 +1899,8 @@ export namespace std
using std::submdspan_mapping_result;
using std::submdspan_canonicalize_slices;
using std::submdspan_extents;
+ using std::submdspan;
#endif
- // FIXME mdsubspan
}
#endif
diff --git a/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc b/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc
new file mode 100644
index 0000000..d862b16
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc
@@ -0,0 +1,60 @@
+// { dg-do compile { target c++20 } }
+
+#include <utility>
+
+template<typename T>
+constexpr bool
+test()
+{
+ using S = std::make_signed_t<T>;
+ using U = std::make_unsigned_t<T>;
+
+ static_assert( std::cmp_less((S)-1, (U)1));
+ static_assert( ! std::cmp_less((S)20, (U)10));
+ static_assert( ! std::cmp_less((U)20, (S)10));
+
+ static_assert( std::cmp_greater((S)100, (U)1) );
+ static_assert( std::cmp_greater((U)100, (S)1) );
+ static_assert( ! std::cmp_greater((S)-100, (U)1) );
+
+ static_assert( std::cmp_less_equal((S)-1, (U)1));
+ static_assert( std::cmp_less_equal((U)10, (S)10));
+ static_assert( ! std::cmp_less_equal((U)-100, (S)-100));
+
+ static_assert( std::cmp_greater_equal((S)200, (U)2) );
+ static_assert( std::cmp_greater_equal((U)2000, (S)2000) );
+ static_assert( ! std::cmp_greater_equal((S)-100, (U)100) );
+
+ static_assert( std::cmp_equal((S)1, (U)1) );
+ static_assert( ! std::cmp_equal((S)-2, (U)-2) );
+
+ static_assert( std::cmp_not_equal((S)-1, (U)-1) );
+ static_assert( ! std::cmp_not_equal((S)100, (U)100) );
+
+ static_assert( std::in_range<S>((U)5) );
+ static_assert( std::in_range<U>((S)5) );
+ static_assert( ! std::in_range<S>((U)-5) );
+ static_assert( ! std::in_range<U>((S)-5) );
+
+ return true;
+}
+
+#ifdef __SIZEOF_INT128__
+static_assert(test<__int128>());
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_0
+static_assert(test<__GLIBCXX_TYPE_INT_N_0>());
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_1
+static_assert(test<__GLIBCXX_TYPE_INT_N_1>());
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_2
+static_assert(test<__GLIBCXX_TYPE_INT_N_2>());
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_3
+static_assert(test<__GLIBCXX_TYPE_INT_N_3>());
+#endif
diff --git a/libstdc++-v3/testsuite/20_util/variant/112591.cc b/libstdc++-v3/testsuite/20_util/variant/112591.cc
new file mode 100644
index 0000000..b1b07c4
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/variant/112591.cc
@@ -0,0 +1,32 @@
+// { dg-do run { target c++17 } }
+
+#include <variant>
+#include <testsuite_hooks.h>
+
+struct NonEmpty { int x; };
+struct TrivialEmpty {};
+struct NonTrivialEmpty { ~NonTrivialEmpty() {} };
+
+template<typename T>
+struct Compose : T
+{
+ std::variant<T, int> v;
+};
+
+template<typename T>
+bool testAlias()
+{
+ Compose<T> c;
+ return static_cast<T*>(&c) == &std::get<T>(c.v);
+}
+
+int main()
+{
+ VERIFY( !testAlias<NonEmpty>() );
+ VERIFY( !testAlias<TrivialEmpty>() );
+#if __cplusplus >= 202002L
+ VERIFY( !testAlias<NonTrivialEmpty>() );
+#else
+ VERIFY( testAlias<NonTrivialEmpty>() );
+#endif
+}
diff --git a/libstdc++-v3/testsuite/20_util/variant/87619.cc b/libstdc++-v3/testsuite/20_util/variant/87619.cc
index d988925..ac7dd46 100644
--- a/libstdc++-v3/testsuite/20_util/variant/87619.cc
+++ b/libstdc++-v3/testsuite/20_util/variant/87619.cc
@@ -16,6 +16,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile { target c++17 } }
+// { dg-options "-ftemplate-depth=270" }
#include <variant>
#include <utility>
@@ -23,6 +24,7 @@
template<std::size_t I>
struct S {
+ ~S() {}
};
template <std::size_t... Is>
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
index d5f07c1..fdbcb70 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
@@ -16,6 +16,13 @@ static_assert(!std::is_constructible_v<std::extents<int, 1, dyn, 3>, int, int>);
// Not constructible from non integer-like objects.
static_assert(!std::is_constructible_v<std::extents<int, 1>, int, A>);
+#ifdef __SIZEOF_INT128__
+static_assert(std::is_constructible_v<std::extents<__int128, 1, 2>,
+ __int128, unsigned __int128>);
+static_assert(std::is_constructible_v<std::extents<unsigned __int128, 1, 2>,
+ unsigned int, int>);
+#endif
+
// No implicit conversion from integer-like objects.
template<typename Extent, typename... OExtents>
constexpr bool
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h b/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
index 619cab5..f0aeac3 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layout_traits.h
@@ -87,6 +87,8 @@ template<>
{
using layout_same = std::layout_left;
using layout_other = std::layout_right;
+ template<size_t PaddingValue>
+ using layout_same_padded = std::layout_left_padded<PaddingValue>;
template<typename Extents>
using extents_type = Extents;
@@ -126,6 +128,8 @@ template<>
struct LayoutTraits<PaddingSide::Right>
{
using layout_same = std::layout_right;
+ template<size_t PaddingValue>
+ using layout_same_padded = std::layout_right_padded<PaddingValue>;
using layout_other = std::layout_left;
template<typename IndexType, size_t... Extents>
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/generic.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/generic.cc
new file mode 100644
index 0000000..682ff62
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/generic.cc
@@ -0,0 +1,71 @@
+// { dg-do compile { target c++26 } }
+#include <mdspan>
+
+namespace adl
+{
+ struct NoFriend
+ {
+ template<typename Extents>
+ class mapping
+ {
+ public:
+ using extents_type = Extents;
+ using index_type = typename extents_type::index_type;
+ };
+ };
+
+ struct NoFull
+ {
+ template<typename Extents>
+ class mapping
+ {
+ public:
+ using extents_type = Extents;
+ using index_type = typename extents_type::index_type;
+
+ private:
+ friend constexpr auto
+ submdspan_mapping(mapping, int)
+ { return std::submdspan_mapping_result{mapping{}, 0}; }
+ };
+ };
+
+ struct WrongReturnValue
+ {
+ template<typename Extents>
+ class mapping
+ {
+ public:
+ using extents_type = Extents;
+ using index_type = typename extents_type::index_type;
+
+ private:
+ friend constexpr int
+ submdspan_mapping(mapping, std::full_extent_t)
+ { return 42; }
+ };
+ };
+}
+
+template<typename MdSpan, typename... Slices>
+ concept submdspan_exists = requires (MdSpan md, Slices... slices)
+ {
+ std::submdspan(md, slices...);
+ };
+
+template<typename Layout, bool Expected>
+constexpr bool
+test_invalid_mapping()
+{
+ using Extents = std::extents<int, 3>;
+ using MdSpan = std::mdspan<double, Extents, Layout>;
+ static_assert(submdspan_exists<MdSpan, int> == Expected);
+ static_assert(submdspan_exists<MdSpan, std::full_extent_t> == Expected);
+ static_assert(!submdspan_exists<MdSpan>);
+ static_assert(!submdspan_exists<MdSpan, int, int>);
+ return true;
+}
+static_assert(test_invalid_mapping<std::layout_left, true>());
+static_assert(test_invalid_mapping<adl::NoFriend, false>());
+static_assert(test_invalid_mapping<adl::NoFull, false>());
+static_assert(test_invalid_mapping<adl::WrongReturnValue, false>());
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left.cc
new file mode 100644
index 0000000..d6a85d0
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left.cc
@@ -0,0 +1,9 @@
+// { dg-do run { target c++26 } }
+#include "testcases.h"
+
+int
+main()
+{
+ test_all<std::layout_left>();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded.cc
new file mode 100644
index 0000000..711ce35
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/left_padded.cc
@@ -0,0 +1,12 @@
+// { dg-do run { target c++26 } }
+// { dg-timeout-factor 2 }
+#include "testcases.h"
+
+int
+main()
+{
+ test_all<std::layout_left_padded<1>>();
+ test_all<std::layout_left_padded<8>>();
+ test_all<std::layout_left_padded<dyn>>();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/right.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/right.cc
new file mode 100644
index 0000000..2557072
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/right.cc
@@ -0,0 +1,9 @@
+// { dg-do run { target c++26 } }
+#include "testcases.h"
+
+int
+main()
+{
+ test_all<std::layout_right>();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/right_padded.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/right_padded.cc
new file mode 100644
index 0000000..24ed6cb
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/right_padded.cc
@@ -0,0 +1,12 @@
+// { dg-do run { target c++26 } }
+// { dg-timeout-factor 2 }
+#include "testcases.h"
+
+int
+main()
+{
+ test_all<std::layout_right_padded<1>>();
+ test_all<std::layout_right_padded<8>>();
+ test_all<std::layout_right_padded<dyn>>();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/stride.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/stride.cc
new file mode 100644
index 0000000..19451d7
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/stride.cc
@@ -0,0 +1,9 @@
+// { dg-do run { target c++26 } }
+#include "testcases.h"
+
+int
+main()
+{
+ test_all<std::layout_stride>();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/testcases.h b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/testcases.h
new file mode 100644
index 0000000..d7b751d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/selections/testcases.h
@@ -0,0 +1,360 @@
+#include <mdspan>
+
+#include <vector>
+#include <numeric>
+#include "../../layout_traits.h"
+#include <testsuite_hooks.h>
+
+constexpr size_t dyn = std::dynamic_extent;
+constexpr auto all = std::full_extent;
+
+template<typename T>
+ constexpr bool is_strided_slice = false;
+
+template<typename O, typename E, typename S>
+ constexpr bool is_strided_slice<std::strided_slice<O, E, S>> = true;
+
+template<typename MDSpan>
+ constexpr void
+ fill(const MDSpan& md)
+ {
+ using IndexType = typename MDSpan::index_type;
+ auto exts = md.extents();
+ if constexpr (exts.rank() == 3)
+ for(IndexType i = 0; i < exts.extent(0); ++i)
+ for(IndexType j = 0; j < exts.extent(1); ++j)
+ for(IndexType k = 0; k < exts.extent(2); ++k)
+ md[i, j, k] = 100 * i + 10 * j + k;
+ }
+
+template<typename Int, size_t Rank>
+ class multi_index_generator
+ {
+ struct sentinel
+ { };
+
+ class iterator
+ {
+ public:
+ constexpr
+ iterator(const std::array<Int, Rank>& shape)
+ : M_shape(shape)
+ { }
+
+ constexpr iterator&
+ operator++()
+ {
+ if constexpr (Rank > 0)
+ {
+ ++M_indices[Rank-1];
+ for(size_t i = Rank; i > 1; --i)
+ if (M_indices[i-1] == M_shape[i-1])
+ {
+ M_indices[i-1] = 0;
+ ++M_indices[i-2];
+ }
+ }
+ return *this;
+ }
+
+ constexpr auto
+ operator*()
+ { return M_indices; }
+
+ private:
+ friend constexpr bool
+ operator==(const iterator& it, sentinel)
+ {
+ if constexpr (Rank > 0)
+ return it.M_indices[0] == it.M_shape[0];
+ else
+ return true;
+ }
+
+ std::array<Int, Rank> M_indices{};
+ std::array<Int, Rank> M_shape;
+ };
+
+ public:
+ constexpr
+ multi_index_generator(std::array<Int, Rank> shape)
+ : M_shape(shape)
+ { }
+
+ constexpr iterator
+ begin() const
+ { return iterator(M_shape); }
+
+ constexpr sentinel
+ end() const
+ { return sentinel{}; }
+
+ private:
+ std::array<Int, Rank> M_shape;
+ };
+
+constexpr bool
+test_multi_index()
+{
+ auto shape = std::array{3, 5, 7, 1};
+ auto gen = multi_index_generator(shape);
+ auto it = gen.begin();
+ auto end = gen.end();
+ for (int i = 0; i < shape[0]; ++i)
+ for (int j = 0; j < shape[1]; ++j)
+ for (int k = 0; k < shape[2]; ++k)
+ for (int l = 0; l < shape[3]; ++l)
+ {
+ VERIFY(it != end);
+ VERIFY(*it == std::array{i, j, k, l});
+ ++it;
+ }
+ return true;
+}
+static_assert(test_multi_index());
+
+struct
+collapse
+{ };
+
+template<typename... Slices>
+ consteval auto
+ inv_collapsed_index_map()
+ {
+ constexpr size_t rank = sizeof...(Slices);
+ auto is_collapsing = std::array{std::same_as<Slices, collapse>...};
+ constexpr auto collapsed_rank = ((!std::same_as<Slices, collapse>) + ... + 0);
+
+ std::array<size_t, collapsed_rank> ret;
+ if constexpr (collapsed_rank > 0)
+ for(size_t k = 0, i = 0; i < rank; ++i)
+ if (!is_collapsing[i])
+ ret[k++] = i;
+ return ret;
+ }
+
+static_assert(inv_collapsed_index_map<collapse, collapse, collapse>()
+ == std::array<size_t, 0>{});
+
+static_assert(inv_collapsed_index_map<collapse, decltype(all), collapse>()
+ == std::array<size_t, 1>{1});
+
+template<typename IndexType, typename Slice>
+ constexpr std::vector<IndexType>
+ make_selection(IndexType extent, const Slice& slice)
+ {
+ if constexpr (std::convertible_to<Slice, IndexType>)
+ return {static_cast<IndexType>(slice)};
+ else if constexpr (std::same_as<Slice, std::full_extent_t>)
+ {
+ auto ret = std::vector<IndexType>(static_cast<size_t>(extent));
+ std::ranges::iota(ret, 0);
+ return ret;
+ }
+ else if constexpr (is_strided_slice<Slice>)
+ {
+ auto ret = std::vector<IndexType>{};
+ size_t n = static_cast<size_t>(slice.extent);
+ for(size_t i = 0; i < n; i += slice.stride)
+ ret.push_back(slice.offset + i);
+ return ret;
+ }
+ else
+ {
+ auto [begin, end] = slice;
+ auto ret = std::vector<IndexType>(static_cast<size_t>(end - begin));
+ std::ranges::iota(ret, begin);
+ return ret;
+ }
+ }
+
+template<typename Layout, size_t... I, typename... Slices>
+ constexpr bool
+ check_selection(std::index_sequence<I...>, auto md, Slices... slices)
+ {
+ auto exts = md.extents();
+ auto outer_shape = std::array{exts.extent(0), exts.extent(1), exts.extent(2)};
+
+ constexpr auto full_index = inv_collapsed_index_map<Slices...>();
+ auto make_slice = [](size_t i, auto slice)
+ {
+ if constexpr (std::same_as<decltype(slice), collapse>)
+ return i;
+ else
+ return slice;
+ };
+
+ auto loop_body = [&]<size_t... J>(std::index_sequence<J...>, auto ijk,
+ auto... slices)
+ {
+ auto submd = submdspan(md, slices...[I]...);
+ auto selection = std::tuple{make_selection(exts.extent(I), slices...[I])...};
+ auto inner_shape = std::array<size_t, full_index.size()>{
+ std::get<full_index[J]>(selection).size()...
+ };
+
+ for (auto ij : multi_index_generator(inner_shape))
+ {
+ ((ijk[full_index[J]] = get<full_index[J]>(selection)[ij[J]]),...);
+ VERIFY(submd[ij] == md[ijk]);
+ }
+ };
+
+ for (auto ijk : multi_index_generator(outer_shape))
+ loop_body(std::make_index_sequence<full_index.size()>(), ijk,
+ make_slice(ijk[I], slices...[I])...);
+ return true;
+ }
+
+template<typename Layout, typename...MD, typename... Slices>
+ constexpr bool
+ check_selection(std::mdspan<MD...> md, Slices... slices)
+ {
+ auto indices = std::make_index_sequence<sizeof...(slices)>();
+ return check_selection<Layout>(indices, md, slices...);
+ }
+
+template<typename Layout, typename IndexType, size_t... Extents,
+ typename... Slices>
+ constexpr bool
+ check_selection(std::extents<IndexType, Extents...>exts, Slices... slices)
+ {
+ auto run = [&](auto m)
+ {
+ auto storage = std::vector<double>(m.required_span_size());
+ auto md = std::mdspan(storage.data(), m);
+ fill(md);
+ return check_selection<Layout>(md, slices...);
+ };
+
+ if constexpr (std::same_as<Layout, std::layout_stride>)
+ {
+ auto m = typename Layout::mapping(exts, std::array{15, 2, 50});
+ return run(m);
+ }
+ else
+ {
+ auto m = typename Layout::mapping(exts);
+ return run(m);
+ }
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_scalar_selection(auto exts)
+ {
+ check_selection<Layout>(exts, collapse{}, collapse{}, collapse{});
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_full_lines(auto exts)
+ {
+ check_selection<Layout>(exts, all, collapse{}, collapse{});
+ check_selection<Layout>(exts, collapse{}, all, collapse{});
+ check_selection<Layout>(exts, collapse{}, collapse{}, all);
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_full_blocks(auto exts)
+ {
+ check_selection<Layout>(exts, all, all, collapse{});
+ check_selection<Layout>(exts, all, collapse{}, all);
+ check_selection<Layout>(exts, collapse{}, all, all);
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_cubes(auto exts)
+ {
+ auto s0 = std::pair{0, 2};
+ auto s1 = std::pair{1, 4};
+ auto s2 = std::pair{3, 7};
+
+ check_selection<Layout>(exts, all, all, all);
+ check_selection<Layout>(exts, all, all, s2);
+ check_selection<Layout>(exts, s0, all, all);
+ check_selection<Layout>(exts, s0, all, s2);
+ check_selection<Layout>(exts, s0, s1, s2);
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_strided_line_selection(auto exts)
+ {
+ auto check = [&](auto s)
+ {
+ check_selection<Layout>(exts, collapse{}, s, collapse{});
+ };
+
+ check(std::strided_slice(0, 2, 2));
+ check(std::strided_slice(0, 3, 2));
+ check(std::strided_slice(1, 3, 2));
+ check(std::strided_slice(1, std::cw<3>, std::cw<2>));
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_strided_box_selection(auto exts)
+ {
+ auto s0 = std::strided_slice(0, 3, 2);
+ auto s1 = std::strided_slice(1, 4, 2);
+ auto s2 = std::strided_slice(0, 7, 3);
+
+ check_selection<Layout>(exts, s0, s1, s2);
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_all_cheap()
+ {
+ constexpr auto dyn_exts = std::extents(3, 5, 7);
+ constexpr auto sta_exts = std::extents<int, 3, 5, 7>{};
+
+ test_scalar_selection<Layout>(dyn_exts);
+ test_scalar_selection<Layout>(sta_exts);
+ static_assert(test_scalar_selection<Layout>(dyn_exts));
+ static_assert(test_scalar_selection<Layout>(sta_exts));
+
+ test_full_lines<Layout>(dyn_exts);
+ test_full_lines<Layout>(sta_exts);
+ static_assert(test_full_lines<Layout>(dyn_exts));
+ static_assert(test_full_lines<Layout>(sta_exts));
+
+ test_strided_box_selection<Layout>(dyn_exts);
+ test_strided_box_selection<Layout>(sta_exts);
+ static_assert(test_strided_box_selection<Layout>(dyn_exts));
+ static_assert(test_strided_box_selection<Layout>(sta_exts));
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_all_expensive()
+ {
+ auto run = [](auto exts)
+ {
+ test_full_blocks<Layout>(exts);
+ test_cubes<Layout>(exts);
+ };
+
+ run(std::extents(3, 5, 7));
+ run(std::extents<int, 3, 5, 7>{});
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_all()
+ {
+ test_all_cheap<Layout>();
+ test_all_expensive<Layout>();
+ return true;
+ }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc
index c43a821..6fa5aaa 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc
@@ -34,6 +34,9 @@ test_all()
test_initializers(0, 1, 2);
test_initializers(std::integral_constant<short, 0>{}, size_t{1}, std::cw<2>);
test_initializers(-1, 2, 2);
+#ifdef __SIZEOF_INT128__
+ test_initializers((__int128)1, (unsigned __int128)-2, std::cw<(__int128)3>);
+#endif
return true;
}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc
new file mode 100644
index 0000000..efd71d1
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_mapping.cc
@@ -0,0 +1,301 @@
+// { dg-do run { target c++26 } }
+#include <mdspan>
+
+#include <iostream> // TODO remove
+#include "../layout_traits.h"
+#include <testsuite_hooks.h>
+
+constexpr size_t dyn = std::dynamic_extent;
+constexpr auto all = std::full_extent;
+
+template<typename Mapping, typename... Slices>
+ constexpr auto
+ call_submdspan_mapping(const Mapping& m, std::tuple<Slices...> slices)
+ {
+ auto impl = [&]<size_t... I>(std::index_sequence<I...>)
+ { return submdspan_mapping(m, get<I>(slices)...); };
+ return impl(std::make_index_sequence<sizeof...(Slices)>());
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_layout_common_return_types()
+ {
+ constexpr auto padding_side = DeducePaddingSide::from_typename<Layout>();
+ using Traits = LayoutTraits<padding_side>;
+ using layout_unpadded = typename Traits::layout_same;
+
+ {
+ auto m0 = typename Layout::mapping(std::extents());
+ auto result = submdspan_mapping(m0);
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, Layout>);
+ }
+
+ auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13));
+ auto m = typename Layout::mapping(exts);
+ auto s251 = std::strided_slice{2, 5, std::cw<1>};
+
+ {
+ auto slices = std::tuple{0, 0, 0, 0, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, layout_unpadded>);
+ }
+
+ {
+ auto s0 = std::strided_slice{1, 1, std::cw<1>};
+ auto slices = std::tuple{s0, all, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(is_same_padded<padding_side, layout_type>);
+ }
+
+ {
+ auto s0 = std::strided_slice{1, 2, std::cw<1>};
+ auto slices = std::tuple{s0, all, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(is_same_padded<padding_side, layout_type>);
+ }
+
+ {
+ auto s0 = std::strided_slice{1, 2, std::cw<1>};
+ auto slices = std::tuple{s0, 0, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(is_same_padded<padding_side, layout_type>);
+ }
+
+ {
+ auto s0 = std::strided_slice{1, 2, 1};
+ auto slices = std::tuple{s0, all, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, std::layout_stride>);
+ }
+
+ {
+ auto slices = std::tuple{1, all, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, std::layout_stride>);
+ }
+
+ {
+ auto s3 = std::strided_slice{2, std::cw<7>, std::cw<2>};
+ auto slices = std::tuple{all, all, all, s3, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, std::layout_stride>);
+ }
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_layout_unpadded_return_types()
+ {
+ constexpr auto padding_side = DeducePaddingSide::from_typename<Layout>();
+ using Traits = LayoutTraits<padding_side>;
+
+ auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13));
+ auto m = typename Layout::mapping(exts);
+ auto s251 = std::strided_slice{2, 5, std::cw<1>};
+
+ {
+ auto slices = std::tuple{all, all, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, Layout>);
+ }
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_layout_padded_return_types()
+ {
+ constexpr auto padding_side = DeducePaddingSide::from_typename<Layout>();
+ using Traits = LayoutTraits<padding_side>;
+
+ auto exts = Traits::make_extents(std::dims<5, int>(3, 5, 7, 11, 13));
+ auto m = typename Layout::mapping(exts);
+ auto s251 = std::strided_slice{2, 5, std::cw<1>};
+
+ {
+ auto slices = std::tuple{all, all, all, s251, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ using layout_expected = typename Traits::layout_same_padded<dyn>;
+ static_assert(std::same_as<layout_type, layout_expected>);
+ }
+
+ {
+ auto slices = std::tuple{all, 0, 0, 0, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ using layout_expected = typename Traits::layout_same;
+ static_assert(std::same_as<layout_type, layout_expected>);
+ }
+
+ {
+ auto s121 = std::strided_slice{1, 2, std::cw<1>};
+ auto slices = std::tuple{s121, 0, 0, 0, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ using layout_expected = typename Traits::layout_same;
+ static_assert(std::same_as<layout_type, layout_expected>);
+ }
+
+ {
+ auto s121 = std::strided_slice{1, 2, std::cw<1>};
+ auto slices = std::tuple{0, s121, 0, 0, 0};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ using layout_type = typename decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, std::layout_stride>);
+ }
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_layout_unpadded_padding_value()
+ {
+ using Traits = LayoutTraits<DeducePaddingSide::from_typename<Layout>()>;
+ auto s0 = std::strided_slice{size_t(1), size_t(2), std::cw<size_t(1)>};
+ auto s3 = std::strided_slice{size_t(2), size_t(5), std::cw<size_t(1)>};
+
+ auto check = [&](auto exts, size_t expected)
+ {
+ auto m = typename Layout::mapping(Traits::make_extents(exts));
+ auto slices = std::tuple{s0, size_t(0), all, s3, size_t(0)};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ auto padding_value = decltype(result.mapping)::padding_value;
+ VERIFY(padding_value == expected);
+ };
+
+ check(std::extents(std::cw<3>, std::cw<5>, std::cw<7>, 11, 13), 3*5);
+ check(std::extents(std::cw<3>, std::cw<5>, 7, 11, 13), 3*5);
+ check(std::extents(std::cw<3>, 5, 7, 11, 13), dyn);
+ check(std::extents(3, 5, 7, 11, 13), dyn);
+ return true;
+ }
+
+template<typename Layout>
+constexpr size_t static_padding_value = 1;
+
+template<size_t PaddingValue>
+constexpr size_t static_padding_value<std::layout_left_padded<PaddingValue>> = PaddingValue;
+
+template<size_t PaddingValue>
+constexpr size_t static_padding_value<std::layout_right_padded<PaddingValue>> = PaddingValue;
+
+template<typename Layout>
+ constexpr bool
+ test_layout_padded_padding_value()
+ {
+ using Traits = LayoutTraits<DeducePaddingSide::from_typename<Layout>()>;
+ auto s0 = std::strided_slice{size_t(1), size_t(2), std::cw<size_t(1)>};
+ auto s3 = std::strided_slice{size_t(2), size_t(5), std::cw<size_t(1)>};
+
+ auto check = [&](auto exts, size_t expected)
+ {
+ auto m = typename Layout::mapping(Traits::make_extents(exts));
+ auto slices = std::tuple{s0, size_t(0), all, s3, size_t(0)};
+ auto result = call_submdspan_mapping(m, Traits::make_tuple(slices));
+ auto padding_value = decltype(result.mapping)::padding_value;
+ VERIFY(padding_value == expected);
+ };
+
+ auto pad = [](int n, int m) -> size_t
+ {
+ constexpr auto padding_value = static_padding_value<Layout>;
+ if constexpr (padding_value != dyn)
+ {
+ auto npad = ((n + padding_value - 1) / padding_value) * padding_value;
+ return npad * m;
+ }
+ else
+ return dyn;
+ };
+
+ check(std::extents(std::cw<3>, std::cw<5>, std::cw<7>, 11, 13), pad(3, 5));
+ check(std::extents(std::cw<3>, std::cw<5>, 7, 11, 13), pad(3, 5));
+ check(std::extents(std::cw<3>, std::cw<6>, 7, 11, 13), pad(3, 6));
+ check(std::extents(std::cw<3>, 5, 7, 11, 13), dyn);
+ check(std::extents(3, 5, 7, 11, 13), dyn);
+ return true;
+ }
+
+constexpr bool
+test_layout_stride_return_types()
+{
+ auto exts = std::extents(3, 5);
+ auto m = std::layout_stride::mapping(exts, std::array{2, 12});
+
+ using index_type = decltype(exts)::index_type;
+ auto s1 = std::strided_slice{index_type(2), index_type(2),
+ std::cw<index_type(2)>};
+ auto result = submdspan_mapping(m, index_type(1), s1);
+ using layout_type = decltype(result.mapping)::layout_type;
+ static_assert(std::same_as<layout_type, std::layout_stride>);
+ return true;
+}
+
+template<typename Layout>
+ constexpr bool
+ test_return_types_all()
+ {
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_return_types_unpadded_all()
+ {
+ test_layout_common_return_types<Layout>();
+ static_assert(test_layout_common_return_types<Layout>());
+
+ test_layout_unpadded_return_types<Layout>();
+ static_assert(test_layout_unpadded_return_types<Layout>());
+
+ test_layout_unpadded_padding_value<Layout>();
+ static_assert(test_layout_unpadded_padding_value<Layout>());
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_return_types_padded_all()
+ {
+ test_layout_common_return_types<Layout>();
+ static_assert(test_layout_common_return_types<Layout>());
+
+ test_layout_padded_return_types<Layout>();
+ static_assert(test_layout_padded_return_types<Layout>());
+
+ test_layout_padded_padding_value<Layout>();
+ static_assert(test_layout_padded_padding_value<Layout>());
+ return true;
+ }
+
+int
+main()
+{
+ test_return_types_unpadded_all<std::layout_left>();
+ test_return_types_unpadded_all<std::layout_right>();
+
+ test_return_types_padded_all<std::layout_left_padded<1>>();
+ test_return_types_padded_all<std::layout_left_padded<2>>();
+ test_return_types_padded_all<std::layout_left_padded<dyn>>();
+
+ test_return_types_padded_all<std::layout_right_padded<1>>();
+ test_return_types_padded_all<std::layout_right_padded<2>>();
+ test_return_types_padded_all<std::layout_right_padded<dyn>>();
+
+ test_layout_stride_return_types();
+ static_assert(test_layout_stride_return_types());
+ return 0;
+}
+
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc
new file mode 100644
index 0000000..39eb18c
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_neg.cc
@@ -0,0 +1,122 @@
+// { dg-do compile { target c++26 } }
+#include <mdspan>
+
+#include <vector>
+
+template<typename Layout, typename... Slices>
+ constexpr bool
+ check_slice_range(Slices... slices)
+ {
+ auto m = typename Layout::mapping<std::extents<int, 3, 5, 7>>{};
+ auto storage = std::vector<double>(m.required_span_size());
+ auto md = std::mdspan(storage.data(), m);
+
+ auto submd = submdspan(md, slices...); // { dg-error "expansion of" }
+ (void) submd;
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_int_under()
+ {
+ check_slice_range<Layout>(1, -1, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_int_under<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_int_under<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_int_under<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_int_over()
+ {
+ check_slice_range<Layout>(1, 5, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_int_over<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_int_over<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_int_over<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_tuple_under()
+ {
+ check_slice_range<Layout>(1, std::tuple{-1, 2}, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_tuple_under<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_tuple_under<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_tuple_under<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_tuple_reversed()
+ {
+ check_slice_range<Layout>(1, std::tuple{3, 2}, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_tuple_reversed<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_tuple_reversed<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_tuple_reversed<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_tuple_over()
+ {
+ check_slice_range<Layout>(1, std::tuple{0, 6}, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_tuple_over<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_tuple_over<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_tuple_over<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_strided_slice_zero()
+ {
+ check_slice_range<Layout>(1, std::strided_slice{1, 1, 0}, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_strided_slice_zero<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_strided_slice_zero<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_strided_slice_zero<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_strided_slice_offset_under()
+ {
+ check_slice_range<Layout>(1, std::strided_slice{-1, 1, 1}, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_strided_slice_offset_under<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_strided_slice_offset_under<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_strided_slice_offset_under<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_strided_slice_offset_over()
+ {
+ check_slice_range<Layout>(1, std::strided_slice{6, 0, 1}, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_strided_slice_offset_over<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_strided_slice_offset_over<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_strided_slice_offset_over<std::layout_stride>()); // { dg-error "expansion of" }
+
+template<typename Layout>
+ constexpr bool
+ test_strided_slice_extent_over()
+ {
+ check_slice_range<Layout>(1, std::strided_slice{1, 5, 1}, 2); // { dg-error "expansion of" }
+ return true;
+ }
+static_assert(test_strided_slice_extent_over<std::layout_left>()); // { dg-error "expansion of" }
+static_assert(test_strided_slice_extent_over<std::layout_right>()); // { dg-error "expansion of" }
+static_assert(test_strided_slice_extent_over<std::layout_stride>()); // { dg-error "expansion of" }
+
+// { dg-prune-output "static assertion failed" }
+// { dg-prune-output "__glibcxx_assert_fail" }
+// { dg-prune-output "non-constant condition" }
+// { dg-prune-output "no matching function" }
+// { dg-prune-output "does not satisfy placeholder constraints" }
diff --git a/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc b/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc
new file mode 100644
index 0000000..fbef628
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc
@@ -0,0 +1,55 @@
+// { dg-do compile { target c++26 } }
+
+#include <numeric>
+#include <limits>
+
+template<typename T>
+constexpr bool
+test()
+{
+ using S = std::make_signed_t<T>;
+ using U = std::make_unsigned_t<T>;
+
+ constexpr S smax = std::numeric_limits<S>::max();
+ constexpr S smin = std::numeric_limits<S>::min();
+ constexpr U umax = std::numeric_limits<U>::max();
+
+ static_assert( std::add_sat(smax, (S)1) == smax );
+ static_assert( std::add_sat(smin, (S)-2) == smin );
+ static_assert( std::add_sat(umax, (U)3) == umax );
+
+ static_assert( std::sub_sat(smax, (S)-1) == smax );
+ static_assert( std::sub_sat(smin, (S)2) == smin );
+ static_assert( std::sub_sat((U)0, (U)3) == (U)0 );
+
+ static_assert( std::mul_sat((S)(smax >> 1), (S)3) == smax );
+ static_assert( std::mul_sat((S)(smin >> 1), (S)5) == smin );
+ static_assert( std::mul_sat((U)(umax >> 1), (U)7) == umax );
+
+ static_assert( std::div_sat(smax, (S)2) == (smax >> 1) );
+ static_assert( std::div_sat(smin, (S)4) == (smin >> 2) );
+ static_assert( std::div_sat(smin, (S)-1) == smax );
+ static_assert( std::div_sat(umax, (U)8) == (umax >> 3) );
+
+ return true;
+}
+
+#ifdef __SIZEOF_INT128__
+static_assert(test<__int128>());
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_0
+static_assert(test<__GLIBCXX_TYPE_INT_N_0>());
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_1
+static_assert(test<__GLIBCXX_TYPE_INT_N_1>());
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_2
+static_assert(test<__GLIBCXX_TYPE_INT_N_2>());
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_3
+static_assert(test<__GLIBCXX_TYPE_INT_N_3>());
+#endif
diff --git a/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc b/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc
new file mode 100644
index 0000000..efc0792
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc
@@ -0,0 +1,65 @@
+// { dg-do run { target c++26 } }
+
+#include <stdckdint.h>
+#include <limits>
+#include <testsuite_hooks.h>
+
+template<typename T>
+void
+test()
+{
+ using S = std::make_signed_t<T>;
+ using U = std::make_unsigned_t<T>;
+
+ constexpr S smax = std::numeric_limits<S>::max();
+ constexpr S smin = std::numeric_limits<S>::min();
+ constexpr U umax = std::numeric_limits<U>::max();
+ S sout{};
+ U uout{};
+
+ VERIFY( ckd_add(&sout, smax, (S)1) );
+ VERIFY( ! ckd_add(&uout, smax, (U)1) && uout == ((U)smax + (U)1) );
+ VERIFY( ! ckd_add(&sout, smin, (S)99) && sout == (smin + 99) );
+ VERIFY( ckd_add(&uout, smin, (S)99) );
+ VERIFY( ckd_add(&sout, smin, (S)-2) );
+ VERIFY( ckd_add(&uout, umax, (U)3) );
+ VERIFY( ! ckd_add(&sout, (U)9, (U)3) && sout == 12 );
+
+ VERIFY( ckd_sub(&sout, smax, (S)-1) );
+ VERIFY( ! ckd_sub(&uout, smax, (S)-1) && uout == ((U)smax + (U)1) );
+ VERIFY( ckd_sub(&sout, smin, (S)2) );
+ VERIFY( ! ckd_sub(&sout, smin, (S)-2) && sout == (smin + 2) );
+ VERIFY( ! ckd_sub(&sout, (U)0, (U)3) && sout == -3 );
+ VERIFY( ckd_sub(&uout, (U)0, (U)3) );
+
+ VERIFY( ! ckd_mul(&sout, (S)(smax >> 2), (S)3) && sout == (smax/4*3) );
+ VERIFY( ckd_mul(&sout, (S)(smax >> 1), (S)3) );
+ VERIFY( ! ckd_mul(&uout, (S)(smax >> 1), (S)3) );
+ VERIFY( ckd_mul(&sout, (S)(smin >> 1), (S)5) );
+ VERIFY( ! ckd_mul(&uout, (U)(umax >> 2), (U)3) );
+ VERIFY( ckd_mul(&sout, (U)(umax >> 2), (U)3) );
+ VERIFY( ckd_mul(&uout, (U)(umax >> 1), (U)7) );
+}
+
+int main()
+{
+#ifdef __SIZEOF_INT128__
+ test<__int128>();
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_0
+ test<__GLIBCXX_TYPE_INT_N_0>();
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_1
+ test<__GLIBCXX_TYPE_INT_N_1>();
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_2
+ test<__GLIBCXX_TYPE_INT_N_2>();
+#endif
+
+#ifdef __GLIBCXX_TYPE_INT_N_3
+ test<__GLIBCXX_TYPE_INT_N_3>();
+#endif
+}
diff --git a/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc b/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc
new file mode 100644
index 0000000..01870d8
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc
@@ -0,0 +1,28 @@
+// { dg-do compile { target c++20 } }
+
+#include <concepts>
+#include <compare>
+
+// P2404R3 Move-only types for equality_comparable_with,
+// totally_ordered_with, and three_way_comparable_with
+
+// This was approved for C++23 but we treat it as a DR for C++20.
+
+#ifndef __cpp_lib_concepts
+# error "Feature-test macro __cpp_lib_concepts is missing in <compare>"
+#elif __cpp_lib_concepts < 202207L
+# error "Feature-test macro __cpp_lib_concepts has wrong value in <compare>"
+#endif
+
+struct MoveOnly
+{
+ MoveOnly(int);
+ MoveOnly(MoveOnly&&) = default;
+ auto operator<=>(const MoveOnly&) const = default;
+ std::strong_ordering operator<=>(int) const;
+ bool operator==(const MoveOnly&) const;
+};
+
+static_assert(std::equality_comparable_with<MoveOnly, int>);
+static_assert(std::totally_ordered_with<MoveOnly, int>);
+static_assert(std::three_way_comparable_with<MoveOnly, int>);