From 8f89b29af11d18e0a083e6e86f79055ca997bea0 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 23 May 2024 23:40:10 -0500 Subject: system/gcc: Update to 13.3.0 0012-static-pie and 201-ada were forward-ported by my own paws. Three digit 0xx underscore patches are from Gentoo. This is also the source of the insn-split and match-split patches, which significantly increase performance on build. They are also the source of the new configure option --with-matchpd-partitions. On systems with very many cores/threads, a number higher than 32 would probably perform even better, but 32 should give decent perf on 8+ threads, and runs quite nicely on the 64-thread Talos II I ran the testbuild on. 202 is from Void. The 300s are originally written by me. Presently only tested on ppc64, but built both passes of system/ with only a few incompatibilities (which will be fixed later in this branch). --- system/gcc/0008-s390x-muslldso.patch | 26 - system/gcc/0009-microblaze-pr65649.patch | 34 - system/gcc/0010-ldbl128-config.patch | 76 - system/gcc/0011-m68k.patch | 40 - system/gcc/0012-static-pie.patch | 62 +- system/gcc/0016-invalid-tls-model.patch | 51 - system/gcc/002_all_default-relro.patch | 8 +- system/gcc/005_all_default-as-needed.patch | 68 +- system/gcc/006_as-needed-gold.patch | 58 - system/gcc/007_all_alpha-mieee-default.patch | 48 + .../gcc/011_all_default-warn-format-security.patch | 9 +- system/gcc/012_all_default-warn-trampolines.patch | 4 +- system/gcc/020_all_msgfmt-libstdc++-link.patch | 4 +- system/gcc/050_all_sanitizer-lfs.patch | 197 ++ system/gcc/051_all_libiberty-pic.patch | 2 +- ...l_match.pd-don-t-emit-label-if-not-needed.patch | 114 + ...78_all_match.pd-CSE-the-dump-output-check.patch | 70 + system/gcc/092_all_riscv_PR109760-gstreamer.patch | 337 ++ system/gcc/201-ada.patch | 233 +- system/gcc/202-ibm-ldbl.patch | 4 +- system/gcc/205-nopie.patch | 4 +- system/gcc/206-arm-unwind-functionise.patch | 6 +- system/gcc/320-libffi-gnulinux.patch | 13 - system/gcc/330-gccgo-link-to-ucontext.patch | 2 +- system/gcc/331-gccgo-use-real-off_t-type.patch | 39 +- system/gcc/332-gccgo-sysinfo.patch | 2 +- system/gcc/333-gccgo-signal-ppc64.patch | 11 - system/gcc/334-gccgo-signal-shell.patch | 16 +- system/gcc/335-gccgo-signal-ppc32.patch | 2 +- system/gcc/336-gccgo-mmap64.patch | 17 +- system/gcc/337-gccgo-signal-sig34.patch | 11 - system/gcc/338-gccgo-syscall.patch | 115 - system/gcc/339-gccgo-errstr.patch | 45 - system/gcc/340-gccgo-time64-stat.patch | 19 - system/gcc/341-gccgo-libucontext-stack.patch | 38 +- system/gcc/342-gccgo-more-unwinding.patch | 37 - system/gcc/APKBUILD | 112 +- system/gcc/ada-shared.patch | 8 +- ...ackport-r267157-posix-conformant-snprintf.patch | 80 - system/gcc/fix-cxxflags-passing.patch | 2 +- system/gcc/gcc-4.9-musl-fortify.patch | 2 +- system/gcc/gcc-5.4.0-locale.patch | 2 +- system/gcc/gcc-6.1-musl-libssp.patch | 11 +- system/gcc/gcc-pure64.patch | 60 +- system/gcc/insn-split.patch | 1404 ++++++++ system/gcc/libgcc-always-build-gcceh.a.patch | 6 +- system/gcc/match-split.patch | 3583 ++++++++++++++++++++ 47 files changed, 6028 insertions(+), 1064 deletions(-) delete mode 100644 system/gcc/0008-s390x-muslldso.patch delete mode 100644 system/gcc/0009-microblaze-pr65649.patch delete mode 100644 system/gcc/0010-ldbl128-config.patch delete mode 100644 system/gcc/0011-m68k.patch delete mode 100644 system/gcc/0016-invalid-tls-model.patch delete mode 100644 system/gcc/006_as-needed-gold.patch create mode 100644 system/gcc/007_all_alpha-mieee-default.patch create mode 100644 system/gcc/050_all_sanitizer-lfs.patch create mode 100644 system/gcc/076_all_match.pd-don-t-emit-label-if-not-needed.patch create mode 100644 system/gcc/078_all_match.pd-CSE-the-dump-output-check.patch create mode 100644 system/gcc/092_all_riscv_PR109760-gstreamer.patch delete mode 100644 system/gcc/320-libffi-gnulinux.patch delete mode 100644 system/gcc/333-gccgo-signal-ppc64.patch delete mode 100644 system/gcc/337-gccgo-signal-sig34.patch delete mode 100644 system/gcc/338-gccgo-syscall.patch delete mode 100644 system/gcc/339-gccgo-errstr.patch delete mode 100644 system/gcc/340-gccgo-time64-stat.patch delete mode 100644 system/gcc/342-gccgo-more-unwinding.patch delete mode 100644 system/gcc/backport-r267157-posix-conformant-snprintf.patch create mode 100644 system/gcc/insn-split.patch create mode 100644 system/gcc/match-split.patch diff --git a/system/gcc/0008-s390x-muslldso.patch b/system/gcc/0008-s390x-muslldso.patch deleted file mode 100644 index 64833f308..000000000 --- a/system/gcc/0008-s390x-muslldso.patch +++ /dev/null @@ -1,26 +0,0 @@ -From b693804c8dba92fea7beee98f0aa520853a0532b Mon Sep 17 00:00:00 2001 -From: Szabolcs Nagy -Date: Thu, 22 Dec 2016 11:22:28 +0000 -Subject: [PATCH 08/12] s390x muslldso - ---- - gcc/config/s390/linux.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h -index 525c17c2c9f..2d4f4a0654e 100644 ---- a/gcc/config/s390/linux.h -+++ b/gcc/config/s390/linux.h -@@ -76,6 +76,9 @@ along with GCC; see the file COPYING3. If not see - #define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1" - #define GLIBC_DYNAMIC_LINKER64 "/lib/ld64.so.1" - -+#define MUSL_DYNAMIC_LINKER32 "/lib/ld-musl-s390.so.1" -+#define MUSL_DYNAMIC_LINKER64 "/lib/ld-musl-s390x.so.1" -+ - #undef LINK_SPEC - #define LINK_SPEC \ - "%{m31:-m elf_s390}%{m64:-m elf64_s390} \ --- -2.17.1 - diff --git a/system/gcc/0009-microblaze-pr65649.patch b/system/gcc/0009-microblaze-pr65649.patch deleted file mode 100644 index 35bf88d69..000000000 --- a/system/gcc/0009-microblaze-pr65649.patch +++ /dev/null @@ -1,34 +0,0 @@ -From a0934d40a8ed3b6e82abb31d2f8d7c60548d4a05 Mon Sep 17 00:00:00 2001 -From: Szabolcs Nagy -Date: Fri, 26 Jan 2018 20:25:11 +0000 -Subject: [PATCH 09/12] microblaze-pr65649 - ---- - gcc/config/microblaze/microblaze.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c -index 9a4a287be23..60aadaf51f7 100644 ---- a/gcc/config/microblaze/microblaze.c -+++ b/gcc/config/microblaze/microblaze.c -@@ -2399,7 +2399,7 @@ print_operand (FILE * file, rtx op, int letter) - unsigned long value_long; - REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), - value_long); -- fprintf (file, HOST_WIDE_INT_PRINT_HEX, value_long); -+ fprintf (file, "0x%lx", value_long); - } - else - { -@@ -2458,7 +2458,7 @@ print_operand (FILE * file, rtx op, int letter) - print_operand_address (file, XEXP (op, 0)); - } - else if (letter == 'm') -- fprintf (file, HOST_WIDE_INT_PRINT_DEC, (1L << INTVAL (op))); -+ fprintf (file, "%ld", (1L << INTVAL (op))); - else - output_addr_const (file, op); - } --- -2.17.1 - diff --git a/system/gcc/0010-ldbl128-config.patch b/system/gcc/0010-ldbl128-config.patch deleted file mode 100644 index b5a101052..000000000 --- a/system/gcc/0010-ldbl128-config.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 47467f3ab0fb2f2fcede81060fe8bb339d0909eb Mon Sep 17 00:00:00 2001 -From: Szabolcs Nagy -Date: Wed, 28 Feb 2018 00:54:05 +0000 -Subject: [PATCH 10/12] ldbl128 config - ---- - gcc/configure | 13 +++++++++++++ - gcc/configure.ac | 16 ++++++++++++++-- - 2 files changed, 27 insertions(+), 2 deletions(-) - -diff --git a/gcc/configure b/gcc/configure -index 6121e163259..07ff8597d48 100755 ---- a/gcc/configure -+++ b/gcc/configure -@@ -29309,6 +29309,15 @@ if test "${with_long_double_128+set}" = set; then : - withval=$with_long_double_128; gcc_cv_target_ldbl128="$with_long_double_128" - else - -+ case "$target" in -+ s390*-*-linux-musl*) -+ gcc_cv_target_ldbl128=yes -+ ;; -+ powerpc*-*-linux-musl*) -+ gcc_cv_target_ldbl128=no -+ ;; -+ *) -+ - if test $glibc_version_major -gt 2 \ - || ( test $glibc_version_major -eq 2 && test $glibc_version_minor -ge 4 ); then : - gcc_cv_target_ldbl128=yes -@@ -29320,6 +29329,10 @@ else - && gcc_cv_target_ldbl128=yes - - fi -+ -+ ;; -+ esac -+ - fi - - ;; -diff --git a/gcc/configure.ac b/gcc/configure.ac -index b066cc609e1..6c15ed898c0 100644 ---- a/gcc/configure.ac -+++ b/gcc/configure.ac -@@ -5971,13 +5971,25 @@ case "$target" in - AC_ARG_WITH(long-double-128, - [AS_HELP_STRING([--with-long-double-128], - [use 128-bit long double by default])], -- gcc_cv_target_ldbl128="$with_long_double_128", -+ gcc_cv_target_ldbl128="$with_long_double_128", [ -+ case "$target" in -+ s390*-*-linux-musl*) -+ gcc_cv_target_ldbl128=yes -+ ;; -+ powerpc*-*-linux-musl*) -+ gcc_cv_target_ldbl128=no -+ ;; -+ *)] - [GCC_GLIBC_VERSION_GTE_IFELSE([2], [4], [gcc_cv_target_ldbl128=yes], [ - [gcc_cv_target_ldbl128=no - grep '^[ ]*#[ ]*define[ ][ ]*__LONG_DOUBLE_MATH_OPTIONAL' \ - $target_header_dir/bits/wordsize.h > /dev/null 2>&1 \ - && gcc_cv_target_ldbl128=yes -- ]])]) -+ ]])] -+ [ -+ ;; -+ esac -+ ]) - ;; - esac - if test x$gcc_cv_target_ldbl128 = xyes; then --- -2.17.1 - diff --git a/system/gcc/0011-m68k.patch b/system/gcc/0011-m68k.patch deleted file mode 100644 index 74a5a98da..000000000 --- a/system/gcc/0011-m68k.patch +++ /dev/null @@ -1,40 +0,0 @@ -From cc44e95053140efe41212746882d410052b480a3 Mon Sep 17 00:00:00 2001 -From: Szabolcs Nagy -Date: Sun, 1 Jul 2018 18:34:01 +0000 -Subject: [PATCH 11/12] m68k - ---- - gcc/config/m68k/linux.h | 3 +++ - libgcc/config/m68k/linux-unwind.h | 2 +- - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h -index f584d19e179..a3c215550fe 100644 ---- a/gcc/config/m68k/linux.h -+++ b/gcc/config/m68k/linux.h -@@ -73,6 +73,9 @@ along with GCC; see the file COPYING3. If not see - - #define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1" - -+#undef MUSL_DYNAMIC_LINKER -+#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-m68k.so.1" -+ - #undef LINK_SPEC - #define LINK_SPEC "-m m68kelf %{shared} \ - %{!shared: \ -diff --git a/libgcc/config/m68k/linux-unwind.h b/libgcc/config/m68k/linux-unwind.h -index 395e4b3212a..432b757541c 100644 ---- a/libgcc/config/m68k/linux-unwind.h -+++ b/libgcc/config/m68k/linux-unwind.h -@@ -37,7 +37,7 @@ struct uw_ucontext { - stack_t uc_stack; - mcontext_t uc_mcontext; - unsigned long uc_filler[80]; -- __sigset_t uc_sigmask; -+ sigset_t uc_sigmask; - }; - - #define MD_FALLBACK_FRAME_STATE_FOR m68k_fallback_frame_state --- -2.17.1 - diff --git a/system/gcc/0012-static-pie.patch b/system/gcc/0012-static-pie.patch index 0600c791e..5c7a1b519 100644 --- a/system/gcc/0012-static-pie.patch +++ b/system/gcc/0012-static-pie.patch @@ -13,14 +13,14 @@ an alias to -static -pie. gcc/common.opt | 4 ++-- gcc/config/gnu-user.h | 12 +++++------- gcc/config/rs6000/sysv4.h | 11 +++++------ - gcc/gcc.c | 6 +++--- + gcc/gcc.cc | 6 +++--- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/gcc/common.opt b/gcc/common.opt index b52ef0b38c8..0ce5857e01d 100644 --- a/gcc/common.opt +++ b/gcc/common.opt -@@ -3197,11 +3197,11 @@ Driver +@@ -3669,11 +3669,11 @@ Driver no-pie Driver RejectNegative Negative(shared) @@ -38,7 +38,7 @@ diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h index 8620de3e42d..235328a2642 100644 --- a/gcc/config/gnu-user.h +++ b/gcc/config/gnu-user.h -@@ -52,13 +52,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +@@ -51,13 +51,12 @@ #define GNU_USER_TARGET_STARTFILE_SPEC \ "%{shared:; \ pg|p|profile:%{static-pie:grcrt1.o%s;:gcrt1.o%s}; \ @@ -46,8 +46,8 @@ index 8620de3e42d..235328a2642 100644 - static-pie:rcrt1.o%s; \ + static|static-pie:%{" PIE_SPEC ":rcrt1.o%s;:crt1.o%s}; \ " PIE_SPEC ":Scrt1.o%s; \ - :crt1.o%s} \ - crti.o%s \ + :crt1.o%s} " \ + GNU_USER_TARGET_CRTI " \ - %{static:crtbeginT.o%s; \ - shared|static-pie|" PIE_SPEC ":crtbeginS.o%s; \ + %{shared|" PIE_SPEC ":crtbeginS.o%s; \ @@ -55,7 +55,7 @@ index 8620de3e42d..235328a2642 100644 :crtbegin.o%s} \ %{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_start_preinit.o%s; \ -@@ -92,8 +91,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +@@ -76,8 +75,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see "%{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_end_preinit.o%s; \ fvtable-verify=std:vtv_end.o%s} \ @@ -63,9 +63,9 @@ index 8620de3e42d..235328a2642 100644 - shared|static-pie|" PIE_SPEC ":crtendS.o%s; \ + %{shared|" PIE_SPEC ":crtendS.o%s; \ :crtend.o%s} \ - crtn.o%s \ - " CRTOFFLOADEND -@@ -133,7 +131,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + GNU_USER_TARGET_CRTN " " \ + CRTOFFLOADEND +@@ -106,7 +104,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define LIB_SPEC GNU_USER_TARGET_LIB_SPEC #if defined(HAVE_LD_EH_FRAME_HDR) @@ -73,43 +73,12 @@ index 8620de3e42d..235328a2642 100644 +#define LINK_EH_SPEC "%{!static|" PIE_SPEC ":--eh-frame-hdr} " #endif - #undef LINK_GCC_C_SEQUENCE_SPEC -diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h -index bb19d0dcd41..bb2a2324eb0 100644 ---- a/gcc/config/rs6000/sysv4.h -+++ b/gcc/config/rs6000/sysv4.h -@@ -763,12 +763,12 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN) - #define STARTFILE_LINUX_SPEC \ - "%{shared:; \ - pg|p|profile:gcrt1.o%s; \ -- static:crt1.o%s; \ -- static-pie|" PIE_SPEC ":Scrt1.o%s; \ -+ static|static-pie:%{" PIE_SPEC ":rcrt1.o%s;:crt1.o%s}; \ -+ " PIE_SPEC ":Scrt1.o%s; \ - :crt1.o%s} \ - %{mnewlib:ecrti.o%s;:crti.o%s} \ -- %{static:crtbeginT.o%s; \ -- shared|static-pie|" PIE_SPEC ":crtbeginS.o%s; \ -+ %{shared|" PIE_SPEC ":crtbeginS.o%s; \ -+ static:crtbeginT.o%s; \ - :crtbegin.o%s} \ - %{fvtable-verify=none:%s; \ - fvtable-verify=preinit:vtv_start_preinit.o%s; \ -@@ -781,8 +781,7 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN) - "%{fvtable-verify=none:%s; \ - fvtable-verify=preinit:vtv_end_preinit.o%s; \ - fvtable-verify=std:vtv_end.o%s} \ -- %{static:crtend.o%s; \ -- shared|static-pie|" PIE_SPEC ":crtendS.o%s; \ -+ %{shared|" PIE_SPEC ":crtendS.o%s; \ - :crtend.o%s} \ - %{mnewlib:ecrtn.o%s;:crtn.o%s} \ - " CRTOFFLOADEND -diff --git a/gcc/gcc.c b/gcc/gcc.c + #define GNU_USER_TARGET_LINK_GCC_C_SEQUENCE_SPEC \ +diff --git a/gcc/gcc.cc b/gcc/gcc.cc index eb1610ba8b0..87560afb03c 100644 ---- a/gcc/gcc.c -+++ b/gcc/gcc.c -@@ -900,7 +900,7 @@ proper position among the other output files. */ +--- a/gcc/gcc.cc ++++ b/gcc/gcc.cc +@@ -1003,7 +1003,7 @@ proper position among the other output files. */ #define NO_FPIE_AND_FPIC_SPEC NO_FPIE_SPEC "|" NO_FPIC_SPEC #define FPIE_OR_FPIC_SPEC NO_FPIE_AND_FPIC_SPEC ":;" #else @@ -118,7 +87,7 @@ index eb1610ba8b0..87560afb03c 100644 #define FPIE1_SPEC "fpie" #define NO_FPIE1_SPEC FPIE1_SPEC ":;" #define FPIE2_SPEC "fPIE" -@@ -924,12 +924,12 @@ proper position among the other output files. */ +@@ -1027,12 +1027,12 @@ proper position among the other output files. */ #ifndef LINK_PIE_SPEC #ifdef HAVE_LD_PIE #ifndef LD_PIE_SPEC @@ -135,4 +104,3 @@ index eb1610ba8b0..87560afb03c 100644 #ifndef LINK_BUILDID_SPEC -- 2.17.1 - diff --git a/system/gcc/0016-invalid-tls-model.patch b/system/gcc/0016-invalid-tls-model.patch deleted file mode 100644 index d3b2b8ea0..000000000 --- a/system/gcc/0016-invalid-tls-model.patch +++ /dev/null @@ -1,51 +0,0 @@ ---- gcc-7.3.0/libgomp/configure.tgt.orig 2018-09-25 13:44:16.654561098 -0400 -+++ gcc-7.3.0/libgomp/configure.tgt 2018-09-25 13:44:50.452688100 -0400 -@@ -10,23 +10,6 @@ - # XCFLAGS Add extra compile flags to use. - # XLDFLAGS Add extra link flags to use. - --# Optimize TLS usage by avoiding the overhead of dynamic allocation. --if test $gcc_cv_have_tls = yes ; then -- case "${target}" in -- -- *-*-k*bsd*-gnu*) -- ;; -- -- *-*-linux* | *-*-gnu*) -- XCFLAGS="${XCFLAGS} -ftls-model=initial-exec" -- ;; -- -- *-*-rtems*) -- XCFLAGS="${XCFLAGS} -ftls-model=local-exec" -- ;; -- esac --fi -- - # Since we require POSIX threads, assume a POSIX system by default. - config_path="posix" - ---- gcc-7.3.0/libitm/configure.tgt.orig 2018-09-25 13:47:31.019296903 -0400 -+++ gcc-7.3.0/libitm/configure.tgt 2018-09-25 13:47:37.676322335 -0400 -@@ -27,22 +27,6 @@ - # XCFLAGS Add extra compile flags to use. - # XLDFLAGS Add extra link flags to use. - --# Optimize TLS usage by avoiding the overhead of dynamic allocation. --if test "$gcc_cv_have_tls" = yes ; then -- case "${target}" in -- -- # For x86, we use slots in the TCB head for most of our TLS. -- # The setup of those slots in beginTransaction can afford to -- # use the global-dynamic model. -- i[456]86-*-linux* | x86_64-*-linux*) -- ;; -- -- *-*-linux*) -- XCFLAGS="${XCFLAGS} -ftls-model=initial-exec" -- ;; -- esac --fi -- - # Map the target cpu to an ARCH sub-directory. At the same time, - # work out any special compilation flags as necessary. - case "${target_cpu}" in diff --git a/system/gcc/002_all_default-relro.patch b/system/gcc/002_all_default-relro.patch index 284deef1a..6fbf7684d 100644 --- a/system/gcc/002_all_default-relro.patch +++ b/system/gcc/002_all_default-relro.patch @@ -19,11 +19,11 @@ Index: b/gcc/doc/invoke.texi @item -u @var{symbol} @opindex u Pretend the symbol @var{symbol} is undefined, to force linking of -Index: b/gcc/gcc.c +Index: b/gcc/gcc.cc =================================================================== ---- a/gcc/gcc.c -+++ b/gcc/gcc.c -@@ -890,6 +890,7 @@ proper position among the other output f +--- a/gcc/gcc.cc ++++ b/gcc/gcc.cc +@@ -1144,6 +1144,7 @@ proper position among the other output f "%{flto|flto=*:% + +Note: upstream doesn't want to take this due to long standing behavior, and +because it'd make behavior across OS's inconsistent: + https://gcc.gnu.org/ml/gcc-patches/2003-07/msg02144.html + +This makes sense for upstream, but Gentoo is more concerned about packages +behaving the same across arches under Linux. + +--- a/gcc/config/alpha/alpha.h ++++ b/gcc/config/alpha/alpha.h +@@ -94,6 +94,8 @@ along with GCC; see the file COPYING3. If not see + while (0) + #endif + ++#define CPP_SPEC "%{!no-ieee:-mieee}" ++ + /* Run-time compilation parameters selecting different hardware subsets. */ + + /* Which processor to schedule for. The cpu attribute defines a list that +--- a/gcc/config/alpha/alpha.opt ++++ b/gcc/config/alpha/alpha.opt +@@ -35,7 +35,7 @@ + Request IEEE-conformant math library routines (OSF/1). + + mieee +-Target RejectNegative Mask(IEEE) ++Target Mask(IEEE) + Emit IEEE-conformant code, without inexact exceptions. + + mieee-with-inexact + diff --git a/system/gcc/011_all_default-warn-format-security.patch b/system/gcc/011_all_default-warn-format-security.patch index 1f400d026..6b62fdecf 100644 --- a/system/gcc/011_all_default-warn-format-security.patch +++ b/system/gcc/011_all_default-warn-format-security.patch @@ -1,10 +1,9 @@ Enable -Wformat and -Wformat-security by default. - --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt -@@ -459,7 +459,7 @@ C ObjC C++ ObjC++ Var(warn_format_nonliteral) Warning LangEnabledBy(C ObjC C++ O - Warn about format strings that are not literals. +@@ -704,7 +704,7 @@ Warn about function calls with format strings that write past the end + of the destination region. Same as -Wformat-overflow=1. Wformat-security -C ObjC C++ ObjC++ Var(warn_format_security) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 2, 0) @@ -12,7 +11,7 @@ Enable -Wformat and -Wformat-security by default. Warn about possible security problems with format functions. Wformat-signedness -@@ -475,7 +475,7 @@ C ObjC C++ ObjC++ Var(warn_format_zero_length) Warning LangEnabledBy(C ObjC C++ +@@ -725,7 +725,7 @@ C ObjC C++ ObjC++ Var(warn_format_zero_length) Warning LangEnabledBy(C ObjC C++ Warn about zero-length formats. Wformat= @@ -20,4 +19,4 @@ Enable -Wformat and -Wformat-security by default. +C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format) Init(1) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0) IntegerRange(0, 2) Warn about printf/scanf/strftime/strfmon format string anomalies. - Wignored-qualifiers + Wformat-overflow= diff --git a/system/gcc/012_all_default-warn-trampolines.patch b/system/gcc/012_all_default-warn-trampolines.patch index 89ebfaccd..0bb1bd6d8 100644 --- a/system/gcc/012_all_default-warn-trampolines.patch +++ b/system/gcc/012_all_default-warn-trampolines.patch @@ -3,7 +3,7 @@ Enable -Wtrampolines by default. --- a/gcc/common.opt +++ b/gcc/common.opt -@@ -648,7 +648,7 @@ Common Var(warn_system_headers) Warning +@@ -799,7 +799,7 @@ Common Var(warn_system_headers) Warning Do not suppress warnings from system headers Wtrampolines @@ -14,7 +14,7 @@ Enable -Wtrampolines by default. Wtype-limits --- a/gcc/doc/gcc.info +++ b/gcc/doc/gcc.info -@@ -4021,6 +4021,8 @@ compiler warns that an unrecognized option is present. +@@ -7744,6 +7744,8 @@ compiler warns that an unrecognized option is present. and thus requires the stack to be made executable in order for the program to work properly. diff --git a/system/gcc/020_all_msgfmt-libstdc++-link.patch b/system/gcc/020_all_msgfmt-libstdc++-link.patch index a70ea50a0..753b70302 100644 --- a/system/gcc/020_all_msgfmt-libstdc++-link.patch +++ b/system/gcc/020_all_msgfmt-libstdc++-link.patch @@ -19,7 +19,7 @@ https://bugs.gentoo.org/295480 --- gcc-4.1.2.orig/libstdc++-v3/po/Makefile.am +++ gcc-4.1.2/libstdc++-v3/po/Makefile.am -@@ -39,6 +39,7 @@ MSGFMT = msgfmt +@@ -38,6 +38,7 @@ MSGFMT = msgfmt EXTRA_DIST = string_literals.cc POTFILES.in $(PACKAGE).pot $(LOCALE_IN) .po.mo: @@ -29,7 +29,7 @@ https://bugs.gentoo.org/295480 all-local: all-local-$(USE_NLS) --- gcc-4.1.2.orig/libstdc++-v3/po/Makefile.in +++ gcc-4.1.2/libstdc++-v3/po/Makefile.in -@@ -419,6 +419,7 @@ uninstall-am: uninstall-info-am +@@ -561,6 +561,7 @@ uninstall-am: uninstall-info-am .po.mo: diff --git a/system/gcc/050_all_sanitizer-lfs.patch b/system/gcc/050_all_sanitizer-lfs.patch new file mode 100644 index 000000000..65baea289 --- /dev/null +++ b/system/gcc/050_all_sanitizer-lfs.patch @@ -0,0 +1,197 @@ +https://bugs.gentoo.org/900871 +https://reviews.llvm.org/D141186 +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109533 +https://github.com/llvm/llvm-project/commit/a5519b99bc73d50f362d6fb306411e9fcb758b53 +--- a/libsanitizer/interception/interception_type_test.cpp ++++ b/libsanitizer/interception/interception_type_test.cpp +@@ -24,9 +24,9 @@ COMPILER_CHECK(sizeof(::SSIZE_T) == sizeof(ssize_t)); + COMPILER_CHECK(sizeof(::PTRDIFF_T) == sizeof(ptrdiff_t)); + COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t)); + +-#if !SANITIZER_APPLE ++# if SANITIZER_GLIBC || SANITIZER_ANDROID + COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t)); +-#endif ++# endif + + // The following are the cases when pread (and friends) is used instead of + // pread64. In those cases we need OFF_T to match off_t. We don't care about the +--- a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc ++++ b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc +@@ -910,24 +910,26 @@ POST_SYSCALL(statfs)(long res, const void *path, void *buf) { + } + } + +-PRE_SYSCALL(statfs64)(const void *path, long sz, void *buf) { +- if (path) +- PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1); +-} ++PRE_SYSCALL(fstatfs)(long fd, void *buf) {} + +-POST_SYSCALL(statfs64)(long res, const void *path, long sz, void *buf) { ++POST_SYSCALL(fstatfs)(long res, long fd, void *buf) { + if (res >= 0) { + if (buf) +- POST_WRITE(buf, struct_statfs64_sz); ++ POST_WRITE(buf, struct_statfs_sz); + } + } ++# endif // !SANITIZER_ANDROID + +-PRE_SYSCALL(fstatfs)(long fd, void *buf) {} ++# if SANITIZER_GLIBC ++PRE_SYSCALL(statfs64)(const void *path, long sz, void *buf) { ++ if (path) ++ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1); ++} + +-POST_SYSCALL(fstatfs)(long res, long fd, void *buf) { ++POST_SYSCALL(statfs64)(long res, const void *path, long sz, void *buf) { + if (res >= 0) { + if (buf) +- POST_WRITE(buf, struct_statfs_sz); ++ POST_WRITE(buf, struct_statfs64_sz); + } + } + +@@ -939,7 +941,7 @@ POST_SYSCALL(fstatfs64)(long res, long fd, long sz, void *buf) { + POST_WRITE(buf, struct_statfs64_sz); + } + } +-# endif // !SANITIZER_ANDROID ++# endif // SANITIZER_GLIBC + + PRE_SYSCALL(lstat)(const void *filename, void *statbuf) { + if (filename) +@@ -998,7 +1000,7 @@ POST_SYSCALL(newfstat)(long res, long fd, void *statbuf) { + } + } + +-# if !SANITIZER_ANDROID ++# if SANITIZER_GLIBC + PRE_SYSCALL(ustat)(long dev, void *ubuf) {} + + POST_SYSCALL(ustat)(long res, long dev, void *ubuf) { +@@ -1007,7 +1009,7 @@ POST_SYSCALL(ustat)(long res, long dev, void *ubuf) { + POST_WRITE(ubuf, struct_ustat_sz); + } + } +-# endif // !SANITIZER_ANDROID ++# endif // SANITIZER_GLIBC + + PRE_SYSCALL(stat64)(const void *filename, void *statbuf) { + if (filename) +@@ -2228,7 +2230,7 @@ POST_SYSCALL(setrlimit)(long res, long resource, void *rlim) { + } + } + +-# if !SANITIZER_ANDROID ++# if SANITIZER_GLIBC + PRE_SYSCALL(prlimit64) + (long pid, long resource, const void *new_rlim, void *old_rlim) { + if (new_rlim) +--- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h ++++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h +@@ -269,7 +269,7 @@ + #define SANITIZER_INTERCEPT_INET_ATON SI_POSIX + #define SANITIZER_INTERCEPT_SYSINFO SI_LINUX + #define SANITIZER_INTERCEPT_READDIR SI_POSIX +-#define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 ++#define SANITIZER_INTERCEPT_READDIR64 SI_GLIBC || SI_SOLARIS32 + #if SI_LINUX_NOT_ANDROID && \ + (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ +@@ -308,7 +308,7 @@ + #define SANITIZER_INTERCEPT_XPG_STRERROR_R SI_LINUX_NOT_ANDROID + #define SANITIZER_INTERCEPT_SCANDIR \ + (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) +-#define SANITIZER_INTERCEPT_SCANDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 ++#define SANITIZER_INTERCEPT_SCANDIR64 SI_GLIBC || SI_SOLARIS32 + #define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX + #define SANITIZER_INTERCEPT_POLL SI_POSIX + #define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS +@@ -330,10 +330,10 @@ + #define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID + #define SANITIZER_INTERCEPT_STATFS \ + (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) +-#define SANITIZER_INTERCEPT_STATFS64 SI_LINUX_NOT_ANDROID && SANITIZER_HAS_STATFS64 ++#define SANITIZER_INTERCEPT_STATFS64 SI_GLIBC && SANITIZER_HAS_STATFS64 + #define SANITIZER_INTERCEPT_STATVFS \ + (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID) +-#define SANITIZER_INTERCEPT_STATVFS64 SI_LINUX_NOT_ANDROID ++#define SANITIZER_INTERCEPT_STATVFS64 SI_GLIBC + #define SANITIZER_INTERCEPT_INITGROUPS SI_POSIX + #define SANITIZER_INTERCEPT_ETHER_NTOA_ATON SI_POSIX + #define SANITIZER_INTERCEPT_ETHER_HOST \ +@@ -471,9 +471,9 @@ + #define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX) + #define SANITIZER_INTERCEPT___XSTAT \ + ((!SANITIZER_INTERCEPT_STAT && SI_POSIX) || SI_STAT_LINUX) +-#define SANITIZER_INTERCEPT___XSTAT64 SI_LINUX_NOT_ANDROID ++#define SANITIZER_INTERCEPT___XSTAT64 SI_GLIBC + #define SANITIZER_INTERCEPT___LXSTAT SANITIZER_INTERCEPT___XSTAT +-#define SANITIZER_INTERCEPT___LXSTAT64 SI_LINUX_NOT_ANDROID ++#define SANITIZER_INTERCEPT___LXSTAT64 SI_GLIBC + + #define SANITIZER_INTERCEPT_UTMP \ + (SI_POSIX && !SI_MAC && !SI_FREEBSD && !SI_NETBSD) +@@ -484,7 +484,7 @@ + (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD) + + #define SANITIZER_INTERCEPT_MMAP SI_POSIX +-#define SANITIZER_INTERCEPT_MMAP64 SI_LINUX_NOT_ANDROID || SI_SOLARIS ++#define SANITIZER_INTERCEPT_MMAP64 SI_GLIBC || SI_SOLARIS + #define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO (SI_GLIBC || SI_ANDROID) + #define SANITIZER_INTERCEPT_MEMALIGN (!SI_FREEBSD && !SI_MAC && !SI_NETBSD) + #define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC +--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp ++++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp +@@ -260,7 +260,7 @@ namespace __sanitizer { + unsigned struct_itimerspec_sz = sizeof(struct itimerspec); + #endif // SANITIZER_LINUX + +-#if SANITIZER_LINUX && !SANITIZER_ANDROID ++#if SANITIZER_GLIBC + // Use pre-computed size of struct ustat to avoid which + // has been removed from glibc 2.28. + #if defined(__aarch64__) || defined(__s390x__) || defined(__mips64) || \ +@@ -281,7 +281,7 @@ namespace __sanitizer { + unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT; + unsigned struct_rlimit64_sz = sizeof(struct rlimit64); + unsigned struct_statvfs64_sz = sizeof(struct statvfs64); +-#endif // SANITIZER_LINUX && !SANITIZER_ANDROID ++#endif // SANITIZER_GLIBC + + #if SANITIZER_INTERCEPT_CRYPT_R + unsigned struct_crypt_data_sz = sizeof(struct crypt_data); +@@ -1089,7 +1089,7 @@ CHECK_SIZE_AND_OFFSET(dirent, d_off); + #endif + CHECK_SIZE_AND_OFFSET(dirent, d_reclen); + +-#if SANITIZER_LINUX && !SANITIZER_ANDROID ++#if SANITIZER_GLIBC + COMPILER_CHECK(sizeof(__sanitizer_dirent64) <= sizeof(dirent64)); + CHECK_SIZE_AND_OFFSET(dirent64, d_ino); + CHECK_SIZE_AND_OFFSET(dirent64, d_off); +--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h ++++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h +@@ -28,8 +28,7 @@ + #define SANITIZER_HAS_STAT64 0 + #define SANITIZER_HAS_STATFS64 0 + #endif +-#else +-// Must be SANITIZER_LINUX then ++#elif SANITIZER_GLIBC || SANITIZER_ANDROID + #define SANITIZER_HAS_STAT64 1 + #define SANITIZER_HAS_STATFS64 1 + #endif +@@ -517,7 +516,7 @@ struct __sanitizer_dirent { + }; + # endif + +-# if SANITIZER_LINUX && !SANITIZER_ANDROID ++# if SANITIZER_GLIBC + struct __sanitizer_dirent64 { + unsigned long long d_ino; + unsigned long long d_off; + diff --git a/system/gcc/051_all_libiberty-pic.patch b/system/gcc/051_all_libiberty-pic.patch index b6160a730..3f0bae16b 100644 --- a/system/gcc/051_all_libiberty-pic.patch +++ b/system/gcc/051_all_libiberty-pic.patch @@ -1,6 +1,6 @@ --- a/libiberty/Makefile.in +++ b/libiberty/Makefile.in -@@ -246,6 +246,7 @@ $(TARGETLIB): $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS) +@@ -265,6 +265,7 @@ $(TARGETLIB): $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS) $(AR) $(AR_FLAGS) $(TARGETLIB) \ $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS); \ $(RANLIB) $(TARGETLIB); \ diff --git a/system/gcc/076_all_match.pd-don-t-emit-label-if-not-needed.patch b/system/gcc/076_all_match.pd-don-t-emit-label-if-not-needed.patch new file mode 100644 index 000000000..95da940fe --- /dev/null +++ b/system/gcc/076_all_match.pd-don-t-emit-label-if-not-needed.patch @@ -0,0 +1,114 @@ +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21 + +From 6178fddd3e0957fbb8bcfc443fef172691b7640b Mon Sep 17 00:00:00 2001 +From: Tamar Christina +Date: Fri, 5 May 2023 13:35:17 +0100 +Subject: [PATCH 01/15] match.pd: don't emit label if not needed + +This is a small QoL codegen improvement for match.pd to not emit labels when +they are not needed. The codegen is nice and there is a small (but consistent) +improvement in compile time. + +gcc/ChangeLog: + + PR bootstrap/84402 + * genmatch.cc (dt_simplify::gen_1): Only emit labels if used. + +(cherry picked from commit 580cda3c2799b1f8323af770e52f1eb0fa204718) +--- + gcc/genmatch.cc | 30 ++++++++++++++++++++++-------- + 1 file changed, 22 insertions(+), 8 deletions(-) + +diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc +index c1023d921fca..9ecd0a462b4f 100644 +--- a/gcc/genmatch.cc ++++ b/gcc/genmatch.cc +@@ -3354,6 +3354,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + char local_fail_label[256]; + snprintf (local_fail_label, 256, "next_after_fail%u", ++fail_label_cnt); + fail_label = local_fail_label; ++ bool needs_label = false; + + /* Analyze captures and perform early-outs on the incoming arguments + that cover cases we cannot handle. */ +@@ -3368,6 +3369,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + fprintf_indent (f, indent, + "if (TREE_SIDE_EFFECTS (_p%d)) goto %s;\n", + i, fail_label); ++ needs_label = true; + if (verbose >= 1) + warning_at (as_a (s->match)->ops[i]->location, + "forcing toplevel operand to have no " +@@ -3383,6 +3385,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + fprintf_indent (f, indent, + "if (TREE_SIDE_EFFECTS (captures[%d])) " + "goto %s;\n", i, fail_label); ++ needs_label = true; + if (verbose >= 1) + warning_at (cinfo.info[i].c->location, + "forcing captured operand to have no " +@@ -3425,7 +3428,10 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + } + + if (s->kind == simplify::SIMPLIFY) +- fprintf_indent (f, indent, "if (UNLIKELY (!dbg_cnt (match))) goto %s;\n", fail_label); ++ { ++ fprintf_indent (f, indent, "if (UNLIKELY (!dbg_cnt (match))) goto %s;\n", fail_label); ++ needs_label = true; ++ } + + fprintf_indent (f, indent, "if (UNLIKELY (dump_file && (dump_flags & TDF_FOLDING))) " + "fprintf (dump_file, \"%s ", +@@ -3498,9 +3504,12 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + "res_op->resimplify (%s, valueize);\n", + !e->force_leaf ? "lseq" : "NULL"); + if (e->force_leaf) +- fprintf_indent (f, indent, +- "if (!maybe_push_res_to_seq (res_op, NULL)) " +- "goto %s;\n", fail_label); ++ { ++ fprintf_indent (f, indent, ++ "if (!maybe_push_res_to_seq (res_op, NULL)) " ++ "goto %s;\n", fail_label); ++ needs_label = true; ++ } + } + } + else if (result->type == operand::OP_CAPTURE +@@ -3556,9 +3565,12 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + continue; + if (cinfo.info[i].result_use_count + > cinfo.info[i].match_use_count) +- fprintf_indent (f, indent, +- "if (! tree_invariant_p (captures[%d])) " +- "goto %s;\n", i, fail_label); ++ { ++ fprintf_indent (f, indent, ++ "if (! tree_invariant_p (captures[%d])) " ++ "goto %s;\n", i, fail_label); ++ needs_label = true; ++ } + } + for (unsigned j = 0; j < e->ops.length (); ++j) + { +@@ -3609,6 +3621,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + { + fprintf_indent (f, indent, "if (!_r)\n"); + fprintf_indent (f, indent, " goto %s;\n", fail_label); ++ needs_label = true; + } + } + } +@@ -3649,7 +3662,8 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + } + indent -= 2; + fprintf_indent (f, indent, "}\n"); +- fprintf (f, "%s:;\n", fail_label); ++ if (needs_label) ++ fprintf (f, "%s:;\n", fail_label); + fail_label = NULL; + } + +-- +2.44.0 + diff --git a/system/gcc/078_all_match.pd-CSE-the-dump-output-check.patch b/system/gcc/078_all_match.pd-CSE-the-dump-output-check.patch new file mode 100644 index 000000000..e084c4c77 --- /dev/null +++ b/system/gcc/078_all_match.pd-CSE-the-dump-output-check.patch @@ -0,0 +1,70 @@ +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21 + +From 2d83fafb3f263544be09bf7dbde036e4a84f6d7c Mon Sep 17 00:00:00 2001 +From: Tamar Christina +Date: Fri, 5 May 2023 13:36:43 +0100 +Subject: [PATCH 03/15] match.pd: CSE the dump output check. + +This is a small improvement in QoL codegen for match.pd to save time not +re-evaluating the condition for printing debug information in every function. + +There is a small but consistent runtime and compile time win here. The runtime +win comes from not having to do the condition over again, and on Arm plaforms +we now use the new test-and-branch support for booleans to only have a single +instruction here. + +gcc/ChangeLog: + + PR bootstrap/84402 + * genmatch.cc (decision_tree::gen, write_predicate): Generate new + debug_dump var. + (dt_simplify::gen_1): Use it. + +(cherry picked from commit c0ce29bc1ce329001b6c02bb3d34bcbb086e1b72) +--- + gcc/genmatch.cc | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc +index 45e49c790b6d..a17ef8a23ed5 100644 +--- a/gcc/genmatch.cc ++++ b/gcc/genmatch.cc +@@ -3433,7 +3433,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) + needs_label = true; + } + +- fprintf_indent (f, indent, "if (UNLIKELY (dump_file && (dump_flags & TDF_FOLDING))) " ++ fprintf_indent (f, indent, "if (UNLIKELY (debug_dump)) " + "fprintf (dump_file, \"%s ", + s->kind == simplify::SIMPLIFY + ? "Applying pattern" : "Matching expression"); +@@ -3894,6 +3894,8 @@ decision_tree::gen (FILE *f, bool gimple) + } + + fprintf (f, ")\n{\n"); ++ fprintf_indent (f, 2, "const bool debug_dump = " ++ "dump_file && (dump_flags & TDF_FOLDING);\n"); + s->s->gen_1 (f, 2, gimple, s->s->s->result); + if (gimple) + fprintf (f, " return false;\n"); +@@ -3939,6 +3941,8 @@ decision_tree::gen (FILE *f, bool gimple) + fprintf (f, ", tree _p%d", i); + fprintf (f, ")\n"); + fprintf (f, "{\n"); ++ fprintf_indent (f, 2, "const bool debug_dump = " ++ "dump_file && (dump_flags & TDF_FOLDING);\n"); + dop->gen_kids (f, 2, gimple, 0); + if (gimple) + fprintf (f, " return false;\n"); +@@ -4048,6 +4052,8 @@ write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple) + gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : ""); + /* Conveniently make 'type' available. */ + fprintf_indent (f, 2, "const tree type = TREE_TYPE (t);\n"); ++ fprintf_indent (f, 2, "const bool debug_dump = " ++ "dump_file && (dump_flags & TDF_FOLDING);\n"); + + if (!gimple) + fprintf_indent (f, 2, "if (TREE_SIDE_EFFECTS (t)) return false;\n"); +-- +2.44.0 + diff --git a/system/gcc/092_all_riscv_PR109760-gstreamer.patch b/system/gcc/092_all_riscv_PR109760-gstreamer.patch new file mode 100644 index 000000000..976f68915 --- /dev/null +++ b/system/gcc/092_all_riscv_PR109760-gstreamer.patch @@ -0,0 +1,337 @@ +https://bugs.gentoo.org/928234 +https://gcc.gnu.org/PR109760 +https://gcc.gnu.org/PR110095 +https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=55914b016de8c8514c58eb59822677a69e44135c + +From 55914b016de8c8514c58eb59822677a69e44135c Mon Sep 17 00:00:00 2001 +From: Die Li +Date: Fri, 19 May 2023 23:00:13 -0600 +Subject: [PATCH] Fix riscv_expand_conditional_move. + +Two issues have been observed in current riscv_expand_conditional_move +implementation. +1. Before introduction of TARGET_XTHEADCONDMOV, op0 of comparision expression +is used for mode comparision with word_mode, but after TARGET_XTHEADCONDMOV +megered with TARGET_SFB_ALU, dest of if-then-else is used for mode comparision with +word_mode, and from md file mode of dest is DI or SI which can be different with +word_mode in RV64. + +2. TARGET_XTHEADCONDMOV cannot be generated when the mode of the comparison is E_VOID. + +This patch solves the issues above. + +Provide an example from the newly added test case. + +Testcase: +int ConNmv_reg_reg_reg(int x, int y, int z, int n){ + if (x != y) return z; + return n; +} + +Cflags: +-O2 -march=rv64gc_xtheadcondmov -mabi=lp64d + +before patch: +ConNmv_reg_reg_reg: + bne a0,a1,.L23 + mv a2,a3 +.L23: + mv a0,a2 + ret + +after patch: +ConNmv_reg_reg_reg: + sub a1,a0,a1 + th.mveqz a2,zero,a1 + th.mvnez a3,zero,a1 + or a0,a2,a3 + ret + +Co-Authored by: Fei Gao +Signed-off-by: Die Li + +gcc/ChangeLog: + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Fix mode + checking. + +gcc/testsuite/ChangeLog: + + * gcc.target/riscv/xtheadcondmov-indirect-rv32.c: New test. + * gcc.target/riscv/xtheadcondmov-indirect-rv64.c: New test. +--- + gcc/config/riscv/riscv.cc | 4 +- + .../riscv/xtheadcondmov-indirect-rv32.c | 116 ++++++++++++++++++ + .../riscv/xtheadcondmov-indirect-rv64.c | 116 ++++++++++++++++++ + 3 files changed, 234 insertions(+), 2 deletions(-) + create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-indirect-rv32.c + create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-indirect-rv64.c + +diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc +index 2a7b43849e5..7bb38978261 100644 +--- a/gcc/config/riscv/riscv.cc ++++ b/gcc/config/riscv/riscv.cc +@@ -3406,7 +3406,7 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) + && GET_MODE_CLASS (mode) == MODE_INT + && reg_or_0_operand (cons, mode) + && reg_or_0_operand (alt, mode) +- && GET_MODE (op) == mode ++ && (GET_MODE (op) == mode || GET_MODE (op) == E_VOIDmode) + && GET_MODE (op0) == mode + && GET_MODE (op1) == mode + && (code == EQ || code == NE)) +@@ -3415,7 +3415,7 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) + return true; + } + else if (TARGET_SFB_ALU +- && mode == word_mode) ++ && GET_MODE (op0) == word_mode) + { + riscv_emit_int_compare (&code, &op0, &op1); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); +diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-indirect-rv32.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-indirect-rv32.c +new file mode 100644 +index 00000000000..9afdc2eabfd +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-indirect-rv32.c +@@ -0,0 +1,116 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -march=rv32gc_xtheadcondmov -mabi=ilp32 -mriscv-attribute" } */ ++/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */ ++/* { dg-final { check-function-bodies "**" "" } } */ ++ ++/* ++**ConEmv_imm_imm_reg: ++** addi a5,a0,-1000 ++** li a0,10 ++** th.mvnez a0,zero,a5 ++** th.mveqz a1,zero,a5 ++** or a0,a0,a1 ++** ret ++*/ ++int ConEmv_imm_imm_reg(int x, int y){ ++ if (x == 1000) return 10; ++ return y; ++} ++ ++/* ++**ConEmv_imm_reg_reg: ++** addi a5,a0,-1000 ++** th.mvnez a1,zero,a5 ++** th.mveqz a2,zero,a5 ++** or a0,a1,a2 ++** ret ++*/ ++int ConEmv_imm_reg_reg(int x, int y, int z){ ++ if (x == 1000) return y; ++ return z; ++} ++ ++/* ++**ConEmv_reg_imm_reg: ++** sub a1,a0,a1 ++** li a0,10 ++** th.mvnez a0,zero,a1 ++** th.mveqz a2,zero,a1 ++** or a0,a0,a2 ++** ret ++*/ ++int ConEmv_reg_imm_reg(int x, int y, int z){ ++ if (x == y) return 10; ++ return z; ++} ++ ++/* ++**ConEmv_reg_reg_reg: ++** sub a1,a0,a1 ++** th.mvnez a2,zero,a1 ++** th.mveqz a3,zero,a1 ++** or a0,a2,a3 ++** ret ++*/ ++int ConEmv_reg_reg_reg(int x, int y, int z, int n){ ++ if (x == y) return z; ++ return n; ++} ++ ++/* ++**ConNmv_imm_imm_reg: ++** li a5,9998336 ++** addi a4,a0,-1000 ++** addi a5,a5,1664 ++** th.mvnez a1,zero,a4 ++** th.mveqz a5,zero,a4 ++** or a0,a1,a5 ++** ret ++*/ ++int ConNmv_imm_imm_reg(int x, int y){ ++ if (x != 1000) return 10000000; ++ return y; ++} ++ ++/* ++**ConNmv_imm_reg_reg: ++** addi a5,a0,-1000 ++** th.mveqz a1,zero,a5 ++** th.mvnez a2,zero,a5 ++** or a0,a1,a2 ++** ret ++*/ ++int ConNmv_imm_reg_reg(int x, int y, int z){ ++ if (x != 1000) return y; ++ return z; ++} ++ ++/* ++**ConNmv_reg_imm_reg: ++** sub a1,a0,a1 ++** li a0,10 ++** th.mveqz a0,zero,a1 ++** th.mvnez a2,zero,a1 ++** or a0,a0,a2 ++** ret ++*/ ++int ConNmv_reg_imm_reg(int x, int y, int z){ ++ if (x != y) return 10; ++ return z; ++} ++ ++/* ++**ConNmv_reg_reg_reg: ++** sub a1,a0,a1 ++** th.mveqz a2,zero,a1 ++** th.mvnez a3,zero,a1 ++** or a0,a2,a3 ++** ret ++*/ ++int ConNmv_reg_reg_reg(int x, int y, int z, int n){ ++ if (x != y) return z; ++ return n; ++} ++ ++ ++/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_xtheadcondmov1p0\"" } } */ +diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-indirect-rv64.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-indirect-rv64.c +new file mode 100644 +index 00000000000..a1982fd90bd +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-indirect-rv64.c +@@ -0,0 +1,116 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -march=rv64gc_xtheadcondmov -mabi=lp64d -mriscv-attribute" } */ ++/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */ ++/* { dg-final { check-function-bodies "**" "" } } */ ++ ++/* ++**ConEmv_imm_imm_reg: ++** addi a5,a0,-1000 ++** li a0,10 ++** th.mvnez a0,zero,a5 ++** th.mveqz a1,zero,a5 ++** or a0,a0,a1 ++** ret ++*/ ++int ConEmv_imm_imm_reg(int x, int y){ ++ if (x == 1000) return 10; ++ return y; ++} ++ ++/* ++**ConEmv_imm_reg_reg: ++** addi a5,a0,-1000 ++** th.mvnez a1,zero,a5 ++** th.mveqz a2,zero,a5 ++** or a0,a1,a2 ++** ret ++*/ ++int ConEmv_imm_reg_reg(int x, int y, int z){ ++ if (x == 1000) return y; ++ return z; ++} ++ ++/* ++**ConEmv_reg_imm_reg: ++** sub a1,a0,a1 ++** li a0,10 ++** th.mvnez a0,zero,a1 ++** th.mveqz a2,zero,a1 ++** or a0,a0,a2 ++** ret ++*/ ++int ConEmv_reg_imm_reg(int x, int y, int z){ ++ if (x == y) return 10; ++ return z; ++} ++ ++/* ++**ConEmv_reg_reg_reg: ++** sub a1,a0,a1 ++** th.mvnez a2,zero,a1 ++** th.mveqz a3,zero,a1 ++** or a0,a2,a3 ++** ret ++*/ ++int ConEmv_reg_reg_reg(int x, int y, int z, int n){ ++ if (x == y) return z; ++ return n; ++} ++ ++/* ++**ConNmv_imm_imm_reg: ++** li a5,9998336 ++** addi a4,a0,-1000 ++** addi a5,a5,1664 ++** th.mvnez a1,zero,a4 ++** th.mveqz a5,zero,a4 ++** or a0,a1,a5 ++** ret ++*/ ++int ConNmv_imm_imm_reg(int x, int y){ ++ if (x != 1000) return 10000000; ++ return y; ++} ++ ++/* ++**ConNmv_imm_reg_reg: ++** addi a5,a0,-1000 ++** th.mveqz a1,zero,a5 ++** th.mvnez a2,zero,a5 ++** or a0,a1,a2 ++** ret ++*/ ++int ConNmv_imm_reg_reg(int x, int y, int z){ ++ if (x != 1000) return y; ++ return z; ++} ++ ++/* ++**ConNmv_reg_imm_reg: ++** sub a1,a0,a1 ++** li a0,10 ++** th.mveqz a0,zero,a1 ++** th.mvnez a2,zero,a1 ++** or a0,a0,a2 ++** ret ++*/ ++int ConNmv_reg_imm_reg(int x, int y, int z){ ++ if (x != y) return 10; ++ return z; ++} ++ ++/* ++**ConNmv_reg_reg_reg: ++** sub a1,a0,a1 ++** th.mveqz a2,zero,a1 ++** th.mvnez a3,zero,a1 ++** or a0,a2,a3 ++** ret ++*/ ++int ConNmv_reg_reg_reg(int x, int y, int z, int n){ ++ if (x != y) return z; ++ return n; ++} ++ ++ ++/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_xtheadcondmov1p0\"" } } */ +-- +2.39.3 diff --git a/system/gcc/201-ada.patch b/system/gcc/201-ada.patch index acb1e1f1b..00a6422d7 100644 --- a/system/gcc/201-ada.patch +++ b/system/gcc/201-ada.patch @@ -1,29 +1,8 @@ -diff --git a/gcc/ada/adadecode.c b/gcc/ada/adadecode.c -index a63b7e7641b0..92155ef2025a 100644 ---- a/gcc/ada/adadecode.c -+++ b/gcc/ada/adadecode.c -@@ -29,6 +29,7 @@ - * * - ****************************************************************************/ - -+#include "adaint.h" /* for a macro version of xstrdup. */ - - #if defined(IN_RTS) - #include "tconfig.h" -@@ -42,8 +43,6 @@ - #include - #include - --#include "adaint.h" /* for a macro version of xstrdup. */ -- - #ifndef ISDIGIT - #define ISDIGIT(c) isdigit(c) - #endif diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c index 414346558654..2586a1368903 100644 --- a/gcc/ada/adaint.c +++ b/gcc/ada/adaint.c -@@ -85,6 +85,8 @@ +@@ -101,6 +101,8 @@ #define _LARGEFILE64_SOURCE 1 #endif @@ -32,7 +11,7 @@ index 414346558654..2586a1368903 100644 #ifdef IN_RTS #include "tconfig.h" #include "tsystem.h" -@@ -202,8 +204,6 @@ UINT __gnat_current_ccs_encoding; +@@ -243,8 +245,6 @@ UINT __gnat_current_ccs_encoding; #include #endif @@ -45,7 +24,7 @@ diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h index 0d12f7e90209..74182446d4ac 100644 --- a/gcc/ada/adaint.h +++ b/gcc/ada/adaint.h -@@ -316,6 +316,7 @@ extern void *__gnat_lwp_self (void); +@@ -319,6 +319,7 @@ extern void *__gnat_lwp_self (void); /* Routines for interface to required CPU set primitives */ @@ -64,8 +43,8 @@ index f62cf1eb37dc..0b6c5fe6f0df 100644 +#include "adaint.h" + #ifdef IN_RTS - #include "tconfig.h" - #include "tsystem.h" + #include "runtime.h" + #include @@ -51,8 +53,6 @@ #include "system.h" #endif @@ -86,9 +65,9 @@ index ff97abe36ef1..56aa3477c8cd 100644 +#include "adaint.h" + #ifdef IN_RTS - #include "tconfig.h" - #include "tsystem.h" -@@ -38,8 +40,6 @@ + #include "runtime.h" + #include +@@ -37,8 +39,6 @@ #include "system.h" #endif @@ -101,38 +80,16 @@ diff --git a/gcc/ada/cstreams.c b/gcc/ada/cstreams.c index cdcb531e2b3f..dde6b9948089 100644 --- a/gcc/ada/cstreams.c +++ b/gcc/ada/cstreams.c -@@ -52,6 +52,8 @@ - #include "vxWorks.h" - #endif - -+#include "adaint.h" -+ - #ifdef IN_RTS - #include "tconfig.h" - #include "tsystem.h" -@@ -61,8 +63,6 @@ - #include "system.h" - #endif - --#include "adaint.h" -- - #ifdef __cplusplus - extern "C" { - #endif -diff --git a/gcc/ada/exit.c b/gcc/ada/exit.c -index 6274571c6f04..336b0f8f386b 100644 ---- a/gcc/ada/exit.c -+++ b/gcc/ada/exit.c -@@ -33,6 +33,8 @@ +@@ -58,6 +58,8 @@ #include "vxWorks.h" #endif +#include "adaint.h" + #ifdef IN_RTS - #include "tconfig.h" - #include "tsystem.h" -@@ -42,8 +44,6 @@ + #include + #else +@@ -65,8 +67,6 @@ #include "system.h" #endif @@ -141,11 +98,11 @@ index 6274571c6f04..336b0f8f386b 100644 #ifdef __cplusplus extern "C" { #endif -diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in +diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 0258f106d404..0416244ae428 100644 ---- a/gcc/ada/gcc-interface/Makefile.in -+++ b/gcc/ada/gcc-interface/Makefile.in -@@ -1574,7 +1574,7 @@ ifeq ($(strip $(filter-out powerpc% linux%,$(target_cpu) $(target_os))),) +--- a/gcc/ada/Makefile.rtl ++++ b/gcc/ada/Makefile.rtl +@@ -2205,7 +2205,7 @@ ifeq ($(strip $(filter-out powerpc% linux%,$(target_cpu) $(target_os))),) endif # ARM linux, GNU eabi @@ -165,9 +122,9 @@ index 5088ecffc4f1..02a45b3ce7ca 100644 +#include "adaint.h" + #ifdef IN_RTS - #include "tconfig.h" - #include "tsystem.h" -@@ -65,7 +67,6 @@ + + #ifdef STANDALONE +@@ -71,7 +73,6 @@ #include "system.h" #endif @@ -179,7 +136,7 @@ diff --git a/gcc/ada/libgnarl/s-osinte__linux.ads b/gcc/ada/libgnarl/s-osinte__l index 5bf4a5fe1d26..c52cc70dfbab 100644 --- a/gcc/ada/libgnarl/s-osinte__linux.ads +++ b/gcc/ada/libgnarl/s-osinte__linux.ads -@@ -394,12 +394,6 @@ package System.OS_Interface is +@@ -403,12 +403,6 @@ package System.OS_Interface is PTHREAD_RWLOCK_PREFER_WRITER_NP : constant := 1; PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP : constant := 2; @@ -192,7 +149,7 @@ index 5bf4a5fe1d26..c52cc70dfbab 100644 function pthread_rwlock_init (mutex : access pthread_rwlock_t; attr : access pthread_rwlockattr_t) return int; -@@ -464,11 +458,6 @@ package System.OS_Interface is +@@ -470,11 +464,6 @@ package System.OS_Interface is protocol : int) return int; pragma Import (C, pthread_mutexattr_setprotocol); @@ -208,7 +165,7 @@ diff --git a/gcc/ada/libgnarl/s-taprop__linux.adb b/gcc/ada/libgnarl/s-taprop__l index e55cd65e54f6..32d72b3980a6 100644 --- a/gcc/ada/libgnarl/s-taprop__linux.adb +++ b/gcc/ada/libgnarl/s-taprop__linux.adb -@@ -202,9 +202,6 @@ package body System.Task_Primitives.Operations is +@@ -198,9 +198,6 @@ package body System.Task_Primitives.Operations is pragma Import (C, GNAT_pthread_condattr_setup, "__gnat_pthread_condattr_setup"); @@ -218,7 +175,7 @@ index e55cd65e54f6..32d72b3980a6 100644 -- We do not have pragma Linker_Options ("-lcap"); here, because this -- library is not present on many Linux systems. 'libcap' is the Linux -- "capabilities" library, called by __gnat_has_cap_sys_nice. -@@ -214,38 +211,6 @@ package body System.Task_Primitives.Operations is +@@ -210,38 +207,6 @@ package body System.Task_Primitives.Operations is -- Convert Ada priority to Linux priority. Priorities are 1 .. 99 on -- GNU/Linux, so we map 0 .. 98 to 1 .. 99. @@ -251,13 +208,13 @@ index e55cd65e54f6..32d72b3980a6 100644 - return Ceiling_Support; - end Get_Ceiling_Support; - -- pragma Warnings (Off, "non-static call not allowed in preelaborated unit"); +- pragma Warnings (Off, "non-preelaborable call not allowed*"); - Ceiling_Support : constant Boolean := Get_Ceiling_Support; -- pragma Warnings (On, "non-static call not allowed in preelaborated unit"); +- pragma Warnings (On, "non-preelaborable call not allowed*"); -- True if the locking policy is Ceiling_Locking, and the current process -- has permission to use this policy. The process has permission if it is -- running as 'root', or if the capability was set by the setcap command, -@@ -348,7 +313,9 @@ package body System.Task_Primitives.Operations is +@@ -344,7 +309,9 @@ package body System.Task_Primitives.Operations is -- Init_Mutex -- ---------------- @@ -267,7 +224,7 @@ index e55cd65e54f6..32d72b3980a6 100644 Mutex_Attr : aliased pthread_mutexattr_t; Result, Result_2 : C.int; -@@ -360,16 +327,7 @@ package body System.Task_Primitives.Operations is +@@ -356,16 +323,7 @@ package body System.Task_Primitives.Operations is return Result; end if; @@ -285,7 +242,7 @@ index e55cd65e54f6..32d72b3980a6 100644 Result := pthread_mutexattr_setprotocol (Mutex_Attr'Access, PTHREAD_PRIO_INHERIT); pragma Assert (Result = 0); -@@ -409,11 +367,6 @@ package body System.Task_Primitives.Operations is +@@ -405,11 +363,6 @@ package body System.Task_Primitives.Operations is Result := pthread_rwlockattr_init (RWlock_Attr'Access); pragma Assert (Result = 0); @@ -301,91 +258,31 @@ diff --git a/gcc/ada/libgnat/s-dwalin.adb b/gcc/ada/libgnat/s-dwalin.adb index a857b67132af..1e2bb4c545ad 100644 --- a/gcc/ada/libgnat/s-dwalin.adb +++ b/gcc/ada/libgnat/s-dwalin.adb -@@ -382,7 +382,7 @@ package body System.Dwarf_Lines is - - function Low (C : Dwarf_Context) return Address is - begin -- return C.Low; -+ return To_Address (To_Integer (C.Low) + C.Load_Slide); - end Low; - - ---------- -@@ -1210,19 +1210,21 @@ package body System.Dwarf_Lines is - -- Discard symbols whose length is 0 - Sz := uint32 (Size (S)); - -- -- Try to filter symbols at the same address. This is a best -- -- effort as they might not be consecutive. -- Addr := uint32 (Value (S) - uint64 (C.Low)); -- if Sz > 0 and then Addr /= Prev_Addr then -- Nbr_Symbols := Nbr_Symbols + 1; -- Prev_Addr := Addr; -- -- if Phase = 2 then -- C.Cache (Nbr_Symbols) := -- (First => Addr, -- Size => Sz, -- Sym => uint32 (Off (S)), -- Line => 0); -+ if Sz > 0 then -+ -- Try to filter symbols at the same address. This is a best -+ -- effort as they might not be consecutive. -+ Addr := uint32 (Value (S) - uint64 (C.Low)); -+ if Addr /= Prev_Addr then -+ Nbr_Symbols := Nbr_Symbols + 1; -+ Prev_Addr := Addr; -+ -+ if Phase = 2 then -+ C.Cache (Nbr_Symbols) := -+ (First => Addr, -+ Size => Sz, -+ Sym => uint32 (Off (S)), -+ Line => 0); -+ end if; - end if; - end if; - -@@ -1267,6 +1269,10 @@ package body System.Dwarf_Lines is +@@ -1538,7 +1538,11 @@ package body System.Dwarf_Lines is -- Read table + loop - Read_Aranges_Entry (C, Ar_Start, Ar_Len); + Read_Aranges_Entry (C, Addr_Size, Ar_Start, Ar_Len); + -- Skip references to discarded sections + while Ar_Start = 0 and Ar_Len /= 0 loop -+ Read_Aranges_Entry (C, Ar_Start, Ar_Len); ++ Read_Aranges_Entry (C, Addr_Size, Ar_Start, Ar_Len); + end loop; - exit when Ar_Start = 0 and Ar_Len = 0; + exit when Ar_Start = Null_Address and Ar_Len = 0; Len := uint32 (Ar_Len); -diff --git a/gcc/ada/libgnat/s-trasym__dwarf.adb b/gcc/ada/libgnat/s-trasym__dwarf.adb -index db7c5eb4cdd8..3cd60ecbc37b 100644 ---- a/gcc/ada/libgnat/s-trasym__dwarf.adb -+++ b/gcc/ada/libgnat/s-trasym__dwarf.adb -@@ -123,7 +123,8 @@ package body System.Traceback.Symbolic is - -- Return the String contained in Item, up until the first NUL character - - pragma Warnings (Off, "*Add_Module_To_Cache*"); -- procedure Add_Module_To_Cache (Module_Name : String); -+ procedure Add_Module_To_Cache (Module_Name : String; -+ Load_Address : System.Address); - -- To be called by Build_Cache_For_All_Modules to add a new module to the - -- list. May not be referenced. - -@@ -217,12 +218,13 @@ package body System.Traceback.Symbolic is - -- Add_Module_To_Cache -- - ------------------------- - -- procedure Add_Module_To_Cache (Module_Name : String) is -+ procedure Add_Module_To_Cache (Module_Name : String; -+ Load_Address : System.Address) is - Module : Module_Cache_Acc; - Success : Boolean; - begin - Module := new Module_Cache; -- Init_Module (Module.all, Success, Module_Name); -+ Init_Module (Module.all, Success, Module_Name, Load_Address); - if not Success then - Free (Module); - return; +diff --git a/gcc/ada/libgnat/s-parame.ads b/gcc/ada/libgnat/s-parame.ads +index 3d6e345a1ba9..cfe0b4d3ca6c 100644 +--- a/gcc/ada/libgnat/s-parame.ads ++++ b/gcc/ada/libgnat/s-parame.ads +@@ -102,7 +102,7 @@ package System.Parameters is + -- Characteristics of time_t type -- + ------------------------------------ + +- time_t_bits : constant := Long_Integer'Size; ++ time_t_bits : constant := Long_Long_Integer'Size; + -- Number of bits in type time_t + + ---------------------------------------------- diff --git a/gcc/ada/libgnat/s-tsmona__linux.adb b/gcc/ada/libgnat/s-tsmona__linux.adb index cbebd0652048..c882aa64a6e2 100644 --- a/gcc/ada/libgnat/s-tsmona__linux.adb @@ -468,7 +365,7 @@ index cbebd0652048..c882aa64a6e2 100644 - while lm /= null loop - if Big_String_Conv.To_Pointer (lm.l_name) (1) /= ASCII.NUL then - -- Discard non-file (like the executable itself or the gate). -- Add_Module_To_Cache (Value (lm.l_name)); +- Add_Module_To_Cache (Value (lm.l_name), lm.l_addr); - end if; - lm := lm.l_next; - end loop; @@ -487,8 +384,8 @@ index c101d968a851..43cdd51e8320 100644 +#include "adaint.h" + #ifdef IN_RTS - #include "tconfig.h" - #include "tsystem.h" + #include "runtime.h" + #include @@ -53,8 +55,6 @@ #endif #endif @@ -509,9 +406,9 @@ index 70ad6cd3282a..eb92de1b2137 100644 +#include "adaint.h" + #ifdef IN_RTS - #include "tconfig.h" - #include "tsystem.h" -@@ -40,7 +42,6 @@ + #include "runtime.h" + #else +@@ -39,7 +41,6 @@ #include "system.h" #endif @@ -531,8 +428,8 @@ index 98b3901cb16f..98db6a14c2d5 100644 + #ifdef IN_RTS #define POSIX - #include "tconfig.h" -@@ -72,8 +74,6 @@ + #include "runtime.h" +@@ -74,8 +76,6 @@ extern struct tm *localtime_r(const time_t *, struct tm *); #endif @@ -541,25 +438,3 @@ index 98b3901cb16f..98db6a14c2d5 100644 /* Don't use macros versions of this functions on VxWorks since they cause imcompatible changes in some VxWorks versions */ #ifdef __vxworks -diff --git a/gcc/ada/terminals.c b/gcc/ada/terminals.c -index 7025f57d645e..074845584958 100644 ---- a/gcc/ada/terminals.c -+++ b/gcc/ada/terminals.c -@@ -1112,7 +1112,6 @@ __gnat_setup_winsize (void *desc, int rows, int columns) - (HP-UX) */ - #if !defined (__hpux__) && !defined (BSD) && !defined (__APPLE__) \ - && !defined (__rtems__) && !defined (__QNXNTO__) --# include - #endif - - #include -@@ -1159,7 +1158,8 @@ __gnat_setup_winsize (void *desc, int rows, int columns) - #if defined (__APPLE__) || defined (BSD) - #define USE_OPENPTY - #elif defined (__linux__) --#define USE_GETPT -+#include -+#define USE_OPENPTY - #elif defined (__sun__) - #define USE_CLONE_DEVICE "/dev/ptmx" - #elif defined (_AIX) diff --git a/system/gcc/202-ibm-ldbl.patch b/system/gcc/202-ibm-ldbl.patch index bdf5c75d9..d67cbbf46 100644 --- a/system/gcc/202-ibm-ldbl.patch +++ b/system/gcc/202-ibm-ldbl.patch @@ -32,7 +32,7 @@ index 4f6d4c4..fa93bb6 100644 @@ -1,3 +1,3 @@ SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-glibc.ver --HOST_LIBGCC2_CFLAGS += -mlong-double-128 -mno-minimal-toc -+HOST_LIBGCC2_CFLAGS += -mlong-double-128 -mno-gnu-attribute -mno-minimal-toc +-HOST_LIBGCC2_CFLAGS += -mlong-double-128 ++HOST_LIBGCC2_CFLAGS += -mlong-double-128 -mno-gnu-attribute -- 2.24.0 diff --git a/system/gcc/205-nopie.patch b/system/gcc/205-nopie.patch index e3da94d10..262749d62 100644 --- a/system/gcc/205-nopie.patch +++ b/system/gcc/205-nopie.patch @@ -12,7 +12,7 @@ diff --git a/gcc/configure b/gcc/configure index 1c6e340..7e8b5d6 100755 --- a/gcc/configure +++ b/gcc/configure -@@ -29390,6 +29390,33 @@ fi +@@ -32441,6 +32441,33 @@ fi $as_echo "$gcc_cv_no_pie" >&6; } if test "$gcc_cv_no_pie" = "yes"; then NO_PIE_FLAG="-no-pie" @@ -50,7 +50,7 @@ diff --git a/gcc/configure.ac b/gcc/configure.ac index 6c1dcd9..0ca7647 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac -@@ -6098,6 +6098,19 @@ AC_CACHE_CHECK([for -no-pie option], +@@ -7621,6 +7621,19 @@ AC_CACHE_CHECK([for -no-pie option], LDFLAGS="$saved_LDFLAGS"]) if test "$gcc_cv_no_pie" = "yes"; then NO_PIE_FLAG="-no-pie" diff --git a/system/gcc/206-arm-unwind-functionise.patch b/system/gcc/206-arm-unwind-functionise.patch index 0cee39e54..a5cc9236e 100644 --- a/system/gcc/206-arm-unwind-functionise.patch +++ b/system/gcc/206-arm-unwind-functionise.patch @@ -1,6 +1,6 @@ --- gcc-8.5.0/libgcc/config/arm/unwind-arm.c.old 2021-05-14 03:42:10.000000000 -0500 +++ gcc-8.5.0/libgcc/config/arm/unwind-arm.c 2022-12-24 20:04:04.085095067 -0600 -@@ -510,22 +510,22 @@ +@@ -539,22 +539,22 @@ return __gnu_unwind_pr_common (state, ucbp, context, 2); } @@ -30,7 +30,7 @@ _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1)); --- gcc-8.5.0/libgcc/config/arm/unwind-arm.h.old 2021-05-14 03:42:10.000000000 -0500 +++ gcc-8.5.0/libgcc/config/arm/unwind-arm.h 2022-12-24 20:03:41.415095129 -0600 -@@ -72,7 +72,7 @@ +@@ -97,7 +97,7 @@ { return _URC_FAILURE; } @@ -41,7 +41,7 @@ (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1) --- gcc-8.5.0/gcc/ada/raise-gcc.c.old 2021-05-14 03:42:08.000000000 -0500 +++ gcc-8.5.0/gcc/ada/raise-gcc.c 2022-12-24 22:43:03.605084414 -0600 -@@ -91,7 +91,9 @@ +@@ -90,7 +90,9 @@ This is a hack ???, the real fix is to link gnat1/gnatbind with the runtime of the build compiler. */ # ifdef EH_MECHANISM_arm diff --git a/system/gcc/320-libffi-gnulinux.patch b/system/gcc/320-libffi-gnulinux.patch deleted file mode 100644 index b3b4fc931..000000000 --- a/system/gcc/320-libffi-gnulinux.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/libffi/closures.c.orig b/libffi/closures.c -index 721ff00..22a699c 100644 ---- a/libffi/src/closures.c.orig -+++ b/libffi/src/closures.c -@@ -34,7 +34,7 @@ - #include - - #if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE --# if __gnu_linux__ && !defined(__ANDROID__) -+# if __linux__ && !defined(__ANDROID__) - /* This macro indicates it may be forbidden to map anonymous memory - with both write and execute permission. Code compiled when this - option is defined will attempt to map such pages once, but if it diff --git a/system/gcc/330-gccgo-link-to-ucontext.patch b/system/gcc/330-gccgo-link-to-ucontext.patch index 8aa60ca54..63446f23c 100644 --- a/system/gcc/330-gccgo-link-to-ucontext.patch +++ b/system/gcc/330-gccgo-link-to-ucontext.patch @@ -1,6 +1,6 @@ --- gcc-6.4.0/Makefile.in.old 2018-06-21 22:16:35.167781541 -0500 +++ gcc-6.4.0/Makefile.in 2018-06-22 00:36:13.849486086 -0500 -@@ -41332,7 +41332,7 @@ +@@ -52324,7 +52324,7 @@ esac; \ module_srcdir=libgo; \ rm -f no-such-file || : ; \ diff --git a/system/gcc/331-gccgo-use-real-off_t-type.patch b/system/gcc/331-gccgo-use-real-off_t-type.patch index 1c8c43e9e..c652dd448 100644 --- a/system/gcc/331-gccgo-use-real-off_t-type.patch +++ b/system/gcc/331-gccgo-use-real-off_t-type.patch @@ -1,30 +1,11 @@ ---- gcc-6.4.0/libgo/go/syscall/libcall_linux.go.old 2016-02-03 15:58:02.419872000 -0600 -+++ gcc-6.4.0/libgo/go/syscall/libcall_linux.go 2018-06-22 00:56:31.478280552 -0500 -@@ -355,19 +355,19 @@ - //sys Setxattr(path string, attr string, data []byte, flags int) (err error) - //setxattr(path *byte, name *byte, value *byte, size Size_t, flags _C_int) _C_int +--- gcc-13.3.0/libgo/sysinfo.c.old 2024-05-22 20:29:51.727156372 -0500 ++++ gcc-13.3.0/libgo/sysinfo.c 2024-05-22 20:35:39.499799256 -0500 +@@ -363,6 +363,8 @@ + // loff_t can be defined as a macro; for -fgo-dump-spec make sure we + // see a typedef. + typedef loff_t libgo_loff_t_type; ++#else ++typedef off_t libgo_loff_t_type; + #endif --//sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, err error) --//splice(rfd _C_int, roff *_loff_t, wfd _C_int, woff *_loff_t, len Size_t, flags _C_uint) Ssize_t -+//sys splice(rfd int, roff *_off_t, wfd int, woff *_off_t, len int, flags int) (n int64, err error) -+//splice(rfd _C_int, roff *_off_t, wfd _C_int, woff *_off_t, len Size_t, flags _C_uint) Ssize_t - func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) { -- var lroff _loff_t -- var plroff *_loff_t -+ var lroff _off_t -+ var plroff *_off_t - if roff != nil { -- lroff = _loff_t(*roff) -+ lroff = _off_t(*roff) - plroff = &lroff - } -- var lwoff _loff_t -- var plwoff *_loff_t -+ var lwoff _off_t -+ var plwoff *_off_t - if woff != nil { -- lwoff = _loff_t(*woff) -+ lwoff = _off_t(*woff) - plwoff = &lwoff - } - n, err = splice(rfd, plroff, wfd, plwoff, len, flags) + #if defined(HAVE_OFF64_T) diff --git a/system/gcc/332-gccgo-sysinfo.patch b/system/gcc/332-gccgo-sysinfo.patch index 822bc53c9..8c02cb6e0 100644 --- a/system/gcc/332-gccgo-sysinfo.patch +++ b/system/gcc/332-gccgo-sysinfo.patch @@ -1,6 +1,6 @@ --- gcc-8.3.0/libgo/sysinfo.c.old 2018-06-22 14:25:34.000000000 +0000 +++ gcc-8.3.0/libgo/sysinfo.c 2019-02-27 20:18:38.740000000 +0000 -@@ -73,9 +73,6 @@ +@@ -78,9 +78,6 @@ #include #include #include diff --git a/system/gcc/333-gccgo-signal-ppc64.patch b/system/gcc/333-gccgo-signal-ppc64.patch deleted file mode 100644 index 304b71733..000000000 --- a/system/gcc/333-gccgo-signal-ppc64.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- gcc-8.3.0/libgo/runtime/go-signal.c.old 2017-08-18 20:17:26.000000000 +0000 -+++ gcc-8.3.0/libgo/runtime/go-signal.c 2019-02-27 20:25:02.560000000 +0000 -@@ -222,7 +222,7 @@ - #endif - #ifdef __PPC__ - #ifdef __linux__ -- ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.regs->nip; -+ ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gp_regs[32]; - #endif - #ifdef _AIX - ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar; diff --git a/system/gcc/334-gccgo-signal-shell.patch b/system/gcc/334-gccgo-signal-shell.patch index 5c7405c4f..68fa80bca 100644 --- a/system/gcc/334-gccgo-signal-shell.patch +++ b/system/gcc/334-gccgo-signal-shell.patch @@ -1,6 +1,6 @@ --- gcc-8.3.0/libgo/mksigtab.sh.old 2017-11-22 00:27:29.000000000 +0000 +++ gcc-8.3.0/libgo/mksigtab.sh 2019-03-02 22:01:17.530000000 +0000 -@@ -82,7 +82,7 @@ +@@ -86,7 +86,7 @@ checksig _SIGEMT '{_SigThrow, "SIGEMT: emulate instruction executed"}' checksig _SIGINFO '{_SigNotify, "SIGINFO: status request from keyboard"}' checksig _SIGTHR '{_SigNotify, "SIGTHR: reserved"}' @@ -9,17 +9,3 @@ checksig _SIGWAITING '{_SigNotify, "SIGWAITING: reserved signal no longer used by"}' checksig _SIGLWP '{_SigNotify, "SIGLWP: reserved signal no longer used by"}' checksig _SIGFREEZE '{_SigNotify, "SIGFREEZE: special signal used by CPR"}' -@@ -94,10 +94,12 @@ - - # Special handling of signals 32 and 33 on GNU/Linux systems, - # because they are special to glibc. -+# Signal 34 is additionally special to Linux systems with musl. - if test "${GOOS}" = "linux"; then -- SIGLIST=$SIGLIST"_32__33_" -+ SIGLIST=$SIGLIST"_32__33__34_" - echo ' 32: {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */' - echo ' 33: {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */' -+ echo ' 34: {_SigSetStack + _SigUnblock, "signal 34"}, /* see issue 30062 */' - fi - - if test "${GOOS}" = "aix"; then diff --git a/system/gcc/335-gccgo-signal-ppc32.patch b/system/gcc/335-gccgo-signal-ppc32.patch index f44444948..1e52b925e 100644 --- a/system/gcc/335-gccgo-signal-ppc32.patch +++ b/system/gcc/335-gccgo-signal-ppc32.patch @@ -1,6 +1,6 @@ --- gcc-8.3.0/libgo/runtime/go-signal.c.old 2019-03-02 22:02:02.250000000 +0000 +++ gcc-8.3.0/libgo/runtime/go-signal.c 2019-03-03 02:04:13.220000000 +0000 -@@ -222,7 +222,11 @@ +@@ -249,7 +249,11 @@ #endif #ifdef __PPC__ #ifdef __linux__ diff --git a/system/gcc/336-gccgo-mmap64.patch b/system/gcc/336-gccgo-mmap64.patch index 23b4cebc8..0d4ab19b8 100644 --- a/system/gcc/336-gccgo-mmap64.patch +++ b/system/gcc/336-gccgo-mmap64.patch @@ -1,15 +1,15 @@ --- gcc-8.3.0/libgo/go/runtime/mem_gccgo.go.old 2018-01-09 01:23:08.000000000 +0000 +++ gcc-8.3.0/libgo/go/runtime/mem_gccgo.go 2019-03-03 05:15:33.010000000 +0000 -@@ -16,7 +16,7 @@ - //go:linkname sysFree runtime.sysFree +@@ -15,7 +15,7 @@ + //go:linkname sysFree - //extern mmap + //extern __go_mmap -func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uintptr) unsafe.Pointer +func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off int64) unsafe.Pointer //extern munmap func munmap(addr unsafe.Pointer, length uintptr) int32 -@@ -41,7 +41,7 @@ +@@ -37,7 +37,7 @@ } } @@ -18,12 +18,3 @@ p := sysMmap(addr, n, prot, flags, fd, off) if uintptr(p) == _MAP_FAILED { return nil, errno() -@@ -84,7 +84,7 @@ - return true - } - --func mmap_fixed(v unsafe.Pointer, n uintptr, prot, flags, fd int32, offset uintptr) (unsafe.Pointer, int) { -+func mmap_fixed(v unsafe.Pointer, n uintptr, prot, flags, fd int32, offset int64) (unsafe.Pointer, int) { - p, err := mmap(v, n, prot, flags, fd, offset) - // On some systems, mmap ignores v without - // MAP_FIXED, so retry if the address space is free. diff --git a/system/gcc/337-gccgo-signal-sig34.patch b/system/gcc/337-gccgo-signal-sig34.patch deleted file mode 100644 index 757d2f216..000000000 --- a/system/gcc/337-gccgo-signal-sig34.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- gcc-8.3.0/libgo/go/runtime/signal_gccgo.go.old 2018-01-10 05:15:52.000000000 +0000 -+++ gcc-8.3.0/libgo/go/runtime/signal_gccgo.go 2019-03-03 05:19:28.000000000 +0000 -@@ -111,7 +111,7 @@ - if sigaction(i, nil, &sa) < 0 { - // On GNU/Linux glibc rejects attempts to call - // sigaction with signal 32 (SIGCANCEL) or 33 (SIGSETXID). -- if GOOS == "linux" && (i == 32 || i == 33) { -+ if GOOS == "linux" && (i == 32 || i == 33 || i == 34) { - return _SIG_DFL - } - throw("sigaction read failure") diff --git a/system/gcc/338-gccgo-syscall.patch b/system/gcc/338-gccgo-syscall.patch deleted file mode 100644 index a4ecb5b6b..000000000 --- a/system/gcc/338-gccgo-syscall.patch +++ /dev/null @@ -1,115 +0,0 @@ -diff -Naur gcc-8.3.0-orig/libgo/go/runtime/stubs.go gcc-8.3.0/libgo/go/runtime/stubs.go ---- gcc-8.3.0-orig/libgo/go/runtime/stubs.go 2019-04-25 03:03:52.311215191 +0000 -+++ gcc-8.3.0/libgo/go/runtime/stubs.go 2019-04-25 03:03:27.973824045 +0000 -@@ -284,8 +284,7 @@ - // For gccgo this is in the C code. - func osyield() - --// For gccgo this can be called directly. --//extern syscall -+//extern __go_syscall6 - func syscall(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr - - // For gccgo, to communicate from the C code to the Go code. -diff -Naur gcc-8.3.0-orig/libgo/go/syscall/syscall_unix.go gcc-8.3.0/libgo/go/syscall/syscall_unix.go ---- gcc-8.3.0-orig/libgo/go/syscall/syscall_unix.go 2019-04-25 03:04:55.064488337 +0000 -+++ gcc-8.3.0/libgo/go/syscall/syscall_unix.go 2019-04-25 03:08:23.612133013 +0000 -@@ -19,11 +19,8 @@ - Stderr = 2 - ) - --//extern syscall --func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 -- --//extern syscall --func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 -+//extern __go_syscall6 -+func syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr - - const ( - darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8 -@@ -38,14 +35,7 @@ - func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { - Entersyscall() - SetErrno(0) -- var r uintptr -- if unsafe.Sizeof(r) == 4 { -- r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0) -- r = uintptr(r1) -- } else { -- r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0) -- r = uintptr(r1) -- } -+ r := syscall6(trap, a1, a2, a3, 0, 0, 0) - err = GetErrno() - Exitsyscall() - return r, 0, err -@@ -54,47 +44,22 @@ - func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { - Entersyscall() - SetErrno(0) -- var r uintptr -- if unsafe.Sizeof(r) == 4 { -- r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), -- int32(a4), int32(a5), int32(a6)) -- r = uintptr(r1) -- } else { -- r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), -- int64(a4), int64(a5), int64(a6)) -- r = uintptr(r1) -- } -+ r := syscall6(trap, a1, a2, a3, a4, a5, a6) - err = GetErrno() - Exitsyscall() - return r, 0, err - } - - func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { -- var r uintptr - SetErrno(0) -- if unsafe.Sizeof(r) == 4 { -- r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0) -- r = uintptr(r1) -- } else { -- r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0) -- r = uintptr(r1) -- } -+ r := syscall6(trap, a1, a2, a3, 0, 0, 0) - err = GetErrno() - return r, 0, err - } - - func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { -- var r uintptr - SetErrno(0) -- if unsafe.Sizeof(r) == 4 { -- r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), -- int32(a4), int32(a5), int32(a6)) -- r = uintptr(r1) -- } else { -- r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), -- int64(a4), int64(a5), int64(a6)) -- r = uintptr(r1) -- } -+ r := syscall6(trap, a1, a2, a3, a4, a5, a6) - err = GetErrno() - return r, 0, err - } -diff -Naur gcc-8.3.0-orig/libgo/runtime/go-varargs.c gcc-8.3.0/libgo/runtime/go-varargs.c ---- gcc-8.3.0-orig/libgo/runtime/go-varargs.c 2015-11-06 19:15:45.000000000 +0000 -+++ gcc-8.3.0/libgo/runtime/go-varargs.c 2019-04-25 03:14:11.404851275 +0000 -@@ -89,3 +89,14 @@ - } - - #endif -+ -+// __go_syscall6 is called by both the runtime and syscall packages. -+// We use uintptr_t to make sure that the types match, since the Go -+// and C "int" types are not the same. -+ -+uintptr_t -+__go_syscall6(uintptr_t flag, uintptr_t a1, uintptr_t a2, uintptr_t a3, -+ uintptr_t a4, uintptr_t a5, uintptr_t a6) -+{ -+ return syscall (flag, a1, a2, a3, a4, a5, a6); -+} diff --git a/system/gcc/339-gccgo-errstr.patch b/system/gcc/339-gccgo-errstr.patch deleted file mode 100644 index f78d18aa4..000000000 --- a/system/gcc/339-gccgo-errstr.patch +++ /dev/null @@ -1,45 +0,0 @@ ---- gcc-8.3.0/libgo/go/syscall/errstr_linux.go 2016-08-06 00:36:33.000000000 +0000 -+++ /dev/null 2019-04-08 15:05:18.560000000 +0000 -@@ -1,31 +0,0 @@ --// errstr_linux.go -- GNU/Linux specific error strings. -- --// Copyright 2010 The Go Authors. All rights reserved. --// Use of this source code is governed by a BSD-style --// license that can be found in the LICENSE file. -- --// We use this rather than errstr.go because on GNU/Linux sterror_r --// returns a pointer to the error message, and may not use buf at all. -- --package syscall -- --import "unsafe" -- --//sysnb strerror_r(errnum int, b []byte) (errstr *byte) --//strerror_r(errnum _C_int, b *byte, len Size_t) *byte -- --func Errstr(errnum int) string { -- a := make([]byte, 128) -- p := strerror_r(errnum, a) -- b := (*[1000]byte)(unsafe.Pointer(p)) -- i := 0 -- for b[i] != 0 { -- i++ -- } -- // Lowercase first letter: Bad -> bad, but STREAM -> STREAM. -- if i > 1 && 'A' <= b[0] && b[0] <= 'Z' && 'a' <= b[1] && b[1] <= 'z' { -- c := b[0] + 'a' - 'A' -- return string(c) + string(b[1:i]) -- } -- return string(b[:i]) --} ---- gcc-8.3.0/libgo/go/syscall/errstr.go.old 2016-08-06 00:36:33.000000000 +0000 -+++ gcc-8.3.0/libgo/go/syscall/errstr.go 2019-04-25 05:41:27.915806277 +0000 -@@ -4,8 +4,6 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !linux -- - package syscall - - //sysnb strerror_r(errnum int, buf []byte) (err Errno) diff --git a/system/gcc/340-gccgo-time64-stat.patch b/system/gcc/340-gccgo-time64-stat.patch deleted file mode 100644 index 332712a13..000000000 --- a/system/gcc/340-gccgo-time64-stat.patch +++ /dev/null @@ -1,19 +0,0 @@ -There are more than one st_{a,m,c}tim fields in struct stat on time64 machines. - -Run the Go-isation on all of them. - ---- gcc-8.3.0/libgo/mksysinfo.sh.old 2018-11-09 15:29:52.000000000 +0000 -+++ gcc-8.3.0/libgo/mksysinfo.sh 2019-12-23 00:18:54.129911814 +0000 -@@ -468,9 +468,9 @@ - -e 's/st_size/Size/' \ - -e 's/st_blksize/Blksize/' \ - -e 's/st_blocks/Blocks/' \ -- -e 's/st_atim/Atim/' \ -- -e 's/st_mtim/Mtim/' \ -- -e 's/st_ctim/Ctim/' \ -+ -e 's/st_atim/Atim/g' \ -+ -e 's/st_mtim/Mtim/g' \ -+ -e 's/st_ctim/Ctim/g' \ - -e 's/\([^a-zA-Z0-9_]\)_timeval\([^a-zA-Z0-9_]\)/\1Timeval\2/g' \ - -e 's/\([^a-zA-Z0-9_]\)_timespec_t\([^a-zA-Z0-9_]\)/\1Timespec\2/g' \ - -e 's/\([^a-zA-Z0-9_]\)_st_timespec_t\([^a-zA-Z0-9_]\)/\1StTimespec\2/g' \ diff --git a/system/gcc/341-gccgo-libucontext-stack.patch b/system/gcc/341-gccgo-libucontext-stack.patch index 2befc5d32..cc88bda5a 100644 --- a/system/gcc/341-gccgo-libucontext-stack.patch +++ b/system/gcc/341-gccgo-libucontext-stack.patch @@ -4,15 +4,39 @@ This causes the Go frontend to sometimes go below the stack. On 32-bit Arm systems, this resulted in #832. It is likely, though not known, that this could have caused other issues we've seen in gccgo as well. ---- gcc-8.5.0/libgo/runtime/go-callers.c.old 2021-05-14 03:42:11.000000000 -0500 -+++ gcc-8.5.0/libgo/runtime/go-callers.c 2022-12-25 01:46:15.834110528 -0600 -@@ -117,7 +117,8 @@ - Solaris (http://gcc.gnu.org/PR52583 comment #21). */ +Additionally, since we strip libgo.so, filename is always NULL. This caused +the unwinder to continue through runtime_mstart which caused the same issue. +--- gcc-8.5.0/libgo/runtime/go-callers.c.old 2023-01-01 17:56:27.302982459 -0600 ++++ gcc-8.5.0/libgo/runtime/go-callers.c 2023-01-01 17:58:00.612903483 -0600 +@@ -165,26 +165,11 @@ if (function != NULL) { - if (__builtin_strcmp (function, "makecontext") == 0) + if (__builtin_strcmp (function, "makecontext") == 0 -+ || __builtin_strcmp (function, "libucontext_makecontext") == 0) ++ || __builtin_strcmp (function, "libucontext_makecontext") == 0 ++ || __builtin_strcmp (function, "runtime_mstart") == 0 ++ || __builtin_strcmp (function, "runtime.kickoff") == 0 ++ || __builtin_strcmp (function, "runtime.main") == 0) return 1; - if (filename != NULL) - { +- if (filename != NULL) +- { +- const char *p; +- +- p = strrchr (filename, '/'); +- if (p == NULL) +- p = filename; +- if (__builtin_strcmp (p, "/proc.c") == 0) +- { +- if (__builtin_strcmp (function, "runtime_mstart") == 0) +- return 1; +- } +- else if (__builtin_strcmp (p, "/proc.go") == 0) +- { +- if (__builtin_strcmp (function, "runtime.kickoff") == 0 +- || __builtin_strcmp (function, "runtime.main") == 0) +- return 1; +- } +- } + } + + return arg->index >= arg->max; diff --git a/system/gcc/342-gccgo-more-unwinding.patch b/system/gcc/342-gccgo-more-unwinding.patch deleted file mode 100644 index 7f059b4dc..000000000 --- a/system/gcc/342-gccgo-more-unwinding.patch +++ /dev/null @@ -1,37 +0,0 @@ -The fix for #832 was incomplete. Since we strip libgo.so, filename is -always NULL. This caused the unwinder to continue through -runtime_mstart which caused the same issue. ---- gcc-8.5.0/libgo/runtime/go-callers.c.old 2023-01-01 17:56:27.302982459 -0600 -+++ gcc-8.5.0/libgo/runtime/go-callers.c 2023-01-01 17:58:00.612903483 -0600 -@@ -118,27 +118,11 @@ - if (function != NULL) - { - if (__builtin_strcmp (function, "makecontext") == 0 -- || __builtin_strcmp (function, "libucontext_makecontext") == 0) -+ || __builtin_strcmp (function, "libucontext_makecontext") == 0 -+ || __builtin_strcmp (function, "runtime_mstart") == 0 -+ || __builtin_strcmp (function, "runtime.kickoff") == 0 -+ || __builtin_strcmp (function, "runtime.main") == 0) - return 1; -- if (filename != NULL) -- { -- const char *p; -- -- p = strrchr (filename, '/'); -- if (p == NULL) -- p = filename; -- if (__builtin_strcmp (p, "/proc.c") == 0) -- { -- if (__builtin_strcmp (function, "runtime_mstart") == 0) -- return 1; -- } -- else if (__builtin_strcmp (p, "/proc.go") == 0) -- { -- if (__builtin_strcmp (function, "runtime.kickoff") == 0 -- || __builtin_strcmp (function, "runtime.main") == 0) -- return 1; -- } -- } - } - - return arg->index >= arg->max; diff --git a/system/gcc/APKBUILD b/system/gcc/APKBUILD index b7dcfb592..54d901a64 100644 --- a/system/gcc/APKBUILD +++ b/system/gcc/APKBUILD @@ -1,12 +1,12 @@ # Maintainer: Adelie Platform Group pkgname=gcc -pkgver=8.5.0 +pkgver=13.3.0 [ "$BOOTSTRAP" = "nolibc" ] && pkgname="gcc-pass2" [ "$CBUILD" != "$CHOST" ] && _cross="-$CARCH" || _cross="" [ "$CHOST" != "$CTARGET" ] && _target="-$CTARGET_ARCH" || _target="" pkgname="$pkgname$_target" -pkgrel=4 +pkgrel=0 pkgdesc="The GNU Compiler Collection" url="https://gcc.gnu.org" arch="all" @@ -141,20 +141,19 @@ makedepends="$makedepends_build $makedepends_host" source="https://ftp.gnu.org/gnu/gcc/gcc-$pkgver/gcc-$pkgver.tar.xz 0002-posix_memalign.patch - 0008-s390x-muslldso.patch - 0009-microblaze-pr65649.patch - 0010-ldbl128-config.patch - 0011-m68k.patch 0012-static-pie.patch - 0016-invalid-tls-model.patch 002_all_default-relro.patch 005_all_default-as-needed.patch - 006_as-needed-gold.patch + 007_all_alpha-mieee-default.patch 011_all_default-warn-format-security.patch 012_all_default-warn-trampolines.patch 020_all_msgfmt-libstdc++-link.patch + 050_all_sanitizer-lfs.patch 051_all_libiberty-pic.patch + 076_all_match.pd-don-t-emit-label-if-not-needed.patch + 078_all_match.pd-CSE-the-dump-output-check.patch + 092_all_riscv_PR109760-gstreamer.patch 201-ada.patch 202-ibm-ldbl.patch @@ -169,27 +168,21 @@ source="https://ftp.gnu.org/gnu/gcc/gcc-$pkgver/gcc-$pkgver.tar.xz fix-cxxflags-passing.patch ada-shared.patch - 320-libffi-gnulinux.patch 330-gccgo-link-to-ucontext.patch 331-gccgo-use-real-off_t-type.patch 332-gccgo-sysinfo.patch - 333-gccgo-signal-ppc64.patch 334-gccgo-signal-shell.patch 335-gccgo-signal-ppc32.patch 336-gccgo-mmap64.patch - 337-gccgo-signal-sig34.patch - 338-gccgo-syscall.patch - 339-gccgo-errstr.patch - 340-gccgo-time64-stat.patch 341-gccgo-libucontext-stack.patch - 342-gccgo-more-unwinding.patch add-classic_table-support.patch gcc-5.4.0-locale.patch - backport-r267157-posix-conformant-snprintf.patch - libgo-musl-1.2.3.patch + + match-split.patch + insn-split.patch " # we build out-of-tree @@ -232,7 +225,7 @@ build() { cd "$_gccdir" case "$CTARGET" in - aarch64-*-*-*) _arch_configure="--with-arch=armv8-a --with-abi=lp64 --enable-fix-cortex-a53-835769 --enable-fix-cortex-a53-843419";; + aarch64*-*-*-*) _arch_configure="--with-arch=armv8-a --with-abi=lp64";; armv5-*-*-*eabi) _arch_configure="--with-arch=armv5te --with-tune=arm926ej-s --with-float=soft --with-abi=aapcs-linux";; armv6-*-*-*eabihf) _arch_configure="--with-arch=armv6zk --with-tune=arm1176jzf-s --with-fpu=vfp --with-float=hard --with-abi=aapcs-linux";; armv7-*-*-*eabihf) _arch_configure="--with-arch=armv7-a --with-tune=generic-armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-abi=aapcs-linux --with-mode=thumb";; @@ -241,8 +234,8 @@ build() { mips-*-*-*) _arch_configure="--with-arch=mips3 --with-mips-plt --with-abi=32"; _hash_style="sysv";; mips32el-*-*-*) _arch_configure="--with-arch=mips32 --with-mips-plt --with-abi=32"; _hash_style="sysv";; powerpc-*-*-*) _arch_configure="--enable-secureplt --enable-decimal-float=no";; - powerpc64*-*-*-*) _arch_configure="--with-abi=elfv2 --enable-secureplt --enable-decimal-float=no";; powerpc64le*-*-*-*) _arch_configure="--with-abi=elfv2 --enable-secureplt --enable-decimal-float=no";; + powerpc64*-*-*-*) _arch_configure="--with-abi=elfv2 --enable-secureplt --enable-decimal-float=no";; i486-*-*-*) _arch_configure="--with-arch=i486 --with-tune=generic --enable-cld";; i586-*-*-*) _arch_configure="--with-arch=i586 --with-tune=pentium2 --enable-cld --enable-mmx";; pentium3-*-*-*) _arch_configure="--with-arch=pentium3 --with-tune=pentium-m";; @@ -251,9 +244,7 @@ build() { case "$CTARGET_LIBC" in musl) - # musl does not support mudflap - # libmpx uses secure_getenv and struct _libc_fpstate not present in musl - _libc_configure="--disable-libmpx --disable-libmudflap --disable-libsanitizer" + _libc_configure="--disable-libsanitizer" _symvers="--disable-symvers" export libat_cv_have_ifunc=no export ac_cv_type_off64_t=no @@ -312,10 +303,12 @@ build() { --enable-default-ssp \ --enable-cloog-backend \ --enable-languages=$_languages \ + --enable-linker-build-id \ $_arch_configure \ $_libc_configure \ $_cross_configure \ $_bootstrap_configure \ + --with-matchpd-partitions=32 \ --with-system-zlib \ --with-linker-hash-style=$_hash_style make @@ -548,46 +541,39 @@ gnat() { mv "$pkgdir"/usr/bin/*gnat* "$subpkgdir"/usr/bin/ } -sha512sums="92f599680e6b7fbce88bcdda810f468777d541e5fddfbb287f7977d51093de2a5178bd0e6a08dfe37090ea10a0508a43ccd00220041abbbec33f1179bfc174d8 gcc-8.5.0.tar.xz +sha512sums="ed5f2f4c6ed2c796fcf2c93707159e9dbd3ddb1ba063d549804dd68cdabbb6d550985ae1c8465ae9a336cfe29274a6eb0f42e21924360574ebd8e5d5c7c9a801 gcc-13.3.0.tar.xz 6d84354e6df96d5ea244eb3bb5f044781796b88040b11c78fb6ee509e5aac19d46e0e92ca836e98e6495d9751f52439833b748efc419e4f5d5301fb549c4dcc9 0002-posix_memalign.patch -7f434a7350c9b06d0ae7cc18a569d813238483afa34b0801d112844a0dfe6164ae36b0416955fd4da7a8caa54672247f319a8ec7ce4b6a97a5f4e17ec083112a 0008-s390x-muslldso.patch -b8207c1be82b20fdad2596bb0a60469db52257456d0925bacf48b44899f4c6ece93c501347e1ffe92fd372c30f90d05a6d8d8078876abf4cf2deae3dbb1a1f58 0009-microblaze-pr65649.patch -66085c5555e6b91b6874d1782d5a1dc0ab1792889f9400f48cde9483f82b51b9e3a5de1efbba21a19fc5e664334f2188d0c2bc988d42335efa26118b3c85cc7f 0010-ldbl128-config.patch -cd3ba928121e8578ba9f73215e4d81ee3ebbab33e00b04cdfd62b46d21f9536297ae12dc021aad6e56f3b28d9d544727331bbe6db1e3438d7b9545b2c3250906 0011-m68k.patch -9fbfd2213b445a82ae00c72412a8f87a2d0afc8614168698a12dfc6ad874b525de7f15b3eb2d54b7737d0a9d90f18f134e7cdbf4259e32d9a631c3795b8d44be 0012-static-pie.patch -dfedf48829cff22ee836ece743de20ad467b40e86c8f4034326a4c32df35b10affd69d6b9ab3382df2871a99ad0c2e99d4342183b59f9bca7f15112eed58ec8d 0016-invalid-tls-model.patch -625c02e03c2f1db04da12cc6a086ec85790a031a13df36486243fd9569cd17f7c8ebeec91ac16cc1f87c3ec1ffe4c421153e98a9aeb5eea35943a6f015d81f50 002_all_default-relro.patch -02b725b220e540077efef741e9d457f9e004fe53ae642a138e214875d076a60f7c2f27de0ed9a4225db2030fc9c3d2c5b0414c895b9eec0f5f48fad70e2fb029 005_all_default-as-needed.patch -9073a5ae46e46a44a77adba183db301194a3666afca07a8444a4c10dc2c087dd41d6065a051b1024454bb37bee06fabf4361e5fae62dab8d4c9620520924f606 006_as-needed-gold.patch -622fdbcbbf2feb86bd839af627ec3613c6d2c77b14d37d31165b19f73f45b3663a203efff5d224f194edb15eb62d3d5885e32f85d1b584f071e580fea4e12664 011_all_default-warn-format-security.patch -03cddde56b2a355f08716c8efcd5616606d42946c87831d77d55570636c46e351e81a04c7dabd3466d9406c40476bead857cfe1eceaf7f0d86dd2757c8cf4a9e 012_all_default-warn-trampolines.patch -d35a3ac7e13a4446921a90e1ff3eec1079840c845f9d523c868e24ae21f94cf69ba041de5341ebef96432a6f57598e223381d4286e8fb8baaa25906707f29fbd 020_all_msgfmt-libstdc++-link.patch -0a0bc72b9366158f5d23fff1928e756fdd212433bac6ab1f00d632f241382820db8db5d475ddf11ea020eaf7e2e71b12fb9b1c3c870cf84adf6c2b16f15aabca 051_all_libiberty-pic.patch -a3702c1f642412413d0ffc69f6439a3e101b2b56c16610f94c66556c88e52d01b0b6d1e57bfc5a972668f976c02fbf2fc22bcf707b000867e44744d9eb7b7566 201-ada.patch -152639228a189b211df660b5b7543e3744cf136e80fed7f1ac37a3bc1b692fba3431a0d62337e769ee8f323188acdf11092cb1b2ef5c75fafee9628d13bc4163 202-ibm-ldbl.patch -98473bcaa77903a223ca9b0d2087c0921b287a2816d308cc32c8fe009e6cbf5dd1ae7fba27794ab8d9c09e117fe534413d91a464d1218474fc123ce0adfdc2c1 205-nopie.patch -9fc745619d2628ec21eed1c8de78780ca8960a0ca41f725991202b212bdeb31eb803d9ea2ad18e0278620c2422a99f253f4d2a20d3a354bf88b87a55fc966d9d 206-arm-unwind-functionise.patch -d08d7ead2de0429e5c9055d5b029ec2be9a8c821d22cecaf9b51f633652c493333f98963d9267fa2fa63850c50ae5eefd5f59e5910ec10d20044dac082182a8b libgcc-always-build-gcceh.a.patch -600fe5098dc54edaa9808fd5717af9dec058953f9ad37d49cfba1db4f7e9a7a8f02019342f75157fc575946fa693259422184de27b7ecc8386d9f3ecc0f7cc5d gcc-4.9-musl-fortify.patch -dbe0ee917fc7668571722364ab7c806731e3a31e8bfa30b4941b28b16b877d2a32b4a3897ef533399a28f82d43cac9b28e92de0493f0e779046db56584e07fa4 gcc-6.1-musl-libssp.patch -fa62556719449caec6b2b434355bfbcaa5ae55ffe017b3e1f827f66a2aae21b79c571ee7a4ce723ea69169bc3a6447e73650991a200cc372adf2f102677518d7 gcc-pure64.patch -35d6d59f0b7b968f282f56767c9e0823a7bdc5aa0d450aca50fbd802649a7ca608b47671244a3faa208a9b0d6832cabb5a22724157dc817b2c0ad63d09f93282 fix-cxxflags-passing.patch -3f5bc334d9f73d06f5f7c876738d02356acdd08958bea0e4d2095ebf15c2c2ec4e411abdae0297505ae9a1699ca01b17338e853184e84663203b192b0d35fc19 ada-shared.patch -f4ef08454e28c8732db69115e4998ec153399e8d229dd27f923dbdcf57b68128a65640d026cc7f45b58ba8764ab1eb575d4eb6d6dfc550a87a183f8b94e76181 320-libffi-gnulinux.patch -8efd028febb962ae100be32f72f7450c4f77d67ad96a5f47072136cdf47043f9d54835a87c7ab5aaa0fa0108c4c7a97ba2d7732d5aaf2efce70fe1f7e1c39d6e 330-gccgo-link-to-ucontext.patch -24c8708f64b9b7945b3f07e9bbecf17ab8bcde2524f49cbd694ca2f6146ccc3f13bb027db282f326525ea79d50a2868fa3fa2b0d688a914b5ea77bbfd7e5cbe4 331-gccgo-use-real-off_t-type.patch -31f9d85faa8648d140834646fc2bc7733eb362bfb87d696c5f375f9c0a3e4c3df41708a9a37c49bc0757513a7704976b9a5e21aa5c2de4b380d47d7e2cbde214 332-gccgo-sysinfo.patch -ef6ff46d571814ce2f6db549bfb9b9f5cc55d46085b197c36627a72e4f355fcbeb41d04fabd3029f3bc536fc48155fe3feab58a7a6ece9dcd19409ea44c17b0b 333-gccgo-signal-ppc64.patch -ab7a19d2702d232c9c1242fbdf9bd782e195d94104c0278e3b9ce435060a169094525ca53b615b3a9e62786db77bba836ecd495d58b544df474b13348432c200 334-gccgo-signal-shell.patch -e755072a3c71ada6cde354dd258fae029919e1116048068368d38411ca28a6ad8856702498d6667b0dcbb1d09fcb3fd66669aa79739a5e574a9cd490bd92ce90 335-gccgo-signal-ppc32.patch -de0cc0f9356c9ee5ea7b0f954441b59115f4a8f8f63573d0c17b6537e6f37641cf137531b496fc192d38035c2c4ba8175d36cbd7da15cbfcf8dc18c049c0f111 336-gccgo-mmap64.patch -c2916948b028e1e990e1953875b884561c0f8dd105c1ec03073795df9a47ec2c627cbc95ca0ec98ab9177bf2b7c8458bf3fd09f780fa6c301995846f6317e366 337-gccgo-signal-sig34.patch -0bdf592ec8444c6e253f1a7626b4e618b2e18e6d0b5a4548f90903f9de80a7cf3ea536750c2743f436a05faa1e7b65e52a391da9732dce51c4b00e23853e5365 338-gccgo-syscall.patch -b32d496a3a04c2357200b75dbf7f667fb57bf5af4f0c68926bc58f6600e4f23caa48aad2eaf073f1408168cacf27e8f11a6062c65bf5bb67458eedef698871d4 339-gccgo-errstr.patch -4db4a00dff1d3cb3ecbc713659316782ac839478ff1fd7166cfa64a2c7cee0ba2a0d3fa23cb858af7d8f59a6ac2bdf40e63a45c307b89eefe2a4e888707f615b 340-gccgo-time64-stat.patch -71ee2ce239c62bedc90d0688a40e3e381e641ba9e322c6319c2f6a4362c17d60a232dcb32fd08f5ff9ed5c058c0a010362197839cb391d85bc4a6446943ad4b2 341-gccgo-libucontext-stack.patch -7bb23955ddd67319c2aaae10bb1545ea299b96e54f429423fa6db4ff9af119312f3c8a876b3912c8811403543fabb50e7c7b94b0d2145a4f4e6ef1959d456128 342-gccgo-more-unwinding.patch +f0bda72a54d2a81c4e7b27cc06347409d9e3be708d51e280ad1130c7e1d2db6e0c4e7b2dd3c606f6a4ec78c1eb293a26f76dda8210124d9f928f351d46be7d7e 0012-static-pie.patch +2cb8f3773897e34d2d194076396d7fc6413d28b5f0546d092f83c22f229936f7e329b3eaaf86a6d22e0f609ae2b66e82b656685e9e9a51ed2f89e9efaa5e9534 002_all_default-relro.patch +879c377122af10a4e444ab67cfe81927cc4e574c63d0a619c20f094e87218ab7961dcc96d93830891af688182a5feafeb787d79b58a5125cf20258baa13c94d0 005_all_default-as-needed.patch +b0a6117aad4f72d62777004fbb0a93cb0ae613d44846162556535f1751be998e6cde61329451026bc539d119ae2d54b42eaff54b92f2f68cb14c2b1384cbc928 007_all_alpha-mieee-default.patch +abf28cf8495ce63eeeb9704a83e889c9b7819cc0394807ba966fe57dadc5f1e04478edc6d28af293330286dc70af4b513376bf53ddf705810c3b721b5089c511 011_all_default-warn-format-security.patch +6fa1f7bb936f8c634579689aa5b36a23a89e1f065514b1c946a410cd0057744135db833bb5cbb86a15738ebac787b5803bba0a2d4d0da628dfbd23d9bcd577b4 012_all_default-warn-trampolines.patch +f20ba1e7a6febf099a79c4b4251e15331e6de13531b787c2e2d14c908e3ff1e0e34a79824e7f6470331adf9c01c3302813dfbd508fec021a7f86f833c806806b 020_all_msgfmt-libstdc++-link.patch +8cadf32d4f9e58ae174640be419478ee709702c1df3faffb2cfc4e48418260b8bbadf6c18fbaf43cc32aacb889f090045265c3f51e9366208837a46cbf68ab6e 050_all_sanitizer-lfs.patch +ec0a6613a21bd8352b73f693ee6055e81e4ef056b8b2b9916aa075649477b0c3f855fcfb37aa53301a559f05e5cfa41661c274f3a3c6cabb44a7adecf239473a 051_all_libiberty-pic.patch +0d505f08842bd75c686b18f50bc988078dce07b69ef8b6caa53e5e3a93e39527ab16f1d32a7f1f132279c3ac430a10b4e1aad7fc0bc2b6560fc33a1b65f6c109 076_all_match.pd-don-t-emit-label-if-not-needed.patch +b3cb3cad951c518b399f4fd0d4be07089ca1abf7a3271aaac4c25d8cd34a9b6d2bd6fa68164cf7f3967813f019db8dcf0ae8746f94ac6a4b85209c4012a8936f 078_all_match.pd-CSE-the-dump-output-check.patch +ce44d0bfa646394114c6e77f70da26ac4879cb2198a3bc4108ce080b7a247d6c0b0213c02b9bacbcd0b477a8e22a831a7dae3691f4f0462eaddecb457cd9eee6 092_all_riscv_PR109760-gstreamer.patch +e6598c90b156057f77fd28bf2bb90cc57f00c89dbd5acc878c5a4ab9d14deaf985d388270981f499679bc32417b8839a025954340e2c7dcfe9ac335127eae9f2 201-ada.patch +80748e1f6a287a0f645eecac54c5181156a20ab0facc826e5b1768fec87df9d4e9fd44362370dbbe5f78b25c3bba3a20a6acfbe6ce25ddd99bd6d085bfc6c112 202-ibm-ldbl.patch +ae30090390e3604e1e508edb36bc3a01283fe28657d63ae6d6238dd9f55cce587552c5a482425673aff0d0ccc9d99a649e24b552573e7b2ea29063fc5c0aa497 205-nopie.patch +ae2c2fe6abe678e34d60cb05e42c60d6b499f206d965066ee8bd26f9cabfbb69cab0f0061731d21b96a5f2ad67bebc4b49dbe39cbdd01dce8b61f829f4b3f708 206-arm-unwind-functionise.patch +3c66bbcde298cdc188bb68dfe16e074bda7355c2307b8263c75cb250e244dd604faf2e4bf782f8f39160892b5a433996615fd0597ce5bd20bd5c1b766bf12d2d libgcc-always-build-gcceh.a.patch +40322bba8b3bfc26f0cd92bc9849c59560a6736dd22941bde4b6a1d9846e798d5acfe4fdc3200aafabbf6168349b08070a9e31d41967a48e84dbc608723cdcf3 gcc-4.9-musl-fortify.patch +7800fd0e1bcb33779c673c2effa8a61c4288979fba7d9dd215777ebec4d2cce5fe42fe72dcbce078bbc2268db58a25b42fc1a7327c1156e2db6a694b9303dbec gcc-6.1-musl-libssp.patch +d8a184ff286516f49629fe97423b5584a7799069de2c3f0d45c2ff25be8e6e8706f9ca0e811f760cd3e0089bd82657091a2fa13139f4c3cc7d5d5dd25f82d5e8 gcc-pure64.patch +eb1d27d501e1c5099bbc476cda27738a13a3c27185d2e4f46c770dda30b7b0e774b58a62afad8ead44298296ce60b409fbab2da08bf114a66fa269f02d4132d7 fix-cxxflags-passing.patch +16d66b34de05a220d43ba0327bc75aabc107b36c629efa4b2f14662f6b1c805d8123aeb0a92e7e908c059b3d910acc2e7e1b50c7ac34a004d8a20b9a140427f4 ada-shared.patch +ce69e4cceb212e7b8e9af72a97b336dc3f38d7a30fc0c656a56ab3b431679a07efd746fd1cc39f913934f603c83085dd9e72a1b516636ba85f43b2cd96568404 330-gccgo-link-to-ucontext.patch +25223ce10dbeb6725834fbd2ea57752c9d7b96f9c1e0d1f46927c7b5236c1bed1361b28869e9830ad39818788e491609ef9a79e9255a565a2b6fb3c56c3bc48d 331-gccgo-use-real-off_t-type.patch +2b833b6bcba8eb8914499f3432679635eb1e186f0ab1b0cd2b0012edfe6c296f89c05097476817c9947a0f17ebe031cc1708335e6baa8d3d211116e10cbc7865 332-gccgo-sysinfo.patch +dc03c7b660f0142aa16e78e4e50581c883f6632f4794131f1131e0dc8fd500ba5d6a0046a36dc621c618a558b69e426a9bd1baea63faa5f64d7663915c062bbe 334-gccgo-signal-shell.patch +00f43d3d3f23c106ff020699397e82cf63ef30820e74ff3f7a82bcf55e5245011bb4a8ef84f0704287201ec8138692c548d4b6dae2d3e2aaf56e40d57ca2873d 335-gccgo-signal-ppc32.patch +5ead34140ff01e2918554c9c3f8378fe02cdf41f5b965053c126238dc157a1e2558d58465395b750e85b1d7167c4fc79d8a7f34894146507d7366d79a69d4ee7 336-gccgo-mmap64.patch +3cbe5e879902a73121b22d903be605c7100e607864b0e305d6825a4083502fbe94be9a4166fb833b28e5d18cd7548f317719e28e3579194ea3e1b626450c943b 341-gccgo-libucontext-stack.patch 1860593584f629d24d5b6db14b0a3412e9f93449b663aaa4981301a0923db0159314905e694f27366fbfef72dce06636ab6df86862b7e9e9564847e03bee82c1 add-classic_table-support.patch -67a75a94fdba69de96b98dbc2978a50cb197857c464b81f7c956176da7066b3be937e40cb15e0870fc1e7382d662c5101bcd18cf457fc4112de41802042b51c4 gcc-5.4.0-locale.patch -65a4d8bf9cefcbc79e86015ef4376b2794492d6cae77065359b35bb4ed630dde6256982cd5e43ed837cbbdab366ea376da9f1c83f80ddf6dc53ab017b378c3cd backport-r267157-posix-conformant-snprintf.patch -fa59b0fb081d97f8f63506b8793699588a95c602b5d468140eb1e80456597e52e1cc45dc0b234ac8e60e2b0cd606d94d111c8b0ae64c0a2be1bc1b8a184ceb93 libgo-musl-1.2.3.patch" +a09b3181002798d1b17b8374eba6bec18e67d4d4f30677311c330b599e231e97cf02c1b9b79c0829952f5027016e01146743b665b19558ed2693c60a567823fb gcc-5.4.0-locale.patch +fa59b0fb081d97f8f63506b8793699588a95c602b5d468140eb1e80456597e52e1cc45dc0b234ac8e60e2b0cd606d94d111c8b0ae64c0a2be1bc1b8a184ceb93 libgo-musl-1.2.3.patch +ff6159633f04d26eadc79895dc24ccb46671a04fdc728cbbac86964a14ce17e2e51cd7668947dfe06b9168bb9b8575a80955012e5f51295ea02f4f3169e07541 match-split.patch +ee626cbe4bdda5b868980c86ca066d33167d06517db676e43d0719c4ad7d11e99b3a0151927f15c93ab89f6c76dd12bd48d402d25771fa3fd175273248824eda insn-split.patch" diff --git a/system/gcc/ada-shared.patch b/system/gcc/ada-shared.patch index 6f1c16aff..22a7dc256 100644 --- a/system/gcc/ada-shared.patch +++ b/system/gcc/ada-shared.patch @@ -2,10 +2,10 @@ Index: b/gcc/ada/link.c =================================================================== --- a/gcc/ada/link.c +++ b/gcc/ada/link.c -@@ -105,9 +105,9 @@ - +@@ -107,9 +107,9 @@ #elif defined (__FreeBSD__) const char *__gnat_object_file_option = "-Wl,@"; + const char *__gnat_run_path_option = ""; -const char *__gnat_run_path_option = "-Wl,-rpath,"; -char __gnat_shared_libgnat_default = STATIC; -char __gnat_shared_libgcc_default = STATIC; @@ -15,10 +15,10 @@ Index: b/gcc/ada/link.c int __gnat_link_max = 8192; unsigned char __gnat_objlist_file_supported = 1; const char *__gnat_object_library_extension = ".a"; -@@ -127,9 +127,9 @@ - +@@ -129,9 +129,9 @@ #elif defined (linux) || defined(__GLIBC__) const char *__gnat_object_file_option = "-Wl,@"; + const char *__gnat_run_path_option = ""; -const char *__gnat_run_path_option = "-Wl,-rpath,"; -char __gnat_shared_libgnat_default = STATIC; -char __gnat_shared_libgcc_default = STATIC; diff --git a/system/gcc/backport-r267157-posix-conformant-snprintf.patch b/system/gcc/backport-r267157-posix-conformant-snprintf.patch deleted file mode 100644 index adedf0ce9..000000000 --- a/system/gcc/backport-r267157-posix-conformant-snprintf.patch +++ /dev/null @@ -1,80 +0,0 @@ -https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87096 - -GCC's "optimised" snprintf is not POSIX conformant - ---- trunk/gcc/gimple-ssa-sprintf.c 2018/12/07 17:02:11 266897 -+++ trunk/gcc/gimple-ssa-sprintf.c 2018/12/14 22:38:08 267157 -@@ -3899,6 +3899,7 @@ - /* True when the destination size is constant as opposed to the lower - or upper bound of a range. */ - bool dstsize_cst_p = true; -+ bool posunder4k = true; - - if (idx_dstsize == HOST_WIDE_INT_M1U) - { -@@ -3931,11 +3932,20 @@ - "specified bound %wu exceeds maximum object size " - "%wu", - dstsize, target_size_max () / 2); -+ /* POSIX requires snprintf to fail if DSTSIZE is greater -+ than INT_MAX. Even though not all POSIX implementations -+ conform to the requirement, avoid folding in this case. */ -+ posunder4k = false; - } - else if (dstsize > target_int_max ()) -- warning_at (gimple_location (info.callstmt), info.warnopt (), -- "specified bound %wu exceeds %", -- dstsize); -+ { -+ warning_at (gimple_location (info.callstmt), info.warnopt (), -+ "specified bound %wu exceeds %", -+ dstsize); -+ /* POSIX requires snprintf to fail if DSTSIZE is greater -+ than INT_MAX. Avoid folding in that case. */ -+ posunder4k = false; -+ } - } - else if (TREE_CODE (size) == SSA_NAME) - { -@@ -3944,9 +3954,29 @@ - if (vr->type == VR_RANGE - && TREE_CODE (vr->min) == INTEGER_CST - && TREE_CODE (vr->max) == INTEGER_CST) -- dstsize = (warn_level < 2 -- ? TREE_INT_CST_LOW (vr->max) -- : TREE_INT_CST_LOW (vr->min)); -+ { -+ unsigned HOST_WIDE_INT minsize = TREE_INT_CST_LOW (vr->min); -+ unsigned HOST_WIDE_INT maxsize = TREE_INT_CST_LOW (vr->max); -+ dstsize = warn_level < 2 ? maxsize : minsize; -+ -+ if (minsize > target_int_max ()) -+ warning_at (gimple_location (info.callstmt), info.warnopt (), -+ "specified bound range [%wu, %wu] exceeds " -+ "%", -+ minsize, maxsize); -+ -+ /* POSIX requires snprintf to fail if DSTSIZE is greater -+ than INT_MAX. Avoid folding if that's possible. */ -+ if (maxsize > target_int_max ()) -+ posunder4k = false; -+ } -+ else if (vr->type == VR_VARYING) -+ { -+ /* POSIX requires snprintf to fail if DSTSIZE is greater -+ than INT_MAX. Since SIZE's range is unknown, avoid -+ folding. */ -+ posunder4k = false; -+ } - - /* The destination size is not constant. If the function is - bounded (e.g., snprintf) a lower bound of zero doesn't -@@ -4033,7 +4073,7 @@ - the call. Avoid this optimization when -frounding-math is in effect - and the format string contains a floating point directive. */ - bool call_removed = false; -- if (success && optimize > 0) -+ if (!posunder4k && success && optimize > 0) - { - /* Save a copy of the iterator pointing at the call. The iterator - may change to point past the call in try_substitute_return_value diff --git a/system/gcc/fix-cxxflags-passing.patch b/system/gcc/fix-cxxflags-passing.patch index 8eb1de77d..ec98ba275 100644 --- a/system/gcc/fix-cxxflags-passing.patch +++ b/system/gcc/fix-cxxflags-passing.patch @@ -1,6 +1,6 @@ --- gcc-4.8.1/Makefile.in.orig +++ gcc-4.8.1/Makefile.in -@@ -169,6 +169,7 @@ +@@ -178,6 +178,7 @@ # built for the build system to override those in BASE_FLAGS_TO_PASSS. EXTRA_BUILD_FLAGS = \ CFLAGS="$(CFLAGS_FOR_BUILD)" \ diff --git a/system/gcc/gcc-4.9-musl-fortify.patch b/system/gcc/gcc-4.9-musl-fortify.patch index daae954c8..fba37f257 100644 --- a/system/gcc/gcc-4.9-musl-fortify.patch +++ b/system/gcc/gcc-4.9-musl-fortify.patch @@ -1,6 +1,6 @@ --- gcc-4.9.2/gcc/config/linux.h.orig 2015-03-09 13:27:13.289736710 +0000 +++ gcc-4.9.2/gcc/config/linux.h 2015-03-09 13:29:32.295625046 +0000 -@@ -146,6 +146,8 @@ +@@ -159,6 +159,8 @@ #ifdef NATIVE_SYSTEM_HEADER_DIR #define INCLUDE_DEFAULTS_MUSL_NATIVE \ diff --git a/system/gcc/gcc-5.4.0-locale.patch b/system/gcc/gcc-5.4.0-locale.patch index dca3ba9e8..e1b398b7f 100644 --- a/system/gcc/gcc-5.4.0-locale.patch +++ b/system/gcc/gcc-5.4.0-locale.patch @@ -1,7 +1,7 @@ diff --git gcc-5.4.0/libstdc++-v3/config/locale/generic/c_locale.cc.orig gcc-5.4.0/libstdc++-v3/config/locale/generic/c_locale.cc --- gcc-5.4.0/libstdc++-v3/config/locale/generic/c_locale.cc.orig +++ gcc-5.4.0/libstdc++-v3/config/locale/generic/c_locale.cc -@@ -213,9 +213,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION +@@ -242,9 +242,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Currently, the generic model only supports the "C" locale. // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html __cloc = 0; diff --git a/system/gcc/gcc-6.1-musl-libssp.patch b/system/gcc/gcc-6.1-musl-libssp.patch index fe5c61434..05a9cf8bf 100644 --- a/system/gcc/gcc-6.1-musl-libssp.patch +++ b/system/gcc/gcc-6.1-musl-libssp.patch @@ -1,4 +1,5 @@ -Author: Timo Teräs +Gentoo: https://bugs.gentoo.org/706210, https://bugs.gentoo.org/747346 +Alpine Author: Timo Teräs Alpine musl package provides libssp_nonshared.a. We link to it unconditionally, as otherwise we get link failures if some objects are -fstack-protector built @@ -6,9 +7,11 @@ and final link happens with -fno-stack-protector. This seems to be the common case when bootstrapping gcc, the piepatches do not seem to fully fix the crosstoolchain and bootstrap sequence wrt. stack-protector flag usage. ---- gcc-6.1.0/gcc/gcc.c.orig -+++ gcc-6.1.0/gcc/gcc.c -@@ -870,8 +870,7 @@ +This is done by Gentoo and us (Adélie) as well. + +--- gcc-6.1.0/gcc/gcc.cc ++++ gcc-6.1.0/gcc/gcc.cc +@@ -988,8 +988,7 @@ #ifndef LINK_SSP_SPEC #ifdef TARGET_LIBC_PROVIDES_SSP diff --git a/system/gcc/gcc-pure64.patch b/system/gcc/gcc-pure64.patch index 2c350fe5a..d55c04c85 100644 --- a/system/gcc/gcc-pure64.patch +++ b/system/gcc/gcc-pure64.patch @@ -1,16 +1,8 @@ ---- ./gcc/config/i386/t-linux64.orig 2013-01-14 16:32:37.000000000 +0000 -+++ ./gcc/config/i386/t-linux64 2013-04-22 06:12:32.984439677 +0000 -@@ -34,6 +34,6 @@ - comma=, - MULTILIB_OPTIONS = $(subst $(comma),/,$(TM_MULTILIB_CONFIG)) - MULTILIB_DIRNAMES = $(patsubst m%, %, $(subst /, ,$(MULTILIB_OPTIONS))) --MULTILIB_OSDIRNAMES = m64=../lib64$(call if_multiarch,:x86_64-linux-gnu) --MULTILIB_OSDIRNAMES+= m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:i386-linux-gnu) -+MULTILIB_OSDIRNAMES = m64=../lib -+MULTILIB_OSDIRNAMES+= m32=../lib32 - MULTILIB_OSDIRNAMES+= mx32=../libx32$(call if_multiarch,:x86_64-linux-gnux32) ---- ./gcc/config/aarch64/t-aarch64-linux.orig -+++ ./gcc/config/aarch64/t-aarch64-linux +https://bugs.gentoo.org/675954 +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90077 + +--- a/gcc/config/aarch64/t-aarch64-linux ++++ b/gcc/config/aarch64/t-aarch64-linux @@ -22,7 +22,7 @@ LIB1ASMFUNCS = _aarch64_sync_cache_range @@ -19,19 +11,21 @@ +MULTILIB_OSDIRNAMES = mabi.lp64=../lib MULTIARCH_DIRNAME = $(call if_multiarch,aarch64$(AARCH_BE)-linux-gnu) - MULTILIB_OSDIRNAMES += mabi.ilp32=../libilp32 ---- ./gcc/config/s390/t-linux64.orig -+++ ./gcc/config/s390/t-linux64 -@@ -7,5 +7,5 @@ - MULTILIB_OPTIONS = m64/m31 - MULTILIB_DIRNAMES = 64 32 --MULTILIB_OSDIRNAMES = ../lib64$(call if_multiarch,:s390x-linux-gnu) --MULTILIB_OSDIRNAMES += $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:s390-linux-gnu) + MULTILIB_OSDIRNAMES += mabi.ilp32=../libilp32$(call if_multiarch,:aarch64$(AARCH_BE)-linux-gnu_ilp32) +--- a/gcc/config/i386/t-linux64 ++++ b/gcc/config/i386/t-linux64 +@@ -33,6 +33,6 @@ + comma=, + MULTILIB_OPTIONS = $(subst $(comma),/,$(TM_MULTILIB_CONFIG)) + MULTILIB_DIRNAMES = $(patsubst m%, %, $(subst /, ,$(MULTILIB_OPTIONS))) +-MULTILIB_OSDIRNAMES = m64=../lib64$(call if_multiarch,:x86_64-linux-gnu) +-MULTILIB_OSDIRNAMES+= m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:i386-linux-gnu) +-MULTILIB_OSDIRNAMES+= mx32=../libx32$(call if_multiarch,:x86_64-linux-gnux32) +MULTILIB_OSDIRNAMES = m64=../lib +MULTILIB_OSDIRNAMES+= m32=../lib32 - ---- ./gcc/config/rs6000/t-linux.orig -+++ ./gcc/config/rs6000/t-linux ++MULTILIB_OSDIRNAMES+= mx32=../libx32 +--- a/gcc/config/rs6000/t-linux ++++ b/gcc/config/rs6000/t-linux @@ -2,7 +2,8 @@ # or soft-float. ifeq (,$(filter $(with_cpu),$(SOFT_FLOAT_CPUS))$(findstring soft,$(with_float))) @@ -40,9 +34,9 @@ +MULTILIB_OSDIRNAMES := m64=../lib +MULTILIB_OSDIRNAMES += m32=../lib32 else - ifneq (,$(findstring spe,$(target))) - MULTIARCH_DIRNAME := powerpc-linux-gnuspe$(if $(findstring 8548,$(with_cpu)),,v1) -@@ -14,7 +15,8 @@ + MULTIARCH_DIRNAME := $(call if_multiarch,powerpc-linux-gnu) + endif +@@ -10,7 +11,8 @@ MULTIARCH_DIRNAME := $(subst -linux,le-linux,$(MULTIARCH_DIRNAME)) endif ifneq (,$(findstring powerpc64le,$(target))) @@ -52,8 +46,8 @@ endif endif ---- ./gcc/config/rs6000/t-linux64.orig -+++ ./gcc/config/rs6000/t-linux64 +--- a/gcc/config/rs6000/t-linux64 ++++ b/gcc/config/rs6000/t-linux64 @@ -28,8 +28,8 @@ MULTILIB_OPTIONS := m64/m32 MULTILIB_DIRNAMES := 64 32 @@ -65,8 +59,8 @@ rs6000-linux.o: $(srcdir)/config/rs6000/rs6000-linux.c $(COMPILE) $< ---- ./gcc/config/rs6000/t-linux64bele.orig -+++ ./gcc/config/rs6000/t-linux64bele +--- a/gcc/config/rs6000/t-linux64bele ++++ b/gcc/config/rs6000/t-linux64bele @@ -2,6 +2,6 @@ MULTILIB_OPTIONS += mlittle @@ -76,8 +70,8 @@ +MULTILIB_OSDIRNAMES = m64=../lib +MULTILIB_OSDIRNAMES+= m32=../lib32 MULTILIB_MATCHES := ${MULTILIB_MATCHES_ENDIAN} ---- ./gcc/config/rs6000/t-linux64lebe.orig -+++ ./gcc/config/rs6000/t-linux64lebe +--- a/gcc/config/rs6000/t-linux64lebe ++++ b/gcc/config/rs6000/t-linux64lebe @@ -2,6 +2,6 @@ MULTILIB_OPTIONS += mbig diff --git a/system/gcc/insn-split.patch b/system/gcc/insn-split.patch new file mode 100644 index 000000000..3b7ce8767 --- /dev/null +++ b/system/gcc/insn-split.patch @@ -0,0 +1,1404 @@ +https://gcc.gnu.org/PR54179 +https://inbox.sourceware.org/gcc-patches/de0f7bdc-d236-4f5b-9504-d5bfb215d023@gmail.com/ + +From d63f858f41e2bb0e159d15ed8ee41bf303325ee7 Mon Sep 17 00:00:00 2001 +From: Robin Dapp +Date: Fri, 27 Oct 2023 21:04:25 +0200 +Subject: [PATCH 13/15] genemit: Split insn-emit.cc into ten files. + +After working with Sam off-list (thanks) I managed to get hppa to +build. Initially it looked as if hppa just had a very small number of +instruction patterns so we wouldn't generate all 10 output files. +However, the actual issue (which we will only hit with a low +pattern count) was with counting all the patterns vs only counting +the patterns that will be output. A wrong pattern count lead to +prematurely stopping to write output files. + +With that corrected, hppa "just works" until I hit linker errors +due to relocations - most likely unrelated: + +bin/ld: unwind-dw2-fde-dip_s.o(.data.rel.ro+0): cannot handle +R_PARISC_FPTR64 for __pthread_key_create@@GLIBC_2.34 + +Attached is v3 that has been bootstrapped and tested on x86 and power10, +aarch64 bootstrap was ok, testsuite is still running. A riscv build and +testsuite run was successful as well. + +Regards + Robin + +>From 248744c328440bff9cc339d2bf622852cbaac343 Mon Sep 17 00:00:00 2001 +From: Robin Dapp +Date: Thu, 12 Oct 2023 11:23:26 +0200 +Subject: [PATCH v3] genemit: Split insn-emit.cc into several partitions. + +On riscv insn-emit.cc has grown to over 1.2 mio lines of code and +compiling it takes considerable time. +Therefore, this patch adjust genemit to create several partitions +(insn-emit-1.cc to insn-emit-n.cc). The available patterns are +written to the given files in a sequential fashion. + +Similar to match.pd a configure option --with-emitinsn-partitions=num +is introduced that makes the number of partition configurable. + +gcc/ChangeLog: + + PR bootstrap/84402 + PR target/111600 + + * Makefile.in: Handle split insn-emit.cc. + * configure: Regenerate. + * configure.ac: Add --with-insnemit-partitions. + * genemit.cc (output_peephole2_scratches): Print to file instead + of stdout. + (print_code): Ditto. + (gen_rtx_scratch): Ditto. + (gen_exp): Ditto. + (gen_emit_seq): Ditto. + (emit_c_code): Ditto. + (gen_insn): Ditto. + (gen_expand): Ditto. + (gen_split): Ditto. + (output_add_clobbers): Ditto. + (output_added_clobbers_hard_reg_p): Ditto. + (print_overload_arguments): Ditto. + (print_overload_test): Ditto. + (handle_overloaded_code_for): Ditto. + (handle_overloaded_gen): Ditto. + (print_header): New function. + (handle_arg): New function. + (main): Split output into 10 files. + * gensupport.cc (count_patterns): New function. + * gensupport.h (count_patterns): Define. + * read-md.cc (md_reader::print_md_ptr_loc): Add file argument. + * read-md.h (class md_reader): Change definition. +--- + gcc/Makefile.in | 36 ++- + gcc/configure | 24 +- + gcc/configure.ac | 13 ++ + gcc/genemit.cc | 542 +++++++++++++++++++++++++--------------------- + gcc/gensupport.cc | 55 +++++ + gcc/gensupport.h | 1 + + gcc/read-md.cc | 4 +- + gcc/read-md.h | 2 +- + 8 files changed, 422 insertions(+), 255 deletions(-) + +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index 2c16b14ad0f3..b0c118e6d189 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -232,6 +232,13 @@ GIMPLE_MATCH_PD_SEQ_O = $(patsubst %, gimple-match-%.o, $(MATCH_SPLITS_SEQ)) + GENERIC_MATCH_PD_SEQ_SRC = $(patsubst %, generic-match-%.cc, $(MATCH_SPLITS_SEQ)) + GENERIC_MATCH_PD_SEQ_O = $(patsubst %, generic-match-%.o, $(MATCH_SPLITS_SEQ)) + ++# The number of splits to be made for the insn-emit files. ++NUM_INSNEMIT_SPLITS = @DEFAULT_INSNEMIT_PARTITIONS@ ++INSNEMIT_SPLITS_SEQ = $(wordlist 1,$(NUM_INSNEMIT_SPLITS),$(one_to_9999)) ++INSNEMIT_SEQ_SRC = $(patsubst %, insn-emit-%.cc, $(INSNEMIT_SPLITS_SEQ)) ++INSNEMIT_SEQ_TMP = $(patsubst %, tmp-emit-%.cc, $(INSNEMIT_SPLITS_SEQ)) ++INSNEMIT_SEQ_O = $(patsubst %, insn-emit-%.o, $(INSNEMIT_SPLITS_SEQ)) ++ + # These files are to have specific diagnostics suppressed, or are not to + # be subject to -Werror: + # flex output may yield harmless "no previous prototype" warnings +@@ -1334,7 +1341,7 @@ OBJS = \ + insn-attrtab.o \ + insn-automata.o \ + insn-dfatab.o \ +- insn-emit.o \ ++ $(INSNEMIT_SEQ_O) \ + insn-extract.o \ + insn-latencytab.o \ + insn-modes.o \ +@@ -1820,7 +1827,8 @@ TREECHECKING = @TREECHECKING@ + FULL_DRIVER_NAME=$(target_noncanonical)-gcc-$(version)$(exeext) + + MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \ +- insn-output.cc insn-recog.cc insn-emit.cc insn-extract.cc insn-peep.cc \ ++ insn-output.cc insn-recog.cc $(INSNEMIT_SEQ_SRC) \ ++ insn-extract.cc insn-peep.cc \ + insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \ + insn-latencytab.cc insn-opinit.cc insn-opinit.h insn-preds.cc insn-constants.h \ + tm-preds.h tm-constrs.h checksum-options $(GIMPLE_MATCH_PD_SEQ_SRC) \ +@@ -2437,11 +2445,11 @@ $(common_out_object_file): $(common_out_file) + # and compile them. + + .PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \ +- insn-emit.cc insn-recog.cc insn-extract.cc insn-output.cc insn-peep.cc \ +- insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \ +- insn-latencytab.cc insn-preds.cc $(GIMPLE_MATCH_PD_SEQ_SRC) \ +- $(GENERIC_MATCH_PD_SEQ_SRC) gimple-match-auto.h generic-match-auto.h \ +- insn-target-def.h ++ $(INSNEMIT_SEQ_SRC) insn-recog.cc insn-extract.cc insn-output.cc \ ++ insn-peep.cc insn-attr.h insn-attr-common.h insn-attrtab.cc \ ++ insn-dfatab.cc insn-latencytab.cc insn-preds.cc \ ++ $(GIMPLE_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \ ++ gimple-match-auto.h generic-match-auto.h insn-target-def.h + + # Dependencies for the md file. The first time through, we just assume + # the md file itself and the generated dependency file (in order to get +@@ -2464,7 +2472,7 @@ s-mddeps: $(md_file) $(MD_INCLUDES) build/genmddeps$(build_exeext) + simple_rtl_generated_h = insn-attr.h insn-attr-common.h insn-codes.h \ + insn-config.h insn-flags.h insn-target-def.h + +-simple_rtl_generated_c = insn-automata.cc insn-emit.cc \ ++simple_rtl_generated_c = insn-automata.cc \ + insn-extract.cc insn-output.cc \ + insn-peep.cc insn-recog.cc + +@@ -2493,8 +2501,20 @@ $(simple_generated_c:insn-%.cc=s-%): s-%: build/gen%$(build_exeext) + $(SHELL) $(srcdir)/../move-if-change tmp-$*.cc insn-$*.cc + $(STAMP) s-$* + ++# genemit splits its output into different files and doesn't write to ++# stdout. (but rather to tmp-emit-01.cc..tmp-emit-10.cc) ++$(INSNEMIT_SEQ_SRC): s-tmp-emit; @true ++s-tmp-emit: build/genemit$(build_exeext) $(MD_DEPS) insn-conditions.md ++ $(RUN_GEN) build/genemit$(build_exeext) $(md_file) insn-conditions.md \ ++ $(addprefix -O,${INSNEMIT_SEQ_TMP}) ++ $(foreach id, $(INSNEMIT_SPLITS_SEQ), \ ++ $(SHELL) $(srcdir)/../move-if-change tmp-emit-$(id).cc \ ++ insn-emit-$(id).cc;) ++ $(STAMP) s-tmp-emit ++ + # gencheck doesn't read the machine description, and the file produced + # doesn't use the insn-* convention. ++ + tree-check.h: s-check ; @true + s-check : build/gencheck$(build_exeext) + $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h +diff --git a/gcc/configure b/gcc/configure +index cc8247037569..c98088bea90d 100755 +--- a/gcc/configure ++++ b/gcc/configure +@@ -838,6 +838,7 @@ enable_gcov + enable_shared + enable_fixed_point + enable_decimal_float ++DEFAULT_INSNEMIT_PARTITIONS + DEFAULT_MATCHPD_PARTITIONS + with_float + with_cpu +@@ -967,6 +968,7 @@ enable_multilib + enable_multiarch + with_stack_clash_protection_guard_size + with_matchpd_partitions ++with_insnemit_partitions + enable___cxa_atexit + enable_decimal_float + enable_fixed_point +@@ -1837,6 +1839,9 @@ Optional Packages: + --with-matchpd-partitions=num + Set the number of partitions to make for gimple and + generic when splitting match.pd. [default=10] ++ --with-insnemit-partitions=num ++ Set the number of partitions of insn-emit.cc for ++ genemit to create. [default=10] + --with-dwarf2 force the default debug format to be DWARF 2 (or + later) + --with-specs=SPECS add SPECS to driver command-line processing +@@ -7938,6 +7943,21 @@ fi + + + ++# Specify the number of splits of insn-emit.cc to generate. ++ ++# Check whether --with-insnemit-partitions was given. ++if test "${with_insnemit_partitions+set}" = set; then : ++ withval=$with_insnemit_partitions; DEFAULT_INSNEMIT_PARTITIONS="$with_insnemit_partitions" ++else ++ DEFAULT_INSNEMIT_PARTITIONS=10 ++fi ++ ++if (test $DEFAULT_INSNEMIT_PARTITIONS -lt 1); then ++ as_fn_error $? "Invalid value $DEFAULT_INSNEMIT_PARTITIONS for --with-insnemit-partitions. Cannot be negative." "$LINENO" 5 ++fi ++ ++ ++ + # Enable __cxa_atexit for C++. + # Check whether --enable-__cxa_atexit was given. + if test "${enable___cxa_atexit+set}" = set; then : +@@ -19891,7 +19911,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 19894 "configure" ++#line 19914 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +@@ -19997,7 +20017,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 20000 "configure" ++#line 20020 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +diff --git a/gcc/configure.ac b/gcc/configure.ac +index d02ffc22a3a3..7021f95da3ee 100644 +--- a/gcc/configure.ac ++++ b/gcc/configure.ac +@@ -956,6 +956,19 @@ fi + + AC_SUBST(DEFAULT_MATCHPD_PARTITIONS) + ++# Specify the number of splits of insn-emit.cc to generate. ++AC_ARG_WITH(insnemit-partitions, ++[AS_HELP_STRING([--with-insnemit-partitions=num], ++[Set the number of partitions of insn-emit.cc for genemit to create. [default=10]])], ++[DEFAULT_INSNEMIT_PARTITIONS="$with_insnemit_partitions"], [DEFAULT_INSNEMIT_PARTITIONS=10]) ++if (test $DEFAULT_INSNEMIT_PARTITIONS -lt 1); then ++ AC_MSG_ERROR(m4_normalize([ ++ Invalid value $DEFAULT_INSNEMIT_PARTITIONS for --with-insnemit-partitions. \ ++ Cannot be negative.])) ++fi ++ ++AC_SUBST(DEFAULT_INSNEMIT_PARTITIONS) ++ + # Enable __cxa_atexit for C++. + AC_ARG_ENABLE(__cxa_atexit, + [AS_HELP_STRING([--enable-__cxa_atexit], [enable __cxa_atexit for C++])], +diff --git a/gcc/genemit.cc b/gcc/genemit.cc +index 33c9ec05d6fc..18c95e3f6412 100644 +--- a/gcc/genemit.cc ++++ b/gcc/genemit.cc +@@ -49,29 +49,29 @@ struct clobber_ent + struct clobber_ent *next; + }; + +-static void output_peephole2_scratches (rtx); ++static void output_peephole2_scratches (rtx, FILE*); + + /* True for _optab if that optab isn't allowed to fail. */ + static bool nofail_optabs[NUM_OPTABS]; + + static void +-print_code (RTX_CODE code) ++print_code (RTX_CODE code, FILE *file) + { + const char *p1; + for (p1 = GET_RTX_NAME (code); *p1; p1++) +- putchar (TOUPPER (*p1)); ++ fprintf (file, "%c", TOUPPER (*p1)); + } + + static void +-gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) ++gen_rtx_scratch (rtx x, enum rtx_code subroutine_type, FILE *file) + { + if (subroutine_type == DEFINE_PEEPHOLE2) + { +- printf ("operand%d", XINT (x, 0)); ++ fprintf (file, "operand%d", XINT (x, 0)); + } + else + { +- printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); ++ fprintf (file, "gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); + } + } + +@@ -79,7 +79,8 @@ gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) + substituting any operand references appearing within. */ + + static void +-gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) ++gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info, ++ FILE *file) + { + RTX_CODE code; + int i; +@@ -89,7 +90,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + + if (x == 0) + { +- printf ("NULL_RTX"); ++ fprintf (file, "NULL_RTX"); + return; + } + +@@ -103,67 +104,67 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + { + if (used[XINT (x, 0)]) + { +- printf ("copy_rtx (operand%d)", XINT (x, 0)); ++ fprintf (file, "copy_rtx (operand%d)", XINT (x, 0)); + return; + } + used[XINT (x, 0)] = 1; + } +- printf ("operand%d", XINT (x, 0)); ++ fprintf (file, "operand%d", XINT (x, 0)); + return; + + case MATCH_OP_DUP: +- printf ("gen_rtx_fmt_"); ++ fprintf (file, "gen_rtx_fmt_"); + for (i = 0; i < XVECLEN (x, 1); i++) +- printf ("e"); +- printf (" (GET_CODE (operand%d), ", XINT (x, 0)); ++ fprintf (file, "e"); ++ fprintf (file, " (GET_CODE (operand%d), ", XINT (x, 0)); + if (GET_MODE (x) == VOIDmode) +- printf ("GET_MODE (operand%d)", XINT (x, 0)); ++ fprintf (file, "GET_MODE (operand%d)", XINT (x, 0)); + else +- printf ("%smode", GET_MODE_NAME (GET_MODE (x))); ++ fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x))); + for (i = 0; i < XVECLEN (x, 1); i++) + { +- printf (",\n\t\t"); +- gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info); ++ fprintf (file, ",\n\t\t"); ++ gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info, file); + } +- printf (")"); ++ fprintf (file, ")"); + return; + + case MATCH_OPERATOR: +- printf ("gen_rtx_fmt_"); ++ fprintf (file, "gen_rtx_fmt_"); + for (i = 0; i < XVECLEN (x, 2); i++) +- printf ("e"); +- printf (" (GET_CODE (operand%d)", XINT (x, 0)); +- printf (", %smode", GET_MODE_NAME (GET_MODE (x))); ++ fprintf (file, "e"); ++ fprintf (file, " (GET_CODE (operand%d)", XINT (x, 0)); ++ fprintf (file, ", %smode", GET_MODE_NAME (GET_MODE (x))); + for (i = 0; i < XVECLEN (x, 2); i++) + { +- printf (",\n\t\t"); +- gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info); ++ fprintf (file, ",\n\t\t"); ++ gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info, file); + } +- printf (")"); ++ fprintf (file, ")"); + return; + + case MATCH_PARALLEL: + case MATCH_PAR_DUP: +- printf ("operand%d", XINT (x, 0)); ++ fprintf (file, "operand%d", XINT (x, 0)); + return; + + case MATCH_SCRATCH: +- gen_rtx_scratch (x, subroutine_type); ++ gen_rtx_scratch (x, subroutine_type, file); + return; + + case PC: +- printf ("pc_rtx"); ++ fprintf (file, "pc_rtx"); + return; + case RETURN: +- printf ("ret_rtx"); ++ fprintf (file, "ret_rtx"); + return; + case SIMPLE_RETURN: +- printf ("simple_return_rtx"); ++ fprintf (file, "simple_return_rtx"); + return; + case CLOBBER: + if (REG_P (XEXP (x, 0))) + { +- printf ("gen_hard_reg_clobber (%smode, %i)", ++ fprintf (file, "gen_hard_reg_clobber (%smode, %i)", + GET_MODE_NAME (GET_MODE (XEXP (x, 0))), + REGNO (XEXP (x, 0))); + return; +@@ -172,22 +173,22 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + + case CONST_INT: + if (INTVAL (x) == 0) +- printf ("const0_rtx"); ++ fprintf (file, "const0_rtx"); + else if (INTVAL (x) == 1) +- printf ("const1_rtx"); ++ fprintf (file, "const1_rtx"); + else if (INTVAL (x) == -1) +- printf ("constm1_rtx"); ++ fprintf (file, "constm1_rtx"); + else if (-MAX_SAVED_CONST_INT <= INTVAL (x) + && INTVAL (x) <= MAX_SAVED_CONST_INT) +- printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", ++ fprintf (file, "const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", + (int) INTVAL (x)); + else if (INTVAL (x) == STORE_FLAG_VALUE) +- printf ("const_true_rtx"); ++ fprintf (file, "const_true_rtx"); + else + { +- printf ("GEN_INT ("); +- printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x)); +- printf (")"); ++ fprintf (file, "GEN_INT ("); ++ fprintf (file, HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x)); ++ fprintf (file, ")"); + } + return; + +@@ -195,7 +196,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + /* Handle `const_double_zero' rtx. */ + if (CONST_DOUBLE_REAL_VALUE (x)->cl == rvc_zero) + { +- printf ("CONST_DOUBLE_ATOF (\"0\", %smode)", ++ fprintf (file, "CONST_DOUBLE_ATOF (\"0\", %smode)", + GET_MODE_NAME (GET_MODE (x))); + return; + } +@@ -210,12 +211,12 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + break; + } + +- printf ("gen_rtx_"); +- print_code (code); +- printf (" ("); ++ fprintf (file, "gen_rtx_"); ++ print_code (code, file); ++ fprintf (file, " ("); + if (!always_void_p (code)) + { +- printf ("%smode", GET_MODE_NAME (GET_MODE (x))); ++ fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x))); + sep = ",\n\t"; + } + +@@ -225,41 +226,41 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + { + if (fmt[i] == '0') + break; +- fputs (sep, stdout); ++ fputs (sep, file); + switch (fmt[i]) + { + case 'e': case 'u': +- gen_exp (XEXP (x, i), subroutine_type, used, info); ++ gen_exp (XEXP (x, i), subroutine_type, used, info, file); + break; + + case 'i': +- printf ("%u", XINT (x, i)); ++ fprintf (file, "%u", XINT (x, i)); + break; + + case 'r': +- printf ("%u", REGNO (x)); ++ fprintf (file, "%u", REGNO (x)); + break; + + case 'p': + /* We don't have a way of parsing polynomial offsets yet, + and hopefully never will. */ +- printf ("%d", SUBREG_BYTE (x).to_constant ()); ++ fprintf (file, "%d", SUBREG_BYTE (x).to_constant ()); + break; + + case 's': +- printf ("\"%s\"", XSTR (x, i)); ++ fprintf (file, "\"%s\"", XSTR (x, i)); + break; + + case 'E': + { + int j; +- printf ("gen_rtvec (%d", XVECLEN (x, i)); ++ fprintf (file, "gen_rtvec (%d", XVECLEN (x, i)); + for (j = 0; j < XVECLEN (x, i); j++) + { +- printf (",\n\t\t"); +- gen_exp (XVECEXP (x, i, j), subroutine_type, used, info); ++ fprintf (file, ",\n\t\t"); ++ gen_exp (XVECEXP (x, i, j), subroutine_type, used, info, file); + } +- printf (")"); ++ fprintf (file, ")"); + break; + } + +@@ -268,14 +269,14 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + } + sep = ",\n\t"; + } +- printf (")"); ++ fprintf (file, ")"); + } + + /* Output code to emit the instruction patterns in VEC, with each element + becoming a separate instruction. USED is as for gen_exp. */ + + static void +-gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) ++gen_emit_seq (rtvec vec, char *used, md_rtx_info *info, FILE *file) + { + for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) + { +@@ -283,17 +284,17 @@ gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) + rtx next = RTVEC_ELT (vec, i); + if (const char *name = get_emit_function (next)) + { +- printf (" %s (", name); +- gen_exp (next, DEFINE_EXPAND, used, info); +- printf (");\n"); ++ fprintf (file, " %s (", name); ++ gen_exp (next, DEFINE_EXPAND, used, info, file); ++ fprintf (file, ");\n"); + if (!last_p && needs_barrier_p (next)) +- printf (" emit_barrier ();"); ++ fprintf (file, " emit_barrier ();"); + } + else + { +- printf (" emit ("); +- gen_exp (next, DEFINE_EXPAND, used, info); +- printf (", %s);\n", last_p ? "false" : "true"); ++ fprintf (file, " emit ("); ++ gen_exp (next, DEFINE_EXPAND, used, info, file); ++ fprintf (file, ", %s);\n", last_p ? "false" : "true"); + } + } + } +@@ -303,27 +304,27 @@ gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) + for use in error messages. */ + + static void +-emit_c_code (const char *code, bool can_fail_p, const char *name) ++emit_c_code (const char *code, bool can_fail_p, const char *name, FILE *file) + { + if (can_fail_p) +- printf ("#define FAIL return (end_sequence (), _val)\n"); ++ fprintf (file, "#define FAIL return (end_sequence (), _val)\n"); + else +- printf ("#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" ++ fprintf (file, "#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" + " (void)0\n", name); +- printf ("#define DONE return (_val = get_insns (), " ++ fprintf (file, "#define DONE return (_val = get_insns (), " + "end_sequence (), _val)\n"); + +- rtx_reader_ptr->print_md_ptr_loc (code); +- printf ("%s\n", code); ++ rtx_reader_ptr->print_md_ptr_loc (code, file); ++ fprintf (file, "%s\n", code); + +- printf ("#undef DONE\n"); +- printf ("#undef FAIL\n"); ++ fprintf (file, "#undef DONE\n"); ++ fprintf (file, "#undef FAIL\n"); + } + + /* Generate the `gen_...' function for a DEFINE_INSN. */ + + static void +-gen_insn (md_rtx_info *info) ++gen_insn (md_rtx_info *info, FILE *file) + { + struct pattern_stats stats; + int i; +@@ -409,7 +410,7 @@ gen_insn (md_rtx_info *info) + if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*') + return; + +- printf ("/* %s:%d */\n", info->loc.filename, info->loc.lineno); ++ fprintf (file, "/* %s:%d */\n", info->loc.filename, info->loc.lineno); + + /* Find out how many operands this function has. */ + get_pattern_stats (&stats, XVEC (insn, 1)); +@@ -417,17 +418,17 @@ gen_insn (md_rtx_info *info) + fatal_at (info->loc, "match_dup operand number has no match_operand"); + + /* Output the function name and argument declarations. */ +- printf ("rtx\ngen_%s (", XSTR (insn, 0)); ++ fprintf (file, "rtx\ngen_%s (", XSTR (insn, 0)); + if (stats.num_generator_args) + for (i = 0; i < stats.num_generator_args; i++) + if (i) +- printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i); ++ fprintf (file, ",\n\trtx operand%d ATTRIBUTE_UNUSED", i); + else +- printf ("rtx operand%d ATTRIBUTE_UNUSED", i); ++ fprintf (file, "rtx operand%d ATTRIBUTE_UNUSED", i); + else +- printf ("void"); +- printf (")\n"); +- printf ("{\n"); ++ fprintf (file, "void"); ++ fprintf (file, ")\n"); ++ fprintf (file, "{\n"); + + /* Output code to construct and return the rtl for the instruction body. */ + +@@ -436,16 +437,16 @@ gen_insn (md_rtx_info *info) + char *used = (XVECLEN (insn, 1) == 1 + ? NULL + : XCNEWVEC (char, stats.num_generator_args)); +- printf (" return "); +- gen_exp (pattern, DEFINE_INSN, used, info); +- printf (";\n}\n\n"); ++ fprintf (file, " return "); ++ gen_exp (pattern, DEFINE_INSN, used, info, file); ++ fprintf (file, ";\n}\n\n"); + XDELETEVEC (used); + } + + /* Generate the `gen_...' function for a DEFINE_EXPAND. */ + + static void +-gen_expand (md_rtx_info *info) ++gen_expand (md_rtx_info *info, FILE *file) + { + struct pattern_stats stats; + int i; +@@ -466,17 +467,17 @@ gen_expand (md_rtx_info *info) + "numbers above all other operands", XSTR (expand, 0)); + + /* Output the function name and argument declarations. */ +- printf ("rtx\ngen_%s (", XSTR (expand, 0)); ++ fprintf (file, "rtx\ngen_%s (", XSTR (expand, 0)); + if (stats.num_generator_args) + for (i = 0; i < stats.num_generator_args; i++) + if (i) +- printf (",\n\trtx operand%d", i); ++ fprintf (file, ",\n\trtx operand%d", i); + else +- printf ("rtx operand%d", i); ++ fprintf (file, "rtx operand%d", i); + else +- printf ("void"); +- printf (")\n"); +- printf ("{\n"); ++ fprintf (file, "void"); ++ fprintf (file, ")\n"); ++ fprintf (file, "{\n"); + + /* If we don't have any C code to write, only one insn is being written, + and no MATCH_DUPs are present, we can just return the desired insn +@@ -485,18 +486,18 @@ gen_expand (md_rtx_info *info) + && stats.max_opno >= stats.max_dup_opno + && XVECLEN (expand, 1) == 1) + { +- printf (" return "); +- gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info); +- printf (";\n}\n\n"); ++ fprintf (file, " return "); ++ gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info, file); ++ fprintf (file, ";\n}\n\n"); + return; + } + + /* For each operand referred to only with MATCH_DUPs, + make a local variable. */ + for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++) +- printf (" rtx operand%d;\n", i); +- printf (" rtx_insn *_val = 0;\n"); +- printf (" start_sequence ();\n"); ++ fprintf (file, " rtx operand%d;\n", i); ++ fprintf (file, " rtx_insn *_val = 0;\n"); ++ fprintf (file, " start_sequence ();\n"); + + /* The fourth operand of DEFINE_EXPAND is some code to be executed + before the actual construction. +@@ -506,13 +507,13 @@ gen_expand (md_rtx_info *info) + So copy the operand values there before executing it. */ + if (XSTR (expand, 3) && *XSTR (expand, 3)) + { +- printf (" {\n"); ++ fprintf (file, " {\n"); + if (stats.num_operand_vars > 0) +- printf (" rtx operands[%d];\n", stats.num_operand_vars); ++ fprintf (file, " rtx operands[%d];\n", stats.num_operand_vars); + + /* Output code to copy the arguments into `operands'. */ + for (i = 0; i < stats.num_generator_args; i++) +- printf (" operands[%d] = operand%d;\n", i, i); ++ fprintf (file, " operands[%d] = operand%d;\n", i, i); + + /* Output the special code to be executed before the sequence + is generated. */ +@@ -524,7 +525,7 @@ gen_expand (md_rtx_info *info) + if (nofail_optabs[p.op]) + can_fail_p = false; + } +- emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0)); ++ emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0), file); + + /* Output code to copy the arguments back out of `operands' + (unless we aren't going to use them at all). */ +@@ -532,29 +533,29 @@ gen_expand (md_rtx_info *info) + { + for (i = 0; i <= MAX (stats.max_opno, stats.max_dup_opno); i++) + { +- printf (" operand%d = operands[%d];\n", i, i); +- printf (" (void) operand%d;\n", i); ++ fprintf (file, " operand%d = operands[%d];\n", i, i); ++ fprintf (file, " (void) operand%d;\n", i); + } + } +- printf (" }\n"); ++ fprintf (file, " }\n"); + } + + used = XCNEWVEC (char, stats.num_operand_vars); +- gen_emit_seq (XVEC (expand, 1), used, info); ++ gen_emit_seq (XVEC (expand, 1), used, info, file); + XDELETEVEC (used); + + /* Call `get_insns' to extract the list of all the + insns emitted within this gen_... function. */ + +- printf (" _val = get_insns ();\n"); +- printf (" end_sequence ();\n"); +- printf (" return _val;\n}\n\n"); ++ fprintf (file, " _val = get_insns ();\n"); ++ fprintf (file, " end_sequence ();\n"); ++ fprintf (file, " return _val;\n}\n\n"); + } + + /* Like gen_expand, but generates insns resulting from splitting SPLIT. */ + + static void +-gen_split (md_rtx_info *info) ++gen_split (md_rtx_info *info, FILE *file) + { + struct pattern_stats stats; + int i; +@@ -580,62 +581,62 @@ gen_split (md_rtx_info *info) + /* Output the prototype, function name and argument declarations. */ + if (GET_CODE (split) == DEFINE_PEEPHOLE2) + { +- printf ("extern rtx_insn *gen_%s_%d (rtx_insn *, rtx *);\n", ++ fprintf (file, "extern rtx_insn *gen_%s_%d (rtx_insn *, rtx *);\n", + name, info->index); +- printf ("rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED," ++ fprintf (file, "rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED," + " rtx *operands%s)\n", + name, info->index, unused); + } + else + { +- printf ("extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n", ++ fprintf (file, "extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n", + info->index); +- printf ("rtx_insn *\ngen_split_%d " ++ fprintf (file, "rtx_insn *\ngen_split_%d " + "(rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", + info->index, unused); + } +- printf ("{\n"); ++ fprintf (file, "{\n"); + + /* Declare all local variables. */ + for (i = 0; i < stats.num_operand_vars; i++) +- printf (" rtx operand%d;\n", i); +- printf (" rtx_insn *_val = NULL;\n"); ++ fprintf (file, " rtx operand%d;\n", i); ++ fprintf (file, " rtx_insn *_val = NULL;\n"); + + if (GET_CODE (split) == DEFINE_PEEPHOLE2) +- output_peephole2_scratches (split); ++ output_peephole2_scratches (split, file); + + const char *fn = info->loc.filename; + for (const char *p = fn; *p; p++) + if (*p == '/') + fn = p + 1; + +- printf (" if (dump_file)\n"); +- printf (" fprintf (dump_file, \"Splitting with gen_%s_%d (%s:%d)\\n\");\n", ++ fprintf (file, " if (dump_file)\n"); ++ fprintf (file, " fprintf (dump_file, \"Splitting with gen_%s_%d (%s:%d)\\n\");\n", + name, info->index, fn, info->loc.lineno); + +- printf (" start_sequence ();\n"); ++ fprintf (file, " start_sequence ();\n"); + + /* The fourth operand of DEFINE_SPLIT is some code to be executed + before the actual construction. */ + + if (XSTR (split, 3)) +- emit_c_code (XSTR (split, 3), true, name); ++ emit_c_code (XSTR (split, 3), true, name, file); + + /* Output code to copy the arguments back out of `operands' */ + for (i = 0; i < stats.num_operand_vars; i++) + { +- printf (" operand%d = operands[%d];\n", i, i); +- printf (" (void) operand%d;\n", i); ++ fprintf (file, " operand%d = operands[%d];\n", i, i); ++ fprintf (file, " (void) operand%d;\n", i); + } + +- gen_emit_seq (XVEC (split, 2), used, info); ++ gen_emit_seq (XVEC (split, 2), used, info, file); + + /* Call `get_insns' to make a list of all the + insns emitted within this gen_... function. */ + +- printf (" _val = get_insns ();\n"); +- printf (" end_sequence ();\n"); +- printf (" return _val;\n}\n\n"); ++ fprintf (file, " _val = get_insns ();\n"); ++ fprintf (file, " end_sequence ();\n"); ++ fprintf (file, " return _val;\n}\n\n"); + + free (used); + } +@@ -645,37 +646,37 @@ gen_split (md_rtx_info *info) + the end of the vector. */ + + static void +-output_add_clobbers (md_rtx_info *info) ++output_add_clobbers (md_rtx_info *info, FILE *file) + { + struct clobber_pat *clobber; + struct clobber_ent *ent; + int i; + +- printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n"); +- printf ("{\n"); +- printf (" switch (insn_code_number)\n"); +- printf (" {\n"); ++ fprintf (file, "\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n"); ++ fprintf (file, "{\n"); ++ fprintf (file, " switch (insn_code_number)\n"); ++ fprintf (file, " {\n"); + + for (clobber = clobber_list; clobber; clobber = clobber->next) + { + for (ent = clobber->insns; ent; ent = ent->next) +- printf (" case %d:\n", ent->code_number); ++ fprintf (file, " case %d:\n", ent->code_number); + + for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) + { +- printf (" XVECEXP (pattern, 0, %d) = ", i); ++ fprintf (file, " XVECEXP (pattern, 0, %d) = ", i); + gen_exp (XVECEXP (clobber->pattern, 1, i), +- GET_CODE (clobber->pattern), NULL, info); +- printf (";\n"); ++ GET_CODE (clobber->pattern), NULL, info, file); ++ fprintf (file, ";\n"); + } + +- printf (" break;\n\n"); ++ fprintf (file, " break;\n\n"); + } + +- printf (" default:\n"); +- printf (" gcc_unreachable ();\n"); +- printf (" }\n"); +- printf ("}\n"); ++ fprintf (file, " default:\n"); ++ fprintf (file, " gcc_unreachable ();\n"); ++ fprintf (file, " }\n"); ++ fprintf (file, "}\n"); + } + + /* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code +@@ -684,16 +685,16 @@ output_add_clobbers (md_rtx_info *info) + SCRATCH. */ + + static void +-output_added_clobbers_hard_reg_p (void) ++output_added_clobbers_hard_reg_p (FILE *file) + { + struct clobber_pat *clobber; + struct clobber_ent *ent; + int clobber_p, used; + +- printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n"); +- printf ("{\n"); +- printf (" switch (insn_code_number)\n"); +- printf (" {\n"); ++ fprintf (file, "\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n"); ++ fprintf (file, "{\n"); ++ fprintf (file, " switch (insn_code_number)\n"); ++ fprintf (file, " {\n"); + + for (clobber_p = 0; clobber_p <= 1; clobber_p++) + { +@@ -702,25 +703,25 @@ output_added_clobbers_hard_reg_p (void) + if (clobber->has_hard_reg == clobber_p) + for (ent = clobber->insns; ent; ent = ent->next) + { +- printf (" case %d:\n", ent->code_number); ++ fprintf (file, " case %d:\n", ent->code_number); + used++; + } + + if (used) +- printf (" return %d;\n\n", clobber_p); ++ fprintf (file, " return %d;\n\n", clobber_p); + } + +- printf (" default:\n"); +- printf (" gcc_unreachable ();\n"); +- printf (" }\n"); +- printf ("}\n"); ++ fprintf (file, " default:\n"); ++ fprintf (file, " gcc_unreachable ();\n"); ++ fprintf (file, " }\n"); ++ fprintf (file, "}\n"); + } + + /* Generate code to invoke find_free_register () as needed for the + scratch registers used by the peephole2 pattern in SPLIT. */ + + static void +-output_peephole2_scratches (rtx split) ++output_peephole2_scratches (rtx split, FILE *file) + { + int i; + int insn_nr = 0; +@@ -745,12 +746,12 @@ output_peephole2_scratches (rtx split) + + if (first) + { +- printf (" HARD_REG_SET _regs_allocated;\n"); +- printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n"); ++ fprintf (file, " HARD_REG_SET _regs_allocated;\n"); ++ fprintf (file, " CLEAR_HARD_REG_SET (_regs_allocated);\n"); + first = false; + } + +- printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ ++ fprintf (file, " if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ + return NULL;\n", + XINT (elt, 0), + insn_nr, last_insn_nr, +@@ -766,50 +767,50 @@ output_peephole2_scratches (rtx split) + /* Print "arg" parameter declarations for each argument N of ONAME. */ + + static void +-print_overload_arguments (overloaded_name *oname) ++print_overload_arguments (overloaded_name *oname, FILE *file) + { + for (unsigned int i = 0; i < oname->arg_types.length (); ++i) +- printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i); ++ fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i); + } + + /* Print code to test whether INSTANCE should be chosen, given that + argument N of the overload is available as "arg". */ + + static void +-print_overload_test (overloaded_instance *instance) ++print_overload_test (overloaded_instance *instance, FILE *file) + { + for (unsigned int i = 0; i < instance->arg_values.length (); ++i) +- printf ("%sarg%d == %s", i == 0 ? " if (" : "\n && ", ++ fprintf (file, "%sarg%d == %s", i == 0 ? " if (" : "\n && ", + i, instance->arg_values[i]); +- printf (")\n"); ++ fprintf (file, ")\n"); + } + + /* Emit a maybe_code_for_* function for ONAME. */ + + static void +-handle_overloaded_code_for (overloaded_name *oname) ++handle_overloaded_code_for (overloaded_name *oname, FILE *file) + { + /* Print the function prototype. */ +- printf ("\ninsn_code\nmaybe_code_for_%s (", oname->name); +- print_overload_arguments (oname); +- printf (")\n{\n"); ++ fprintf (file, "\ninsn_code\nmaybe_code_for_%s (", oname->name); ++ print_overload_arguments (oname, file); ++ fprintf (file, ")\n{\n"); + + /* Use a sequence of "if" statements for each instance. */ + for (overloaded_instance *instance = oname->first_instance; + instance; instance = instance->next) + { +- print_overload_test (instance); +- printf (" return CODE_FOR_%s;\n", instance->name); ++ print_overload_test (instance, file); ++ fprintf (file, " return CODE_FOR_%s;\n", instance->name); + } + + /* Return null if no match was found. */ +- printf (" return CODE_FOR_nothing;\n}\n"); ++ fprintf (file, " return CODE_FOR_nothing;\n}\n"); + } + + /* Emit a maybe_gen_* function for ONAME. */ + + static void +-handle_overloaded_gen (overloaded_name *oname) ++handle_overloaded_gen (overloaded_name *oname, FILE *file) + { + unsigned HOST_WIDE_INT seen = 0; + /* All patterns must have the same number of operands. */ +@@ -826,25 +827,25 @@ handle_overloaded_gen (overloaded_name *oname) + seen |= mask; + + /* Print the function prototype. */ +- printf ("\nrtx\nmaybe_gen_%s (", oname->name); +- print_overload_arguments (oname); ++ fprintf (file, "\nrtx\nmaybe_gen_%s (", oname->name); ++ print_overload_arguments (oname, file); + for (int i = 0; i < stats.num_generator_args; ++i) +- printf (", rtx x%d", i); +- printf (")\n{\n"); ++ fprintf (file, ", rtx x%d", i); ++ fprintf (file, ")\n{\n"); + + /* Use maybe_code_for_*, instead of duplicating the selection + logic here. */ +- printf (" insn_code code = maybe_code_for_%s (", oname->name); ++ fprintf (file, " insn_code code = maybe_code_for_%s (", oname->name); + for (unsigned int i = 0; i < oname->arg_types.length (); ++i) +- printf ("%sarg%d", i == 0 ? "" : ", ", i); +- printf (");\n" ++ fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i); ++ fprintf (file, ");\n" + " if (code != CODE_FOR_nothing)\n" + " {\n" + " gcc_assert (insn_data[code].n_generator_args == %d);\n" + " return GEN_FCN (code) (", stats.num_generator_args); + for (int i = 0; i < stats.num_generator_args; ++i) +- printf ("%sx%d", i == 0 ? "" : ", ", i); +- printf (");\n" ++ fprintf (file, "%sx%d", i == 0 ? "" : ", ", i); ++ fprintf (file, ");\n" + " }\n" + " else\n" + " return NULL_RTX;\n" +@@ -852,12 +853,68 @@ handle_overloaded_gen (overloaded_name *oname) + } + } + ++void ++print_header (FILE *file) ++{ ++ fprintf (file, "/* Generated automatically by the program `genemit'\n\ ++from the machine description file `md'. */\n\n"); ++ ++ fprintf (file, "#define IN_TARGET_CODE 1\n"); ++ fprintf (file, "#include \"config.h\"\n"); ++ fprintf (file, "#include \"system.h\"\n"); ++ fprintf (file, "#include \"coretypes.h\"\n"); ++ fprintf (file, "#include \"backend.h\"\n"); ++ fprintf (file, "#include \"predict.h\"\n"); ++ fprintf (file, "#include \"tree.h\"\n"); ++ fprintf (file, "#include \"rtl.h\"\n"); ++ fprintf (file, "#include \"alias.h\"\n"); ++ fprintf (file, "#include \"varasm.h\"\n"); ++ fprintf (file, "#include \"stor-layout.h\"\n"); ++ fprintf (file, "#include \"calls.h\"\n"); ++ fprintf (file, "#include \"memmodel.h\"\n"); ++ fprintf (file, "#include \"tm_p.h\"\n"); ++ fprintf (file, "#include \"flags.h\"\n"); ++ fprintf (file, "#include \"insn-config.h\"\n"); ++ fprintf (file, "#include \"expmed.h\"\n"); ++ fprintf (file, "#include \"dojump.h\"\n"); ++ fprintf (file, "#include \"explow.h\"\n"); ++ fprintf (file, "#include \"emit-rtl.h\"\n"); ++ fprintf (file, "#include \"stmt.h\"\n"); ++ fprintf (file, "#include \"expr.h\"\n"); ++ fprintf (file, "#include \"insn-codes.h\"\n"); ++ fprintf (file, "#include \"optabs.h\"\n"); ++ fprintf (file, "#include \"dfp.h\"\n"); ++ fprintf (file, "#include \"output.h\"\n"); ++ fprintf (file, "#include \"recog.h\"\n"); ++ fprintf (file, "#include \"df.h\"\n"); ++ fprintf (file, "#include \"resource.h\"\n"); ++ fprintf (file, "#include \"reload.h\"\n"); ++ fprintf (file, "#include \"diagnostic-core.h\"\n"); ++ fprintf (file, "#include \"regs.h\"\n"); ++ fprintf (file, "#include \"tm-constrs.h\"\n"); ++ fprintf (file, "#include \"ggc.h\"\n"); ++ fprintf (file, "#include \"target.h\"\n\n"); ++} ++ ++auto_vec output_files; ++ ++static bool ++handle_arg (const char *arg) ++{ ++ if (arg[1] == 'O') ++ { ++ output_files.safe_push (&arg[2]); ++ return true; ++ } ++ return false; ++} ++ + int + main (int argc, const char **argv) + { + progname = "genemit"; + +- if (!init_rtx_reader_args (argc, argv)) ++ if (!init_rtx_reader_args_cb (argc, argv, handle_arg)) + return (FATAL_EXIT_CODE); + + #define DEF_INTERNAL_OPTAB_FN(NAME, FLAGS, OPTAB, TYPE) \ +@@ -867,86 +924,87 @@ main (int argc, const char **argv) + /* Assign sequential codes to all entries in the machine description + in parallel with the tables in insn-output.cc. */ + +- printf ("/* Generated automatically by the program `genemit'\n\ +-from the machine description file `md'. */\n\n"); ++ int npatterns = count_patterns (); ++ md_rtx_info info; ++ ++ bool to_stdout = false; ++ int npatterns_per_file = npatterns; ++ if (!output_files.is_empty ()) ++ npatterns_per_file = npatterns / output_files.length () + 1; ++ else ++ to_stdout = true; + +- printf ("#define IN_TARGET_CODE 1\n"); +- printf ("#include \"config.h\"\n"); +- printf ("#include \"system.h\"\n"); +- printf ("#include \"coretypes.h\"\n"); +- printf ("#include \"backend.h\"\n"); +- printf ("#include \"predict.h\"\n"); +- printf ("#include \"tree.h\"\n"); +- printf ("#include \"rtl.h\"\n"); +- printf ("#include \"alias.h\"\n"); +- printf ("#include \"varasm.h\"\n"); +- printf ("#include \"stor-layout.h\"\n"); +- printf ("#include \"calls.h\"\n"); +- printf ("#include \"memmodel.h\"\n"); +- printf ("#include \"tm_p.h\"\n"); +- printf ("#include \"flags.h\"\n"); +- printf ("#include \"insn-config.h\"\n"); +- printf ("#include \"expmed.h\"\n"); +- printf ("#include \"dojump.h\"\n"); +- printf ("#include \"explow.h\"\n"); +- printf ("#include \"emit-rtl.h\"\n"); +- printf ("#include \"stmt.h\"\n"); +- printf ("#include \"expr.h\"\n"); +- printf ("#include \"insn-codes.h\"\n"); +- printf ("#include \"optabs.h\"\n"); +- printf ("#include \"dfp.h\"\n"); +- printf ("#include \"output.h\"\n"); +- printf ("#include \"recog.h\"\n"); +- printf ("#include \"df.h\"\n"); +- printf ("#include \"resource.h\"\n"); +- printf ("#include \"reload.h\"\n"); +- printf ("#include \"diagnostic-core.h\"\n"); +- printf ("#include \"regs.h\"\n"); +- printf ("#include \"tm-constrs.h\"\n"); +- printf ("#include \"ggc.h\"\n"); +- printf ("#include \"target.h\"\n\n"); ++ gcc_assert (npatterns_per_file > 1); + +- /* Read the machine description. */ ++ /* Reverse so we can pop the first-added element. */ ++ output_files.reverse (); + +- md_rtx_info info; ++ int count = 0; ++ FILE *file = NULL; ++ ++ /* Read the machine description. */ + while (read_md_rtx (&info)) +- switch (GET_CODE (info.def)) +- { +- case DEFINE_INSN: +- gen_insn (&info); +- break; ++ { ++ if (count == 0 || count == npatterns_per_file) ++ { ++ bool is_last = !to_stdout && output_files.is_empty (); ++ if (file && !is_last) ++ if (fclose (file) != 0) ++ return FATAL_EXIT_CODE; + +- case DEFINE_EXPAND: +- printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); +- gen_expand (&info); +- break; ++ if (!output_files.is_empty ()) ++ { ++ const char *const filename = output_files.pop (); ++ file = fopen (filename, "w"); ++ } ++ else if (to_stdout) ++ file = stdout; ++ else ++ break; + +- case DEFINE_SPLIT: +- printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); +- gen_split (&info); +- break; ++ print_header (file); ++ count = 0; ++ } + +- case DEFINE_PEEPHOLE2: +- printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); +- gen_split (&info); +- break; ++ switch (GET_CODE (info.def)) ++ { ++ case DEFINE_INSN: ++ gen_insn (&info, file); ++ break; + +- default: +- break; +- } ++ case DEFINE_EXPAND: ++ fprintf (file, "/* %s:%d */\n", info.loc.filename, info.loc.lineno); ++ gen_expand (&info, file); ++ break; ++ ++ case DEFINE_SPLIT: ++ fprintf (file, "/* %s:%d */\n", info.loc.filename, info.loc.lineno); ++ gen_split (&info, file); ++ break; ++ ++ case DEFINE_PEEPHOLE2: ++ fprintf (file, "/* %s:%d */\n", info.loc.filename, info.loc.lineno); ++ gen_split (&info, file); ++ break; ++ ++ default: ++ break; ++ } ++ ++ count++; ++ } + + /* Write out the routines to add CLOBBERs to a pattern and say whether they + clobber a hard reg. */ +- output_add_clobbers (&info); +- output_added_clobbers_hard_reg_p (); ++ output_add_clobbers (&info, file); ++ output_added_clobbers_hard_reg_p (file); + + for (overloaded_name *oname = rtx_reader_ptr->get_overloads (); + oname; oname = oname->next) + { +- handle_overloaded_code_for (oname); +- handle_overloaded_gen (oname); ++ handle_overloaded_code_for (oname, file); ++ handle_overloaded_gen (oname, file); + } + +- fflush (stdout); +- return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ++ return (fclose (file) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); + } +diff --git a/gcc/gensupport.cc b/gcc/gensupport.cc +index f9efc6eb7572..f941f76a739f 100644 +--- a/gcc/gensupport.cc ++++ b/gcc/gensupport.cc +@@ -2631,6 +2631,61 @@ init_rtx_reader_args (int argc, const char **argv) + return init_rtx_reader_args_cb (argc, argv, 0); + } + ++/* Count the number of patterns in all queues and return the count. */ ++int ++count_patterns () ++{ ++ int count = 0, truth = 1; ++ rtx def; ++ class queue_elem *cur = define_attr_queue; ++ while (cur) ++ { ++ def = cur->data; ++ ++ truth = maybe_eval_c_test (get_c_test (def)); ++ if (truth || !insn_elision) ++ count++; ++ cur = cur->next; ++ } ++ ++ cur = define_pred_queue; ++ while (cur) ++ { ++ def = cur->data; ++ ++ truth = maybe_eval_c_test (get_c_test (def)); ++ if (truth || !insn_elision) ++ count++; ++ cur = cur->next; ++ } ++ ++ cur = define_insn_queue; ++ truth = 1; ++ while (cur) ++ { ++ def = cur->data; ++ ++ truth = maybe_eval_c_test (get_c_test (def)); ++ if (truth || !insn_elision) ++ count++; ++ cur = cur->next; ++ } ++ ++ cur = other_queue; ++ truth = 1; ++ while (cur) ++ { ++ def = cur->data; ++ ++ truth = maybe_eval_c_test (get_c_test (def)); ++ if (truth || !insn_elision) ++ count++; ++ cur = cur->next; ++ } ++ ++ return count; ++} ++ + /* Try to read a single rtx from the file. Return true on success, + describing it in *INFO. */ + +diff --git a/gcc/gensupport.h b/gcc/gensupport.h +index a1edfbd71908..510ba19405e4 100644 +--- a/gcc/gensupport.h ++++ b/gcc/gensupport.h +@@ -129,6 +129,7 @@ extern rtx add_implicit_parallel (rtvec); + extern rtx_reader *init_rtx_reader_args_cb (int, const char **, + bool (*)(const char *)); + extern rtx_reader *init_rtx_reader_args (int, const char **); ++extern int count_patterns (); + extern bool read_md_rtx (md_rtx_info *); + extern unsigned int get_num_insn_codes (); + +diff --git a/gcc/read-md.cc b/gcc/read-md.cc +index fd38818e3a3e..46ab9065e3e4 100644 +--- a/gcc/read-md.cc ++++ b/gcc/read-md.cc +@@ -132,9 +132,9 @@ md_reader::fprint_md_ptr_loc (FILE *outf, const void *ptr) + + /* Special fprint_md_ptr_loc for writing to STDOUT. */ + void +-md_reader::print_md_ptr_loc (const void *ptr) ++md_reader::print_md_ptr_loc (const void *ptr, FILE *file) + { +- fprint_md_ptr_loc (stdout, ptr); ++ fprint_md_ptr_loc (file, ptr); + } + + /* Return a condition that satisfies both COND1 and COND2. Either string +diff --git a/gcc/read-md.h b/gcc/read-md.h +index b309c9c3deb6..2adcb58478fe 100644 +--- a/gcc/read-md.h ++++ b/gcc/read-md.h +@@ -194,7 +194,7 @@ class md_reader + const struct ptr_loc *get_md_ptr_loc (const void *ptr); + void copy_md_ptr_loc (const void *new_ptr, const void *old_ptr); + void fprint_md_ptr_loc (FILE *outf, const void *ptr); +- void print_md_ptr_loc (const void *ptr); ++ void print_md_ptr_loc (const void *ptr, FILE * = stdout); + + struct enum_type *lookup_enum_type (const char *name); + void traverse_enum_types (htab_trav callback, void *info); +-- +2.44.0 + diff --git a/system/gcc/libgcc-always-build-gcceh.a.patch b/system/gcc/libgcc-always-build-gcceh.a.patch index 74ae89730..fd19fb350 100644 --- a/system/gcc/libgcc-always-build-gcceh.a.patch +++ b/system/gcc/libgcc-always-build-gcceh.a.patch @@ -4,7 +4,7 @@ Highly inspired by: diff -durN gcc-4.6.0.orig/libgcc/Makefile.in gcc-4.6.0/libgcc/Makefile.in --- gcc-4.6.0.orig/libgcc/Makefile.in 2011-01-26 05:19:58.000000000 +0100 +++ gcc-4.6.0/libgcc/Makefile.in 2011-09-12 18:17:12.743718974 +0200 -@@ -772,8 +772,9 @@ +@@ -960,8 +960,9 @@ libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_EXT) endif @@ -15,7 +15,7 @@ diff -durN gcc-4.6.0.orig/libgcc/Makefile.in gcc-4.6.0/libgcc/Makefile.in ifneq ($(LIBUNWIND),) all: libunwind$(SHLIB_EXT) endif -@@ -950,10 +951,6 @@ +@@ -1163,10 +1164,6 @@ install-shared: $(mkinstalldirs) $(DESTDIR)$(inst_libdir) @@ -26,7 +26,7 @@ diff -durN gcc-4.6.0.orig/libgcc/Makefile.in gcc-4.6.0/libgcc/Makefile.in $(subst @multilib_dir@,$(MULTIDIR),$(subst \ @shlib_base_name@,libgcc_s,$(subst \ @shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIB_INSTALL)))) -@@ -968,6 +965,10 @@ +@@ -1183,6 +1180,10 @@ chmod 644 $(DESTDIR)$(inst_libdir)/libgcov.a $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcov.a diff --git a/system/gcc/match-split.patch b/system/gcc/match-split.patch new file mode 100644 index 000000000..afb357b1d --- /dev/null +++ b/system/gcc/match-split.patch @@ -0,0 +1,3583 @@ +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21 + +From 49ed8cead428b48bf46afbbb37a4d043d00702d6 Mon Sep 17 00:00:00 2001 +From: Tamar Christina +Date: Fri, 5 May 2023 13:37:49 +0100 +Subject: [PATCH 04/15] genmatch: split shared code to gimple-match-exports.cc + +In preparation for automatically splitting match.pd files I split off the +non-static helper functions that are shared between the match.pd functions off +to another file. + +This file can be compiled in parallel and also allows us to later avoid +duplicate symbols errors. + +gcc/ChangeLog: + + PR bootstrap/84402 + * Makefile.in (OBJS): Add gimple-match-exports.o. + * genmatch.cc (decision_tree::gen): Export gimple_gimplify helpers. + * gimple-match-head.cc (gimple_simplify, gimple_resimplify1, + gimple_resimplify2, gimple_resimplify3, gimple_resimplify4, + gimple_resimplify5, constant_for_folding, convert_conditional_op, + maybe_resimplify_conditional_op, gimple_match_op::resimplify, + maybe_build_generic_op, build_call_internal, maybe_push_res_to_seq, + do_valueize, try_conditional_simplification, gimple_extract, + gimple_extract_op, canonicalize_code, commutative_binary_op_p, + commutative_ternary_op_p, first_commutative_argument, + associative_binary_op_p, directly_supported_p, + get_conditional_internal_fn): Moved to gimple-match-exports.cc + * gimple-match-exports.cc: New file. + +(cherry picked from commit 27fcf994c5515e1bbf2ff03d28fd2fa927c7e7b5) +--- + gcc/Makefile.in | 4 +- + gcc/genmatch.cc | 4 +- + gcc/gimple-match-exports.cc | 1253 +++++++++++++++++++++++++++++++++++ + gcc/gimple-match-head.cc | 1192 +-------------------------------- + 4 files changed, 1260 insertions(+), 1193 deletions(-) + create mode 100644 gcc/gimple-match-exports.cc + +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index 06d192fa9ed8..406856acde1c 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -223,6 +223,7 @@ libgcov-util.o-warn = -Wno-error + libgcov-driver-tool.o-warn = -Wno-error + libgcov-merge-tool.o-warn = -Wno-error + gimple-match.o-warn = -Wno-unused ++gimple-match-exports.o-warn = -Wno-unused + generic-match.o-warn = -Wno-unused + dfp.o-warn = -Wno-strict-aliasing + +@@ -1312,6 +1313,7 @@ ANALYZER_OBJS = \ + # the last objects to finish building. + OBJS = \ + gimple-match.o \ ++ gimple-match-exports.o \ + generic-match.o \ + insn-attrtab.o \ + insn-automata.o \ +@@ -2663,7 +2665,7 @@ s-tm-texi: build/genhooks$(build_exeext) $(srcdir)/doc/tm.texi.in + false; \ + fi + +-gimple-match.cc: s-match gimple-match-head.cc ; @true ++gimple-match.cc: s-match gimple-match-head.cc gimple-match-exports.cc ; @true + generic-match.cc: s-match generic-match-head.cc ; @true + + s-match: build/genmatch$(build_exeext) $(srcdir)/match.pd cfn-operators.pd +diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc +index a17ef8a23ed5..665d7e2106ff 100644 +--- a/gcc/genmatch.cc ++++ b/gcc/genmatch.cc +@@ -3957,7 +3957,7 @@ decision_tree::gen (FILE *f, bool gimple) + if (! has_kids_p) + { + if (gimple) +- fprintf (f, "\nstatic bool\n" ++ fprintf (f, "\nbool\n" + "gimple_simplify (gimple_match_op*, gimple_seq*,\n" + " tree (*)(tree), code_helper,\n" + " const tree"); +@@ -3980,7 +3980,7 @@ decision_tree::gen (FILE *f, bool gimple) + /* Then generate the main entry with the outermost switch and + tail-calls to the split-out functions. */ + if (gimple) +- fprintf (f, "\nstatic bool\n" ++ fprintf (f, "\nbool\n" + "gimple_simplify (gimple_match_op *res_op, gimple_seq *seq,\n" + " tree (*valueize)(tree) ATTRIBUTE_UNUSED,\n" + " code_helper code, const tree type"); +diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc +new file mode 100644 +index 000000000000..7aeb4ddb1524 +--- /dev/null ++++ b/gcc/gimple-match-exports.cc +@@ -0,0 +1,1253 @@ ++/* Helpers for the autogenerated gimple-match.cc file. ++ Copyright (C) 2023 Free Software Foundation, Inc. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify it under ++the terms of the GNU General Public License as published by the Free ++Software Foundation; either version 3, or (at your option) any later ++version. ++ ++GCC is distributed in the hope that it will be useful, but WITHOUT ANY ++WARRANTY; without even the implied warranty of MERCHANTABILITY or ++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++for more details. ++ ++You should have received a copy of the GNU General Public License ++along with GCC; see the file COPYING3. If not see ++. */ ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "backend.h" ++#include "target.h" ++#include "rtl.h" ++#include "tree.h" ++#include "gimple.h" ++#include "ssa.h" ++#include "cgraph.h" ++#include "vec-perm-indices.h" ++#include "fold-const.h" ++#include "fold-const-call.h" ++#include "stor-layout.h" ++#include "gimple-iterator.h" ++#include "gimple-fold.h" ++#include "calls.h" ++#include "tree-dfa.h" ++#include "builtins.h" ++#include "gimple-match.h" ++#include "tree-pass.h" ++#include "internal-fn.h" ++#include "case-cfn-macros.h" ++#include "gimplify.h" ++#include "optabs-tree.h" ++#include "tree-eh.h" ++#include "dbgcnt.h" ++#include "tm.h" ++#include "gimple-range.h" ++#include "langhooks.h" ++ ++tree (*mprts_hook) (gimple_match_op *); ++ ++extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), ++ code_helper, tree, tree); ++extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), ++ code_helper, tree, tree, tree); ++extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), ++ code_helper, tree, tree, tree, tree); ++extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), ++ code_helper, tree, tree, tree, tree, tree); ++extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), ++ code_helper, tree, tree, tree, tree, tree, tree); ++ ++/* Functions that are needed by gimple-match but that are exported and used in ++ other places in the compiler. */ ++ ++tree gimple_simplify (enum tree_code, tree, tree, gimple_seq *, ++ tree (*)(tree)); ++tree gimple_simplify (enum tree_code, tree, tree, tree, gimple_seq *, ++ tree (*)(tree)); ++tree gimple_simplify (enum tree_code, tree, tree, tree, tree, gimple_seq *, ++ tree (*)(tree)); ++tree gimple_simplify (combined_fn, tree, tree, gimple_seq *, ++ tree (*)(tree)); ++tree gimple_simplify (combined_fn, tree, tree, tree, gimple_seq *, ++ tree (*)(tree)); ++tree gimple_simplify (combined_fn, tree, tree, tree, tree, gimple_seq *, ++ tree (*)(tree)); ++ ++tree do_valueize (tree, tree (*)(tree), bool &); ++tree do_valueize (tree (*)(tree), tree); ++ ++/* Forward declarations of the private auto-generated matchers. ++ They expect valueized operands in canonical order and do not ++ perform simplification of all-constant operands. */ ++ ++static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, tree (*)(tree)); ++static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, tree (*)(tree)); ++static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, tree (*)(tree)); ++static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, tree (*)(tree)); ++static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, tree (*)(tree)); ++ ++/* Match and simplify the toplevel valueized operation THIS. ++ Replaces THIS with a simplified and/or canonicalized result and ++ returns whether any change was made. */ ++ ++bool ++gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree)) ++{ ++ switch (num_ops) ++ { ++ case 1: ++ return gimple_resimplify1 (seq, this, valueize); ++ case 2: ++ return gimple_resimplify2 (seq, this, valueize); ++ case 3: ++ return gimple_resimplify3 (seq, this, valueize); ++ case 4: ++ return gimple_resimplify4 (seq, this, valueize); ++ case 5: ++ return gimple_resimplify5 (seq, this, valueize); ++ default: ++ gcc_unreachable (); ++ } ++} ++ ++/* Return whether T is a constant that we'll dispatch to fold to ++ evaluate fully constant expressions. */ ++ ++static inline bool ++constant_for_folding (tree t) ++{ ++ return (CONSTANT_CLASS_P (t) ++ /* The following is only interesting to string builtins. */ ++ || (TREE_CODE (t) == ADDR_EXPR ++ && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)); ++} ++ ++/* Try to convert conditional operation ORIG_OP into an IFN_COND_* ++ operation. Return true on success, storing the new operation in NEW_OP. */ ++ ++static bool ++convert_conditional_op (gimple_match_op *orig_op, ++ gimple_match_op *new_op) ++{ ++ internal_fn ifn; ++ if (orig_op->code.is_tree_code ()) ++ ifn = get_conditional_internal_fn ((tree_code) orig_op->code); ++ else ++ { ++ auto cfn = combined_fn (orig_op->code); ++ if (!internal_fn_p (cfn)) ++ return false; ++ ifn = get_conditional_internal_fn (as_internal_fn (cfn)); ++ } ++ if (ifn == IFN_LAST) ++ return false; ++ unsigned int num_ops = orig_op->num_ops; ++ new_op->set_op (as_combined_fn (ifn), orig_op->type, num_ops + 2); ++ new_op->ops[0] = orig_op->cond.cond; ++ for (unsigned int i = 0; i < num_ops; ++i) ++ new_op->ops[i + 1] = orig_op->ops[i]; ++ tree else_value = orig_op->cond.else_value; ++ if (!else_value) ++ else_value = targetm.preferred_else_value (ifn, orig_op->type, ++ num_ops, orig_op->ops); ++ new_op->ops[num_ops + 1] = else_value; ++ return true; ++} ++/* Helper for gimple_simplify valueizing OP using VALUEIZE and setting ++ VALUEIZED to true if valueization changed OP. */ ++ ++inline tree ++do_valueize (tree op, tree (*valueize)(tree), bool &valueized) ++{ ++ if (valueize && TREE_CODE (op) == SSA_NAME) ++ { ++ tree tem = valueize (op); ++ if (tem && tem != op) ++ { ++ op = tem; ++ valueized = true; ++ } ++ } ++ return op; ++} ++ ++/* If in GIMPLE the operation described by RES_OP should be single-rhs, ++ build a GENERIC tree for that expression and update RES_OP accordingly. */ ++ ++void ++maybe_build_generic_op (gimple_match_op *res_op) ++{ ++ tree_code code = (tree_code) res_op->code; ++ tree val; ++ switch (code) ++ { ++ case REALPART_EXPR: ++ case IMAGPART_EXPR: ++ case VIEW_CONVERT_EXPR: ++ val = build1 (code, res_op->type, res_op->ops[0]); ++ res_op->set_value (val); ++ break; ++ case BIT_FIELD_REF: ++ val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1], ++ res_op->ops[2]); ++ REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse; ++ res_op->set_value (val); ++ break; ++ default:; ++ } ++} ++ ++/* Try to build RES_OP, which is known to be a call to FN. Return null ++ if the target doesn't support the function. */ ++ ++static gcall * ++build_call_internal (internal_fn fn, gimple_match_op *res_op) ++{ ++ if (direct_internal_fn_p (fn)) ++ { ++ tree_pair types = direct_internal_fn_types (fn, res_op->type, ++ res_op->ops); ++ if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH)) ++ return NULL; ++ } ++ return gimple_build_call_internal (fn, res_op->num_ops, ++ res_op->op_or_null (0), ++ res_op->op_or_null (1), ++ res_op->op_or_null (2), ++ res_op->op_or_null (3), ++ res_op->op_or_null (4)); ++} ++ ++/* RES_OP is the result of a simplification. If it is conditional, ++ try to replace it with the equivalent UNCOND form, such as an ++ IFN_COND_* call or a VEC_COND_EXPR. Also try to resimplify the ++ result of the replacement if appropriate, adding any new statements to ++ SEQ and using VALUEIZE as the valueization function. Return true if ++ this resimplification occurred and resulted in at least one change. */ ++ ++static bool ++maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op, ++ tree (*valueize) (tree)) ++{ ++ if (!res_op->cond.cond) ++ return false; ++ ++ if (!res_op->cond.else_value ++ && res_op->code.is_tree_code ()) ++ { ++ /* The "else" value doesn't matter. If the "then" value is a ++ gimple value, just use it unconditionally. This isn't a ++ simplification in itself, since there was no operation to ++ build in the first place. */ ++ if (gimple_simplified_result_is_gimple_val (res_op)) ++ { ++ res_op->cond.cond = NULL_TREE; ++ return false; ++ } ++ ++ /* Likewise if the operation would not trap. */ ++ bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type) ++ && TYPE_OVERFLOW_TRAPS (res_op->type)); ++ tree_code op_code = (tree_code) res_op->code; ++ bool op_could_trap; ++ ++ /* COND_EXPR will trap if, and only if, the condition ++ traps and hence we have to check this. For all other operations, we ++ don't need to consider the operands. */ ++ if (op_code == COND_EXPR) ++ op_could_trap = generic_expr_could_trap_p (res_op->ops[0]); ++ else ++ op_could_trap = operation_could_trap_p ((tree_code) res_op->code, ++ FLOAT_TYPE_P (res_op->type), ++ honor_trapv, ++ res_op->op_or_null (1)); ++ ++ if (!op_could_trap) ++ { ++ res_op->cond.cond = NULL_TREE; ++ return false; ++ } ++ } ++ ++ /* If the "then" value is a gimple value and the "else" value matters, ++ create a VEC_COND_EXPR between them, then see if it can be further ++ simplified. */ ++ gimple_match_op new_op; ++ if (res_op->cond.else_value ++ && VECTOR_TYPE_P (res_op->type) ++ && gimple_simplified_result_is_gimple_val (res_op)) ++ { ++ new_op.set_op (VEC_COND_EXPR, res_op->type, ++ res_op->cond.cond, res_op->ops[0], ++ res_op->cond.else_value); ++ *res_op = new_op; ++ return gimple_resimplify3 (seq, res_op, valueize); ++ } ++ ++ /* Otherwise try rewriting the operation as an IFN_COND_* call. ++ Again, this isn't a simplification in itself, since it's what ++ RES_OP already described. */ ++ if (convert_conditional_op (res_op, &new_op)) ++ *res_op = new_op; ++ ++ return false; ++} ++ ++/* If RES_OP is a call to a conditional internal function, try simplifying ++ the associated unconditional operation and using the result to build ++ a new conditional operation. For example, if RES_OP is: ++ ++ IFN_COND_ADD (COND, A, B, ELSE) ++ ++ try simplifying (plus A B) and using the result to build a replacement ++ for the whole IFN_COND_ADD. ++ ++ Return true if this approach led to a simplification, otherwise leave ++ RES_OP unchanged (and so suitable for other simplifications). When ++ returning true, add any new statements to SEQ and use VALUEIZE as the ++ valueization function. ++ ++ RES_OP is known to be a call to IFN. */ ++ ++static bool ++try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op, ++ gimple_seq *seq, tree (*valueize) (tree)) ++{ ++ code_helper op; ++ tree_code code = conditional_internal_fn_code (ifn); ++ if (code != ERROR_MARK) ++ op = code; ++ else ++ { ++ ifn = get_unconditional_internal_fn (ifn); ++ if (ifn == IFN_LAST) ++ return false; ++ op = as_combined_fn (ifn); ++ } ++ ++ unsigned int num_ops = res_op->num_ops; ++ gimple_match_op cond_op (gimple_match_cond (res_op->ops[0], ++ res_op->ops[num_ops - 1]), ++ op, res_op->type, num_ops - 2); ++ ++ memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops); ++ switch (num_ops - 2) ++ { ++ case 1: ++ if (!gimple_resimplify1 (seq, &cond_op, valueize)) ++ return false; ++ break; ++ case 2: ++ if (!gimple_resimplify2 (seq, &cond_op, valueize)) ++ return false; ++ break; ++ case 3: ++ if (!gimple_resimplify3 (seq, &cond_op, valueize)) ++ return false; ++ break; ++ default: ++ gcc_unreachable (); ++ } ++ *res_op = cond_op; ++ maybe_resimplify_conditional_op (seq, res_op, valueize); ++ return true; ++} ++ ++/* Helper for the autogenerated code, valueize OP. */ ++ ++tree ++do_valueize (tree (*valueize)(tree), tree op) ++{ ++ if (valueize && TREE_CODE (op) == SSA_NAME) ++ { ++ tree tem = valueize (op); ++ if (tem) ++ return tem; ++ } ++ return op; ++} ++ ++/* Push the exploded expression described by RES_OP as a statement to ++ SEQ if necessary and return a gimple value denoting the value of the ++ expression. If RES is not NULL then the result will be always RES ++ and even gimple values are pushed to SEQ. */ ++ ++tree ++maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res) ++{ ++ tree *ops = res_op->ops; ++ unsigned num_ops = res_op->num_ops; ++ ++ /* The caller should have converted conditional operations into an UNCOND ++ form and resimplified as appropriate. The conditional form only ++ survives this far if that conversion failed. */ ++ if (res_op->cond.cond) ++ return NULL_TREE; ++ ++ if (res_op->code.is_tree_code ()) ++ { ++ if (!res ++ && gimple_simplified_result_is_gimple_val (res_op)) ++ return ops[0]; ++ if (mprts_hook) ++ { ++ tree tem = mprts_hook (res_op); ++ if (tem) ++ return tem; ++ } ++ } ++ ++ if (!seq) ++ return NULL_TREE; ++ ++ /* Play safe and do not allow abnormals to be mentioned in ++ newly created statements. */ ++ for (unsigned int i = 0; i < num_ops; ++i) ++ if (TREE_CODE (ops[i]) == SSA_NAME ++ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i])) ++ return NULL_TREE; ++ ++ if (num_ops > 0 && COMPARISON_CLASS_P (ops[0])) ++ for (unsigned int i = 0; i < 2; ++i) ++ if (TREE_CODE (TREE_OPERAND (ops[0], i)) == SSA_NAME ++ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0], i))) ++ return NULL_TREE; ++ ++ if (res_op->code.is_tree_code ()) ++ { ++ auto code = tree_code (res_op->code); ++ if (!res) ++ { ++ if (gimple_in_ssa_p (cfun)) ++ res = make_ssa_name (res_op->type); ++ else ++ res = create_tmp_reg (res_op->type); ++ } ++ maybe_build_generic_op (res_op); ++ gimple *new_stmt = gimple_build_assign (res, code, ++ res_op->op_or_null (0), ++ res_op->op_or_null (1), ++ res_op->op_or_null (2)); ++ gimple_seq_add_stmt_without_update (seq, new_stmt); ++ return res; ++ } ++ else ++ { ++ gcc_assert (num_ops != 0); ++ auto fn = combined_fn (res_op->code); ++ gcall *new_stmt = NULL; ++ if (internal_fn_p (fn)) ++ { ++ /* Generate the given function if we can. */ ++ internal_fn ifn = as_internal_fn (fn); ++ new_stmt = build_call_internal (ifn, res_op); ++ if (!new_stmt) ++ return NULL_TREE; ++ } ++ else ++ { ++ /* Find the function we want to call. */ ++ tree decl = builtin_decl_implicit (as_builtin_fn (fn)); ++ if (!decl) ++ return NULL; ++ ++ /* We can't and should not emit calls to non-const functions. */ ++ if (!(flags_from_decl_or_type (decl) & ECF_CONST)) ++ return NULL; ++ ++ new_stmt = gimple_build_call (decl, num_ops, ++ res_op->op_or_null (0), ++ res_op->op_or_null (1), ++ res_op->op_or_null (2), ++ res_op->op_or_null (3), ++ res_op->op_or_null (4)); ++ } ++ if (!res) ++ { ++ if (gimple_in_ssa_p (cfun)) ++ res = make_ssa_name (res_op->type); ++ else ++ res = create_tmp_reg (res_op->type); ++ } ++ gimple_call_set_lhs (new_stmt, res); ++ gimple_seq_add_stmt_without_update (seq, new_stmt); ++ return res; ++ } ++} ++ ++ ++/* Public API overloads follow for operation being tree_code or ++ built_in_function and for one to three operands or arguments. ++ They return NULL_TREE if nothing could be simplified or ++ the resulting simplified value with parts pushed to SEQ. ++ If SEQ is NULL then if the simplification needs to create ++ new stmts it will fail. If VALUEIZE is non-NULL then all ++ SSA names will be valueized using that hook prior to ++ applying simplifications. */ ++ ++/* Unary ops. */ ++ ++tree ++gimple_simplify (enum tree_code code, tree type, ++ tree op0, ++ gimple_seq *seq, tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (op0)) ++ { ++ tree res = const_unop (code, type, op0); ++ if (res != NULL_TREE ++ && CONSTANT_CLASS_P (res)) ++ return res; ++ } ++ ++ gimple_match_op res_op; ++ if (!gimple_simplify (&res_op, seq, valueize, code, type, op0)) ++ return NULL_TREE; ++ return maybe_push_res_to_seq (&res_op, seq); ++} ++ ++/* Binary ops. */ ++ ++tree ++gimple_simplify (enum tree_code code, tree type, ++ tree op0, tree op1, ++ gimple_seq *seq, tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (op0) && constant_for_folding (op1)) ++ { ++ tree res = const_binop (code, type, op0, op1); ++ if (res != NULL_TREE ++ && CONSTANT_CLASS_P (res)) ++ return res; ++ } ++ ++ /* Canonicalize operand order both for matching and fallback stmt ++ generation. */ ++ if ((commutative_tree_code (code) ++ || TREE_CODE_CLASS (code) == tcc_comparison) ++ && tree_swap_operands_p (op0, op1)) ++ { ++ std::swap (op0, op1); ++ if (TREE_CODE_CLASS (code) == tcc_comparison) ++ code = swap_tree_comparison (code); ++ } ++ ++ gimple_match_op res_op; ++ if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1)) ++ return NULL_TREE; ++ return maybe_push_res_to_seq (&res_op, seq); ++} ++ ++/* Ternary ops. */ ++ ++tree ++gimple_simplify (enum tree_code code, tree type, ++ tree op0, tree op1, tree op2, ++ gimple_seq *seq, tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (op0) && constant_for_folding (op1) ++ && constant_for_folding (op2)) ++ { ++ tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2); ++ if (res != NULL_TREE ++ && CONSTANT_CLASS_P (res)) ++ return res; ++ } ++ ++ /* Canonicalize operand order both for matching and fallback stmt ++ generation. */ ++ if (commutative_ternary_tree_code (code) ++ && tree_swap_operands_p (op0, op1)) ++ std::swap (op0, op1); ++ ++ gimple_match_op res_op; ++ if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2)) ++ return NULL_TREE; ++ return maybe_push_res_to_seq (&res_op, seq); ++} ++ ++/* Builtin or internal function with one argument. */ ++ ++tree ++gimple_simplify (combined_fn fn, tree type, ++ tree arg0, ++ gimple_seq *seq, tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (arg0)) ++ { ++ tree res = fold_const_call (fn, type, arg0); ++ if (res && CONSTANT_CLASS_P (res)) ++ return res; ++ } ++ ++ gimple_match_op res_op; ++ if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0)) ++ return NULL_TREE; ++ return maybe_push_res_to_seq (&res_op, seq); ++} ++ ++/* Builtin or internal function with two arguments. */ ++ ++tree ++gimple_simplify (combined_fn fn, tree type, ++ tree arg0, tree arg1, ++ gimple_seq *seq, tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (arg0) ++ && constant_for_folding (arg1)) ++ { ++ tree res = fold_const_call (fn, type, arg0, arg1); ++ if (res && CONSTANT_CLASS_P (res)) ++ return res; ++ } ++ ++ gimple_match_op res_op; ++ if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1)) ++ return NULL_TREE; ++ return maybe_push_res_to_seq (&res_op, seq); ++} ++ ++/* Builtin or internal function with three arguments. */ ++ ++tree ++gimple_simplify (combined_fn fn, tree type, ++ tree arg0, tree arg1, tree arg2, ++ gimple_seq *seq, tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (arg0) ++ && constant_for_folding (arg1) ++ && constant_for_folding (arg2)) ++ { ++ tree res = fold_const_call (fn, type, arg0, arg1, arg2); ++ if (res && CONSTANT_CLASS_P (res)) ++ return res; ++ } ++ ++ gimple_match_op res_op; ++ if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2)) ++ return NULL_TREE; ++ return maybe_push_res_to_seq (&res_op, seq); ++} ++ ++/* Common subroutine of gimple_extract_op and gimple_simplify. Try to ++ describe STMT in RES_OP, returning true on success. Before recording ++ an operand, call: ++ ++ - VALUEIZE_CONDITION for a COND_EXPR condition ++ - VALUEIZE_OP for every other top-level operand ++ ++ Both routines take a tree argument and returns a tree. */ ++ ++template ++inline bool ++gimple_extract (gimple *stmt, gimple_match_op *res_op, ++ ValueizeOp valueize_op, ++ ValueizeCondition valueize_condition) ++{ ++ switch (gimple_code (stmt)) ++ { ++ case GIMPLE_ASSIGN: ++ { ++ enum tree_code code = gimple_assign_rhs_code (stmt); ++ tree type = TREE_TYPE (gimple_assign_lhs (stmt)); ++ switch (gimple_assign_rhs_class (stmt)) ++ { ++ case GIMPLE_SINGLE_RHS: ++ if (code == REALPART_EXPR ++ || code == IMAGPART_EXPR ++ || code == VIEW_CONVERT_EXPR) ++ { ++ tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); ++ res_op->set_op (code, type, valueize_op (op0)); ++ return true; ++ } ++ else if (code == BIT_FIELD_REF) ++ { ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree op0 = valueize_op (TREE_OPERAND (rhs1, 0)); ++ res_op->set_op (code, type, op0, ++ TREE_OPERAND (rhs1, 1), ++ TREE_OPERAND (rhs1, 2), ++ REF_REVERSE_STORAGE_ORDER (rhs1)); ++ return true; ++ } ++ else if (code == SSA_NAME) ++ { ++ tree op0 = gimple_assign_rhs1 (stmt); ++ res_op->set_op (TREE_CODE (op0), type, valueize_op (op0)); ++ return true; ++ } ++ break; ++ case GIMPLE_UNARY_RHS: ++ { ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ res_op->set_op (code, type, valueize_op (rhs1)); ++ return true; ++ } ++ case GIMPLE_BINARY_RHS: ++ { ++ tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt)); ++ tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt)); ++ res_op->set_op (code, type, rhs1, rhs2); ++ return true; ++ } ++ case GIMPLE_TERNARY_RHS: ++ { ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ if (code == COND_EXPR && COMPARISON_CLASS_P (rhs1)) ++ rhs1 = valueize_condition (rhs1); ++ else ++ rhs1 = valueize_op (rhs1); ++ tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt)); ++ tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt)); ++ res_op->set_op (code, type, rhs1, rhs2, rhs3); ++ return true; ++ } ++ default: ++ gcc_unreachable (); ++ } ++ break; ++ } ++ ++ case GIMPLE_CALL: ++ /* ??? This way we can't simplify calls with side-effects. */ ++ if (gimple_call_lhs (stmt) != NULL_TREE ++ && gimple_call_num_args (stmt) >= 1 ++ && gimple_call_num_args (stmt) <= 5) ++ { ++ combined_fn cfn; ++ if (gimple_call_internal_p (stmt)) ++ cfn = as_combined_fn (gimple_call_internal_fn (stmt)); ++ else ++ { ++ tree fn = gimple_call_fn (stmt); ++ if (!fn) ++ return false; ++ ++ fn = valueize_op (fn); ++ if (TREE_CODE (fn) != ADDR_EXPR ++ || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL) ++ return false; ++ ++ tree decl = TREE_OPERAND (fn, 0); ++ if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL ++ || !gimple_builtin_call_types_compatible_p (stmt, decl)) ++ return false; ++ ++ cfn = as_combined_fn (DECL_FUNCTION_CODE (decl)); ++ } ++ ++ unsigned int num_args = gimple_call_num_args (stmt); ++ res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args); ++ for (unsigned i = 0; i < num_args; ++i) ++ res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i)); ++ return true; ++ } ++ break; ++ ++ case GIMPLE_COND: ++ { ++ tree lhs = valueize_op (gimple_cond_lhs (stmt)); ++ tree rhs = valueize_op (gimple_cond_rhs (stmt)); ++ res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs); ++ return true; ++ } ++ ++ default: ++ break; ++ } ++ ++ return false; ++} ++ ++/* Try to describe STMT in RES_OP, returning true on success. ++ For GIMPLE_CONDs, describe the condition that is being tested. ++ For GIMPLE_ASSIGNs, describe the rhs of the assignment. ++ For GIMPLE_CALLs, describe the call. */ ++ ++bool ++gimple_extract_op (gimple *stmt, gimple_match_op *res_op) ++{ ++ auto nop = [](tree op) { return op; }; ++ return gimple_extract (stmt, res_op, nop, nop); ++} ++ ++/* The main STMT based simplification entry. It is used by the fold_stmt ++ and the fold_stmt_to_constant APIs. */ ++ ++bool ++gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq, ++ tree (*valueize)(tree), tree (*top_valueize)(tree)) ++{ ++ bool valueized = false; ++ auto valueize_op = [&](tree op) ++ { ++ return do_valueize (op, top_valueize, valueized); ++ }; ++ auto valueize_condition = [&](tree op) -> tree ++ { ++ bool cond_valueized = false; ++ tree lhs = do_valueize (TREE_OPERAND (op, 0), top_valueize, ++ cond_valueized); ++ tree rhs = do_valueize (TREE_OPERAND (op, 1), top_valueize, ++ cond_valueized); ++ gimple_match_op res_op2 (res_op->cond, TREE_CODE (op), ++ TREE_TYPE (op), lhs, rhs); ++ if ((gimple_resimplify2 (seq, &res_op2, valueize) ++ || cond_valueized) ++ && res_op2.code.is_tree_code ()) ++ { ++ auto code = tree_code (res_op2.code); ++ if (TREE_CODE_CLASS (code) == tcc_comparison) ++ { ++ valueized = true; ++ return build2 (code, TREE_TYPE (op), ++ res_op2.ops[0], res_op2.ops[1]); ++ } ++ else if (code == SSA_NAME ++ || code == INTEGER_CST ++ || code == VECTOR_CST) ++ { ++ valueized = true; ++ return res_op2.ops[0]; ++ } ++ } ++ return valueize_op (op); ++ }; ++ ++ if (!gimple_extract (stmt, res_op, valueize_op, valueize_condition)) ++ return false; ++ ++ if (res_op->code.is_internal_fn ()) ++ { ++ internal_fn ifn = internal_fn (res_op->code); ++ if (try_conditional_simplification (ifn, res_op, seq, valueize)) ++ return true; ++ } ++ ++ if (!res_op->reverse ++ && res_op->num_ops ++ && res_op->resimplify (seq, valueize)) ++ return true; ++ ++ return valueized; ++} ++ ++/* Helper that matches and simplifies the toplevel result from ++ a gimple_simplify run (where we don't want to build ++ a stmt in case it's used in in-place folding). Replaces ++ RES_OP with a simplified and/or canonicalized result and ++ returns whether any change was made. */ ++ ++static bool ++gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op, ++ tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (res_op->ops[0])) ++ { ++ tree tem = NULL_TREE; ++ if (res_op->code.is_tree_code ()) ++ { ++ auto code = tree_code (res_op->code); ++ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) ++ && TREE_CODE_LENGTH (code) == 1) ++ tem = const_unop (code, res_op->type, res_op->ops[0]); ++ } ++ else ++ tem = fold_const_call (combined_fn (res_op->code), res_op->type, ++ res_op->ops[0]); ++ if (tem != NULL_TREE ++ && CONSTANT_CLASS_P (tem)) ++ { ++ if (TREE_OVERFLOW_P (tem)) ++ tem = drop_tree_overflow (tem); ++ res_op->set_value (tem); ++ maybe_resimplify_conditional_op (seq, res_op, valueize); ++ return true; ++ } ++ } ++ ++ /* Limit recursion, there are cases like PR80887 and others, for ++ example when value-numbering presents us with unfolded expressions ++ that we are really not prepared to handle without eventual ++ oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50 ++ itself as available expression. */ ++ static unsigned depth; ++ if (depth > 10) ++ { ++ if (dump_file && (dump_flags & TDF_FOLDING)) ++ fprintf (dump_file, "Aborting expression simplification due to " ++ "deep recursion\n"); ++ return false; ++ } ++ ++ ++depth; ++ gimple_match_op res_op2 (*res_op); ++ if (gimple_simplify (&res_op2, seq, valueize, ++ res_op->code, res_op->type, res_op->ops[0])) ++ { ++ --depth; ++ *res_op = res_op2; ++ return true; ++ } ++ --depth; ++ ++ if (maybe_resimplify_conditional_op (seq, res_op, valueize)) ++ return true; ++ ++ return false; ++} ++ ++/* Helper that matches and simplifies the toplevel result from ++ a gimple_simplify run (where we don't want to build ++ a stmt in case it's used in in-place folding). Replaces ++ RES_OP with a simplified and/or canonicalized result and ++ returns whether any change was made. */ ++ ++static bool ++gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op, ++ tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (res_op->ops[0]) ++ && constant_for_folding (res_op->ops[1])) ++ { ++ tree tem = NULL_TREE; ++ if (res_op->code.is_tree_code ()) ++ { ++ auto code = tree_code (res_op->code); ++ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) ++ && TREE_CODE_LENGTH (code) == 2) ++ tem = const_binop (code, res_op->type, ++ res_op->ops[0], res_op->ops[1]); ++ } ++ else ++ tem = fold_const_call (combined_fn (res_op->code), res_op->type, ++ res_op->ops[0], res_op->ops[1]); ++ if (tem != NULL_TREE ++ && CONSTANT_CLASS_P (tem)) ++ { ++ if (TREE_OVERFLOW_P (tem)) ++ tem = drop_tree_overflow (tem); ++ res_op->set_value (tem); ++ maybe_resimplify_conditional_op (seq, res_op, valueize); ++ return true; ++ } ++ } ++ ++ /* Canonicalize operand order. */ ++ bool canonicalized = false; ++ bool is_comparison ++ = (res_op->code.is_tree_code () ++ && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison); ++ if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type)) ++ && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) ++ { ++ std::swap (res_op->ops[0], res_op->ops[1]); ++ if (is_comparison) ++ res_op->code = swap_tree_comparison (tree_code (res_op->code)); ++ canonicalized = true; ++ } ++ ++ /* Limit recursion, see gimple_resimplify1. */ ++ static unsigned depth; ++ if (depth > 10) ++ { ++ if (dump_file && (dump_flags & TDF_FOLDING)) ++ fprintf (dump_file, "Aborting expression simplification due to " ++ "deep recursion\n"); ++ return false; ++ } ++ ++ ++depth; ++ gimple_match_op res_op2 (*res_op); ++ if (gimple_simplify (&res_op2, seq, valueize, ++ res_op->code, res_op->type, ++ res_op->ops[0], res_op->ops[1])) ++ { ++ --depth; ++ *res_op = res_op2; ++ return true; ++ } ++ --depth; ++ ++ if (maybe_resimplify_conditional_op (seq, res_op, valueize)) ++ return true; ++ ++ return canonicalized; ++} ++ ++/* Helper that matches and simplifies the toplevel result from ++ a gimple_simplify run (where we don't want to build ++ a stmt in case it's used in in-place folding). Replaces ++ RES_OP with a simplified and/or canonicalized result and ++ returns whether any change was made. */ ++ ++static bool ++gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op, ++ tree (*valueize)(tree)) ++{ ++ if (constant_for_folding (res_op->ops[0]) ++ && constant_for_folding (res_op->ops[1]) ++ && constant_for_folding (res_op->ops[2])) ++ { ++ tree tem = NULL_TREE; ++ if (res_op->code.is_tree_code ()) ++ { ++ auto code = tree_code (res_op->code); ++ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) ++ && TREE_CODE_LENGTH (code) == 3) ++ tem = fold_ternary/*_to_constant*/ (code, res_op->type, ++ res_op->ops[0], res_op->ops[1], ++ res_op->ops[2]); ++ } ++ else ++ tem = fold_const_call (combined_fn (res_op->code), res_op->type, ++ res_op->ops[0], res_op->ops[1], res_op->ops[2]); ++ if (tem != NULL_TREE ++ && CONSTANT_CLASS_P (tem)) ++ { ++ if (TREE_OVERFLOW_P (tem)) ++ tem = drop_tree_overflow (tem); ++ res_op->set_value (tem); ++ maybe_resimplify_conditional_op (seq, res_op, valueize); ++ return true; ++ } ++ } ++ ++ /* Canonicalize operand order. */ ++ bool canonicalized = false; ++ int argno = first_commutative_argument (res_op->code, res_op->type); ++ if (argno >= 0 ++ && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) ++ { ++ std::swap (res_op->ops[argno], res_op->ops[argno + 1]); ++ canonicalized = true; ++ } ++ ++ /* Limit recursion, see gimple_resimplify1. */ ++ static unsigned depth; ++ if (depth > 10) ++ { ++ if (dump_file && (dump_flags & TDF_FOLDING)) ++ fprintf (dump_file, "Aborting expression simplification due to " ++ "deep recursion\n"); ++ return false; ++ } ++ ++ ++depth; ++ gimple_match_op res_op2 (*res_op); ++ if (gimple_simplify (&res_op2, seq, valueize, ++ res_op->code, res_op->type, ++ res_op->ops[0], res_op->ops[1], res_op->ops[2])) ++ { ++ --depth; ++ *res_op = res_op2; ++ return true; ++ } ++ --depth; ++ ++ if (maybe_resimplify_conditional_op (seq, res_op, valueize)) ++ return true; ++ ++ return canonicalized; ++} ++ ++/* Helper that matches and simplifies the toplevel result from ++ a gimple_simplify run (where we don't want to build ++ a stmt in case it's used in in-place folding). Replaces ++ RES_OP with a simplified and/or canonicalized result and ++ returns whether any change was made. */ ++ ++static bool ++gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op, ++ tree (*valueize)(tree)) ++{ ++ /* No constant folding is defined for four-operand functions. */ ++ ++ /* Canonicalize operand order. */ ++ bool canonicalized = false; ++ int argno = first_commutative_argument (res_op->code, res_op->type); ++ if (argno >= 0 ++ && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) ++ { ++ std::swap (res_op->ops[argno], res_op->ops[argno + 1]); ++ canonicalized = true; ++ } ++ ++ /* Limit recursion, see gimple_resimplify1. */ ++ static unsigned depth; ++ if (depth > 10) ++ { ++ if (dump_file && (dump_flags & TDF_FOLDING)) ++ fprintf (dump_file, "Aborting expression simplification due to " ++ "deep recursion\n"); ++ return false; ++ } ++ ++ ++depth; ++ gimple_match_op res_op2 (*res_op); ++ if (gimple_simplify (&res_op2, seq, valueize, ++ res_op->code, res_op->type, ++ res_op->ops[0], res_op->ops[1], res_op->ops[2], ++ res_op->ops[3])) ++ { ++ --depth; ++ *res_op = res_op2; ++ return true; ++ } ++ --depth; ++ ++ if (maybe_resimplify_conditional_op (seq, res_op, valueize)) ++ return true; ++ ++ return canonicalized; ++} ++ ++/* Helper that matches and simplifies the toplevel result from ++ a gimple_simplify run (where we don't want to build ++ a stmt in case it's used in in-place folding). Replaces ++ RES_OP with a simplified and/or canonicalized result and ++ returns whether any change was made. */ ++ ++static bool ++gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op, ++ tree (*valueize)(tree)) ++{ ++ /* No constant folding is defined for five-operand functions. */ ++ ++ /* Canonicalize operand order. */ ++ bool canonicalized = false; ++ int argno = first_commutative_argument (res_op->code, res_op->type); ++ if (argno >= 0 ++ && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) ++ { ++ std::swap (res_op->ops[argno], res_op->ops[argno + 1]); ++ canonicalized = true; ++ } ++ ++ gimple_match_op res_op2 (*res_op); ++ if (gimple_simplify (&res_op2, seq, valueize, ++ res_op->code, res_op->type, ++ res_op->ops[0], res_op->ops[1], res_op->ops[2], ++ res_op->ops[3], res_op->ops[4])) ++ { ++ *res_op = res_op2; ++ return true; ++ } ++ ++ if (maybe_resimplify_conditional_op (seq, res_op, valueize)) ++ return true; ++ ++ return canonicalized; ++} ++ ++/* Return a canonical form for CODE when operating on TYPE. The idea ++ is to remove redundant ways of representing the same operation so ++ that code_helpers can be hashed and compared for equality. ++ ++ The only current canonicalization is to replace built-in functions ++ with internal functions, in cases where internal-fn.def defines ++ such an internal function. ++ ++ Note that the new code_helper cannot necessarily be used in place of ++ the original code_helper. For example, the new code_helper might be ++ an internal function that the target does not support. */ ++ ++code_helper ++canonicalize_code (code_helper code, tree type) ++{ ++ if (code.is_fn_code ()) ++ return associated_internal_fn (combined_fn (code), type); ++ return code; ++} ++ ++/* Return true if CODE is a binary operation and if CODE is commutative when ++ operating on type TYPE. */ ++ ++bool ++commutative_binary_op_p (code_helper code, tree type) ++{ ++ if (code.is_tree_code ()) ++ return commutative_tree_code (tree_code (code)); ++ auto cfn = combined_fn (code); ++ return commutative_binary_fn_p (associated_internal_fn (cfn, type)); ++} ++ ++/* Return true if CODE represents a ternary operation and if the first two ++ operands are commutative when CODE is operating on TYPE. */ ++ ++bool ++commutative_ternary_op_p (code_helper code, tree type) ++{ ++ if (code.is_tree_code ()) ++ return commutative_ternary_tree_code (tree_code (code)); ++ auto cfn = combined_fn (code); ++ return commutative_ternary_fn_p (associated_internal_fn (cfn, type)); ++} ++ ++/* If CODE is commutative in two consecutive operands, return the ++ index of the first, otherwise return -1. */ ++ ++int ++first_commutative_argument (code_helper code, tree type) ++{ ++ if (code.is_tree_code ()) ++ { ++ auto tcode = tree_code (code); ++ if (commutative_tree_code (tcode) ++ || commutative_ternary_tree_code (tcode)) ++ return 0; ++ return -1; ++ } ++ auto cfn = combined_fn (code); ++ return first_commutative_argument (associated_internal_fn (cfn, type)); ++} ++ ++/* Return true if CODE is a binary operation that is associative when ++ operating on type TYPE. */ ++ ++bool ++associative_binary_op_p (code_helper code, tree type) ++{ ++ if (code.is_tree_code ()) ++ return associative_tree_code (tree_code (code)); ++ auto cfn = combined_fn (code); ++ return associative_binary_fn_p (associated_internal_fn (cfn, type)); ++} ++ ++/* Return true if the target directly supports operation CODE on type TYPE. ++ QUERY_TYPE acts as for optab_for_tree_code. */ ++ ++bool ++directly_supported_p (code_helper code, tree type, optab_subtype query_type) ++{ ++ if (code.is_tree_code ()) ++ { ++ direct_optab optab = optab_for_tree_code (tree_code (code), type, ++ query_type); ++ return (optab != unknown_optab ++ && optab_handler (optab, TYPE_MODE (type)) != CODE_FOR_nothing); ++ } ++ gcc_assert (query_type == optab_default ++ || (query_type == optab_vector && VECTOR_TYPE_P (type)) ++ || (query_type == optab_scalar && !VECTOR_TYPE_P (type))); ++ internal_fn ifn = associated_internal_fn (combined_fn (code), type); ++ return (direct_internal_fn_p (ifn) ++ && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED)); ++} ++ ++/* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn ++ for a code_helper CODE operating on type TYPE. */ ++ ++internal_fn ++get_conditional_internal_fn (code_helper code, tree type) ++{ ++ if (code.is_tree_code ()) ++ return get_conditional_internal_fn (tree_code (code)); ++ auto cfn = combined_fn (code); ++ return get_conditional_internal_fn (associated_internal_fn (cfn, type)); ++} +diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc +index 21843d7870b3..3069ff5cb6e1 100644 +--- a/gcc/gimple-match-head.cc ++++ b/gcc/gimple-match-head.cc +@@ -50,1089 +50,8 @@ along with GCC; see the file COPYING3. If not see + #include "attribs.h" + #include "asan.h" + +-/* Forward declarations of the private auto-generated matchers. +- They expect valueized operands in canonical order and do not +- perform simplification of all-constant operands. */ +-static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), +- code_helper, tree, tree); +-static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), +- code_helper, tree, tree, tree); +-static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), +- code_helper, tree, tree, tree, tree); +-static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), +- code_helper, tree, tree, tree, tree, tree); +-static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), +- code_helper, tree, tree, tree, tree, tree, tree); +-static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, +- tree (*)(tree)); +-static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, +- tree (*)(tree)); +-static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, +- tree (*)(tree)); +-static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, +- tree (*)(tree)); +-static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, +- tree (*)(tree)); +- +-const unsigned int gimple_match_op::MAX_NUM_OPS; +- +-/* Return whether T is a constant that we'll dispatch to fold to +- evaluate fully constant expressions. */ +- +-static inline bool +-constant_for_folding (tree t) +-{ +- return (CONSTANT_CLASS_P (t) +- /* The following is only interesting to string builtins. */ +- || (TREE_CODE (t) == ADDR_EXPR +- && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)); +-} +- +-/* Try to convert conditional operation ORIG_OP into an IFN_COND_* +- operation. Return true on success, storing the new operation in NEW_OP. */ +- +-static bool +-convert_conditional_op (gimple_match_op *orig_op, +- gimple_match_op *new_op) +-{ +- internal_fn ifn; +- if (orig_op->code.is_tree_code ()) +- ifn = get_conditional_internal_fn ((tree_code) orig_op->code); +- else +- { +- auto cfn = combined_fn (orig_op->code); +- if (!internal_fn_p (cfn)) +- return false; +- ifn = get_conditional_internal_fn (as_internal_fn (cfn)); +- } +- if (ifn == IFN_LAST) +- return false; +- unsigned int num_ops = orig_op->num_ops; +- new_op->set_op (as_combined_fn (ifn), orig_op->type, num_ops + 2); +- new_op->ops[0] = orig_op->cond.cond; +- for (unsigned int i = 0; i < num_ops; ++i) +- new_op->ops[i + 1] = orig_op->ops[i]; +- tree else_value = orig_op->cond.else_value; +- if (!else_value) +- else_value = targetm.preferred_else_value (ifn, orig_op->type, +- num_ops, orig_op->ops); +- new_op->ops[num_ops + 1] = else_value; +- return true; +-} +- +-/* RES_OP is the result of a simplification. If it is conditional, +- try to replace it with the equivalent UNCOND form, such as an +- IFN_COND_* call or a VEC_COND_EXPR. Also try to resimplify the +- result of the replacement if appropriate, adding any new statements to +- SEQ and using VALUEIZE as the valueization function. Return true if +- this resimplification occurred and resulted in at least one change. */ +- +-static bool +-maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op, +- tree (*valueize) (tree)) +-{ +- if (!res_op->cond.cond) +- return false; +- +- if (!res_op->cond.else_value +- && res_op->code.is_tree_code ()) +- { +- /* The "else" value doesn't matter. If the "then" value is a +- gimple value, just use it unconditionally. This isn't a +- simplification in itself, since there was no operation to +- build in the first place. */ +- if (gimple_simplified_result_is_gimple_val (res_op)) +- { +- res_op->cond.cond = NULL_TREE; +- return false; +- } +- +- /* Likewise if the operation would not trap. */ +- bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type) +- && TYPE_OVERFLOW_TRAPS (res_op->type)); +- tree_code op_code = (tree_code) res_op->code; +- bool op_could_trap; +- +- /* COND_EXPR will trap if, and only if, the condition +- traps and hence we have to check this. For all other operations, we +- don't need to consider the operands. */ +- if (op_code == COND_EXPR) +- op_could_trap = generic_expr_could_trap_p (res_op->ops[0]); +- else +- op_could_trap = operation_could_trap_p ((tree_code) res_op->code, +- FLOAT_TYPE_P (res_op->type), +- honor_trapv, +- res_op->op_or_null (1)); +- +- if (!op_could_trap) +- { +- res_op->cond.cond = NULL_TREE; +- return false; +- } +- } +- +- /* If the "then" value is a gimple value and the "else" value matters, +- create a VEC_COND_EXPR between them, then see if it can be further +- simplified. */ +- gimple_match_op new_op; +- if (res_op->cond.else_value +- && VECTOR_TYPE_P (res_op->type) +- && gimple_simplified_result_is_gimple_val (res_op)) +- { +- new_op.set_op (VEC_COND_EXPR, res_op->type, +- res_op->cond.cond, res_op->ops[0], +- res_op->cond.else_value); +- *res_op = new_op; +- return gimple_resimplify3 (seq, res_op, valueize); +- } +- +- /* Otherwise try rewriting the operation as an IFN_COND_* call. +- Again, this isn't a simplification in itself, since it's what +- RES_OP already described. */ +- if (convert_conditional_op (res_op, &new_op)) +- *res_op = new_op; +- +- return false; +-} +- +-/* Helper that matches and simplifies the toplevel result from +- a gimple_simplify run (where we don't want to build +- a stmt in case it's used in in-place folding). Replaces +- RES_OP with a simplified and/or canonicalized result and +- returns whether any change was made. */ +- +-static bool +-gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op, +- tree (*valueize)(tree)) +-{ +- if (constant_for_folding (res_op->ops[0])) +- { +- tree tem = NULL_TREE; +- if (res_op->code.is_tree_code ()) +- { +- auto code = tree_code (res_op->code); +- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) +- && TREE_CODE_LENGTH (code) == 1) +- tem = const_unop (code, res_op->type, res_op->ops[0]); +- } +- else +- tem = fold_const_call (combined_fn (res_op->code), res_op->type, +- res_op->ops[0]); +- if (tem != NULL_TREE +- && CONSTANT_CLASS_P (tem)) +- { +- if (TREE_OVERFLOW_P (tem)) +- tem = drop_tree_overflow (tem); +- res_op->set_value (tem); +- maybe_resimplify_conditional_op (seq, res_op, valueize); +- return true; +- } +- } +- +- /* Limit recursion, there are cases like PR80887 and others, for +- example when value-numbering presents us with unfolded expressions +- that we are really not prepared to handle without eventual +- oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50 +- itself as available expression. */ +- static unsigned depth; +- if (depth > 10) +- { +- if (dump_file && (dump_flags & TDF_FOLDING)) +- fprintf (dump_file, "Aborting expression simplification due to " +- "deep recursion\n"); +- return false; +- } +- +- ++depth; +- gimple_match_op res_op2 (*res_op); +- if (gimple_simplify (&res_op2, seq, valueize, +- res_op->code, res_op->type, res_op->ops[0])) +- { +- --depth; +- *res_op = res_op2; +- return true; +- } +- --depth; +- +- if (maybe_resimplify_conditional_op (seq, res_op, valueize)) +- return true; +- +- return false; +-} +- +-/* Helper that matches and simplifies the toplevel result from +- a gimple_simplify run (where we don't want to build +- a stmt in case it's used in in-place folding). Replaces +- RES_OP with a simplified and/or canonicalized result and +- returns whether any change was made. */ +- +-static bool +-gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op, +- tree (*valueize)(tree)) +-{ +- if (constant_for_folding (res_op->ops[0]) +- && constant_for_folding (res_op->ops[1])) +- { +- tree tem = NULL_TREE; +- if (res_op->code.is_tree_code ()) +- { +- auto code = tree_code (res_op->code); +- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) +- && TREE_CODE_LENGTH (code) == 2) +- tem = const_binop (code, res_op->type, +- res_op->ops[0], res_op->ops[1]); +- } +- else +- tem = fold_const_call (combined_fn (res_op->code), res_op->type, +- res_op->ops[0], res_op->ops[1]); +- if (tem != NULL_TREE +- && CONSTANT_CLASS_P (tem)) +- { +- if (TREE_OVERFLOW_P (tem)) +- tem = drop_tree_overflow (tem); +- res_op->set_value (tem); +- maybe_resimplify_conditional_op (seq, res_op, valueize); +- return true; +- } +- } +- +- /* Canonicalize operand order. */ +- bool canonicalized = false; +- bool is_comparison +- = (res_op->code.is_tree_code () +- && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison); +- if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type)) +- && tree_swap_operands_p (res_op->ops[0], res_op->ops[1])) +- { +- std::swap (res_op->ops[0], res_op->ops[1]); +- if (is_comparison) +- res_op->code = swap_tree_comparison (tree_code (res_op->code)); +- canonicalized = true; +- } +- +- /* Limit recursion, see gimple_resimplify1. */ +- static unsigned depth; +- if (depth > 10) +- { +- if (dump_file && (dump_flags & TDF_FOLDING)) +- fprintf (dump_file, "Aborting expression simplification due to " +- "deep recursion\n"); +- return false; +- } +- +- ++depth; +- gimple_match_op res_op2 (*res_op); +- if (gimple_simplify (&res_op2, seq, valueize, +- res_op->code, res_op->type, +- res_op->ops[0], res_op->ops[1])) +- { +- --depth; +- *res_op = res_op2; +- return true; +- } +- --depth; +- +- if (maybe_resimplify_conditional_op (seq, res_op, valueize)) +- return true; +- +- return canonicalized; +-} +- +-/* Helper that matches and simplifies the toplevel result from +- a gimple_simplify run (where we don't want to build +- a stmt in case it's used in in-place folding). Replaces +- RES_OP with a simplified and/or canonicalized result and +- returns whether any change was made. */ +- +-static bool +-gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op, +- tree (*valueize)(tree)) +-{ +- if (constant_for_folding (res_op->ops[0]) +- && constant_for_folding (res_op->ops[1]) +- && constant_for_folding (res_op->ops[2])) +- { +- tree tem = NULL_TREE; +- if (res_op->code.is_tree_code ()) +- { +- auto code = tree_code (res_op->code); +- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) +- && TREE_CODE_LENGTH (code) == 3) +- tem = fold_ternary/*_to_constant*/ (code, res_op->type, +- res_op->ops[0], res_op->ops[1], +- res_op->ops[2]); +- } +- else +- tem = fold_const_call (combined_fn (res_op->code), res_op->type, +- res_op->ops[0], res_op->ops[1], res_op->ops[2]); +- if (tem != NULL_TREE +- && CONSTANT_CLASS_P (tem)) +- { +- if (TREE_OVERFLOW_P (tem)) +- tem = drop_tree_overflow (tem); +- res_op->set_value (tem); +- maybe_resimplify_conditional_op (seq, res_op, valueize); +- return true; +- } +- } +- +- /* Canonicalize operand order. */ +- bool canonicalized = false; +- int argno = first_commutative_argument (res_op->code, res_op->type); +- if (argno >= 0 +- && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) +- { +- std::swap (res_op->ops[argno], res_op->ops[argno + 1]); +- canonicalized = true; +- } +- +- /* Limit recursion, see gimple_resimplify1. */ +- static unsigned depth; +- if (depth > 10) +- { +- if (dump_file && (dump_flags & TDF_FOLDING)) +- fprintf (dump_file, "Aborting expression simplification due to " +- "deep recursion\n"); +- return false; +- } +- +- ++depth; +- gimple_match_op res_op2 (*res_op); +- if (gimple_simplify (&res_op2, seq, valueize, +- res_op->code, res_op->type, +- res_op->ops[0], res_op->ops[1], res_op->ops[2])) +- { +- --depth; +- *res_op = res_op2; +- return true; +- } +- --depth; +- +- if (maybe_resimplify_conditional_op (seq, res_op, valueize)) +- return true; +- +- return canonicalized; +-} +- +-/* Helper that matches and simplifies the toplevel result from +- a gimple_simplify run (where we don't want to build +- a stmt in case it's used in in-place folding). Replaces +- RES_OP with a simplified and/or canonicalized result and +- returns whether any change was made. */ +- +-static bool +-gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op, +- tree (*valueize)(tree)) +-{ +- /* No constant folding is defined for four-operand functions. */ +- +- /* Canonicalize operand order. */ +- bool canonicalized = false; +- int argno = first_commutative_argument (res_op->code, res_op->type); +- if (argno >= 0 +- && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) +- { +- std::swap (res_op->ops[argno], res_op->ops[argno + 1]); +- canonicalized = true; +- } +- +- /* Limit recursion, see gimple_resimplify1. */ +- static unsigned depth; +- if (depth > 10) +- { +- if (dump_file && (dump_flags & TDF_FOLDING)) +- fprintf (dump_file, "Aborting expression simplification due to " +- "deep recursion\n"); +- return false; +- } +- +- ++depth; +- gimple_match_op res_op2 (*res_op); +- if (gimple_simplify (&res_op2, seq, valueize, +- res_op->code, res_op->type, +- res_op->ops[0], res_op->ops[1], res_op->ops[2], +- res_op->ops[3])) +- { +- --depth; +- *res_op = res_op2; +- return true; +- } +- --depth; +- +- if (maybe_resimplify_conditional_op (seq, res_op, valueize)) +- return true; +- +- return canonicalized; +-} +- +-/* Helper that matches and simplifies the toplevel result from +- a gimple_simplify run (where we don't want to build +- a stmt in case it's used in in-place folding). Replaces +- RES_OP with a simplified and/or canonicalized result and +- returns whether any change was made. */ +- +-static bool +-gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op, +- tree (*valueize)(tree)) +-{ +- /* No constant folding is defined for five-operand functions. */ +- +- /* Canonicalize operand order. */ +- bool canonicalized = false; +- int argno = first_commutative_argument (res_op->code, res_op->type); +- if (argno >= 0 +- && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1])) +- { +- std::swap (res_op->ops[argno], res_op->ops[argno + 1]); +- canonicalized = true; +- } +- +- gimple_match_op res_op2 (*res_op); +- if (gimple_simplify (&res_op2, seq, valueize, +- res_op->code, res_op->type, +- res_op->ops[0], res_op->ops[1], res_op->ops[2], +- res_op->ops[3], res_op->ops[4])) +- { +- *res_op = res_op2; +- return true; +- } +- +- if (maybe_resimplify_conditional_op (seq, res_op, valueize)) +- return true; +- +- return canonicalized; +-} +- +-/* Match and simplify the toplevel valueized operation THIS. +- Replaces THIS with a simplified and/or canonicalized result and +- returns whether any change was made. */ +- +-bool +-gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree)) +-{ +- switch (num_ops) +- { +- case 1: +- return gimple_resimplify1 (seq, this, valueize); +- case 2: +- return gimple_resimplify2 (seq, this, valueize); +- case 3: +- return gimple_resimplify3 (seq, this, valueize); +- case 4: +- return gimple_resimplify4 (seq, this, valueize); +- case 5: +- return gimple_resimplify5 (seq, this, valueize); +- default: +- gcc_unreachable (); +- } +-} +- +-/* If in GIMPLE the operation described by RES_OP should be single-rhs, +- build a GENERIC tree for that expression and update RES_OP accordingly. */ +- +-void +-maybe_build_generic_op (gimple_match_op *res_op) +-{ +- tree_code code = (tree_code) res_op->code; +- tree val; +- switch (code) +- { +- case REALPART_EXPR: +- case IMAGPART_EXPR: +- case VIEW_CONVERT_EXPR: +- val = build1 (code, res_op->type, res_op->ops[0]); +- res_op->set_value (val); +- break; +- case BIT_FIELD_REF: +- val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1], +- res_op->ops[2]); +- REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse; +- res_op->set_value (val); +- break; +- default:; +- } +-} +- +-tree (*mprts_hook) (gimple_match_op *); +- +-/* Try to build RES_OP, which is known to be a call to FN. Return null +- if the target doesn't support the function. */ +- +-static gcall * +-build_call_internal (internal_fn fn, gimple_match_op *res_op) +-{ +- if (direct_internal_fn_p (fn)) +- { +- tree_pair types = direct_internal_fn_types (fn, res_op->type, +- res_op->ops); +- if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH)) +- return NULL; +- } +- return gimple_build_call_internal (fn, res_op->num_ops, +- res_op->op_or_null (0), +- res_op->op_or_null (1), +- res_op->op_or_null (2), +- res_op->op_or_null (3), +- res_op->op_or_null (4)); +-} +- +-/* Push the exploded expression described by RES_OP as a statement to +- SEQ if necessary and return a gimple value denoting the value of the +- expression. If RES is not NULL then the result will be always RES +- and even gimple values are pushed to SEQ. */ +- +-tree +-maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res) +-{ +- tree *ops = res_op->ops; +- unsigned num_ops = res_op->num_ops; +- +- /* The caller should have converted conditional operations into an UNCOND +- form and resimplified as appropriate. The conditional form only +- survives this far if that conversion failed. */ +- if (res_op->cond.cond) +- return NULL_TREE; +- +- if (res_op->code.is_tree_code ()) +- { +- if (!res +- && gimple_simplified_result_is_gimple_val (res_op)) +- return ops[0]; +- if (mprts_hook) +- { +- tree tem = mprts_hook (res_op); +- if (tem) +- return tem; +- } +- } +- +- if (!seq) +- return NULL_TREE; +- +- /* Play safe and do not allow abnormals to be mentioned in +- newly created statements. */ +- for (unsigned int i = 0; i < num_ops; ++i) +- if (TREE_CODE (ops[i]) == SSA_NAME +- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i])) +- return NULL_TREE; +- +- if (num_ops > 0 && COMPARISON_CLASS_P (ops[0])) +- for (unsigned int i = 0; i < 2; ++i) +- if (TREE_CODE (TREE_OPERAND (ops[0], i)) == SSA_NAME +- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0], i))) +- return NULL_TREE; +- +- if (res_op->code.is_tree_code ()) +- { +- auto code = tree_code (res_op->code); +- if (!res) +- { +- if (gimple_in_ssa_p (cfun)) +- res = make_ssa_name (res_op->type); +- else +- res = create_tmp_reg (res_op->type); +- } +- maybe_build_generic_op (res_op); +- gimple *new_stmt = gimple_build_assign (res, code, +- res_op->op_or_null (0), +- res_op->op_or_null (1), +- res_op->op_or_null (2)); +- gimple_seq_add_stmt_without_update (seq, new_stmt); +- return res; +- } +- else +- { +- gcc_assert (num_ops != 0); +- auto fn = combined_fn (res_op->code); +- gcall *new_stmt = NULL; +- if (internal_fn_p (fn)) +- { +- /* Generate the given function if we can. */ +- internal_fn ifn = as_internal_fn (fn); +- new_stmt = build_call_internal (ifn, res_op); +- if (!new_stmt) +- return NULL_TREE; +- } +- else +- { +- /* Find the function we want to call. */ +- tree decl = builtin_decl_implicit (as_builtin_fn (fn)); +- if (!decl) +- return NULL; +- +- /* We can't and should not emit calls to non-const functions. */ +- if (!(flags_from_decl_or_type (decl) & ECF_CONST)) +- return NULL; +- +- new_stmt = gimple_build_call (decl, num_ops, +- res_op->op_or_null (0), +- res_op->op_or_null (1), +- res_op->op_or_null (2), +- res_op->op_or_null (3), +- res_op->op_or_null (4)); +- } +- if (!res) +- { +- if (gimple_in_ssa_p (cfun)) +- res = make_ssa_name (res_op->type); +- else +- res = create_tmp_reg (res_op->type); +- } +- gimple_call_set_lhs (new_stmt, res); +- gimple_seq_add_stmt_without_update (seq, new_stmt); +- return res; +- } +-} +- +- +-/* Public API overloads follow for operation being tree_code or +- built_in_function and for one to three operands or arguments. +- They return NULL_TREE if nothing could be simplified or +- the resulting simplified value with parts pushed to SEQ. +- If SEQ is NULL then if the simplification needs to create +- new stmts it will fail. If VALUEIZE is non-NULL then all +- SSA names will be valueized using that hook prior to +- applying simplifications. */ +- +-/* Unary ops. */ +- +-tree +-gimple_simplify (enum tree_code code, tree type, +- tree op0, +- gimple_seq *seq, tree (*valueize)(tree)) +-{ +- if (constant_for_folding (op0)) +- { +- tree res = const_unop (code, type, op0); +- if (res != NULL_TREE +- && CONSTANT_CLASS_P (res)) +- return res; +- } +- +- gimple_match_op res_op; +- if (!gimple_simplify (&res_op, seq, valueize, code, type, op0)) +- return NULL_TREE; +- return maybe_push_res_to_seq (&res_op, seq); +-} +- +-/* Binary ops. */ +- +-tree +-gimple_simplify (enum tree_code code, tree type, +- tree op0, tree op1, +- gimple_seq *seq, tree (*valueize)(tree)) +-{ +- if (constant_for_folding (op0) && constant_for_folding (op1)) +- { +- tree res = const_binop (code, type, op0, op1); +- if (res != NULL_TREE +- && CONSTANT_CLASS_P (res)) +- return res; +- } +- +- /* Canonicalize operand order both for matching and fallback stmt +- generation. */ +- if ((commutative_tree_code (code) +- || TREE_CODE_CLASS (code) == tcc_comparison) +- && tree_swap_operands_p (op0, op1)) +- { +- std::swap (op0, op1); +- if (TREE_CODE_CLASS (code) == tcc_comparison) +- code = swap_tree_comparison (code); +- } +- +- gimple_match_op res_op; +- if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1)) +- return NULL_TREE; +- return maybe_push_res_to_seq (&res_op, seq); +-} +- +-/* Ternary ops. */ +- +-tree +-gimple_simplify (enum tree_code code, tree type, +- tree op0, tree op1, tree op2, +- gimple_seq *seq, tree (*valueize)(tree)) +-{ +- if (constant_for_folding (op0) && constant_for_folding (op1) +- && constant_for_folding (op2)) +- { +- tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2); +- if (res != NULL_TREE +- && CONSTANT_CLASS_P (res)) +- return res; +- } +- +- /* Canonicalize operand order both for matching and fallback stmt +- generation. */ +- if (commutative_ternary_tree_code (code) +- && tree_swap_operands_p (op0, op1)) +- std::swap (op0, op1); +- +- gimple_match_op res_op; +- if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2)) +- return NULL_TREE; +- return maybe_push_res_to_seq (&res_op, seq); +-} +- +-/* Builtin or internal function with one argument. */ +- +-tree +-gimple_simplify (combined_fn fn, tree type, +- tree arg0, +- gimple_seq *seq, tree (*valueize)(tree)) +-{ +- if (constant_for_folding (arg0)) +- { +- tree res = fold_const_call (fn, type, arg0); +- if (res && CONSTANT_CLASS_P (res)) +- return res; +- } +- +- gimple_match_op res_op; +- if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0)) +- return NULL_TREE; +- return maybe_push_res_to_seq (&res_op, seq); +-} +- +-/* Builtin or internal function with two arguments. */ +- +-tree +-gimple_simplify (combined_fn fn, tree type, +- tree arg0, tree arg1, +- gimple_seq *seq, tree (*valueize)(tree)) +-{ +- if (constant_for_folding (arg0) +- && constant_for_folding (arg1)) +- { +- tree res = fold_const_call (fn, type, arg0, arg1); +- if (res && CONSTANT_CLASS_P (res)) +- return res; +- } +- +- gimple_match_op res_op; +- if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1)) +- return NULL_TREE; +- return maybe_push_res_to_seq (&res_op, seq); +-} +- +-/* Builtin or internal function with three arguments. */ +- +-tree +-gimple_simplify (combined_fn fn, tree type, +- tree arg0, tree arg1, tree arg2, +- gimple_seq *seq, tree (*valueize)(tree)) +-{ +- if (constant_for_folding (arg0) +- && constant_for_folding (arg1) +- && constant_for_folding (arg2)) +- { +- tree res = fold_const_call (fn, type, arg0, arg1, arg2); +- if (res && CONSTANT_CLASS_P (res)) +- return res; +- } +- +- gimple_match_op res_op; +- if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2)) +- return NULL_TREE; +- return maybe_push_res_to_seq (&res_op, seq); +-} +- +-/* Helper for gimple_simplify valueizing OP using VALUEIZE and setting +- VALUEIZED to true if valueization changed OP. */ +- +-static inline tree +-do_valueize (tree op, tree (*valueize)(tree), bool &valueized) +-{ +- if (valueize && TREE_CODE (op) == SSA_NAME) +- { +- tree tem = valueize (op); +- if (tem && tem != op) +- { +- op = tem; +- valueized = true; +- } +- } +- return op; +-} +- +-/* If RES_OP is a call to a conditional internal function, try simplifying +- the associated unconditional operation and using the result to build +- a new conditional operation. For example, if RES_OP is: +- +- IFN_COND_ADD (COND, A, B, ELSE) +- +- try simplifying (plus A B) and using the result to build a replacement +- for the whole IFN_COND_ADD. +- +- Return true if this approach led to a simplification, otherwise leave +- RES_OP unchanged (and so suitable for other simplifications). When +- returning true, add any new statements to SEQ and use VALUEIZE as the +- valueization function. +- +- RES_OP is known to be a call to IFN. */ +- +-static bool +-try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op, +- gimple_seq *seq, tree (*valueize) (tree)) +-{ +- code_helper op; +- tree_code code = conditional_internal_fn_code (ifn); +- if (code != ERROR_MARK) +- op = code; +- else +- { +- ifn = get_unconditional_internal_fn (ifn); +- if (ifn == IFN_LAST) +- return false; +- op = as_combined_fn (ifn); +- } +- +- unsigned int num_ops = res_op->num_ops; +- gimple_match_op cond_op (gimple_match_cond (res_op->ops[0], +- res_op->ops[num_ops - 1]), +- op, res_op->type, num_ops - 2); +- +- memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops); +- switch (num_ops - 2) +- { +- case 1: +- if (!gimple_resimplify1 (seq, &cond_op, valueize)) +- return false; +- break; +- case 2: +- if (!gimple_resimplify2 (seq, &cond_op, valueize)) +- return false; +- break; +- case 3: +- if (!gimple_resimplify3 (seq, &cond_op, valueize)) +- return false; +- break; +- default: +- gcc_unreachable (); +- } +- *res_op = cond_op; +- maybe_resimplify_conditional_op (seq, res_op, valueize); +- return true; +-} +- +-/* Common subroutine of gimple_extract_op and gimple_simplify. Try to +- describe STMT in RES_OP, returning true on success. Before recording +- an operand, call: +- +- - VALUEIZE_CONDITION for a COND_EXPR condition +- - VALUEIZE_OP for every other top-level operand +- +- Both routines take a tree argument and returns a tree. */ +- +-template +-inline bool +-gimple_extract (gimple *stmt, gimple_match_op *res_op, +- ValueizeOp valueize_op, +- ValueizeCondition valueize_condition) +-{ +- switch (gimple_code (stmt)) +- { +- case GIMPLE_ASSIGN: +- { +- enum tree_code code = gimple_assign_rhs_code (stmt); +- tree type = TREE_TYPE (gimple_assign_lhs (stmt)); +- switch (gimple_assign_rhs_class (stmt)) +- { +- case GIMPLE_SINGLE_RHS: +- if (code == REALPART_EXPR +- || code == IMAGPART_EXPR +- || code == VIEW_CONVERT_EXPR) +- { +- tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); +- res_op->set_op (code, type, valueize_op (op0)); +- return true; +- } +- else if (code == BIT_FIELD_REF) +- { +- tree rhs1 = gimple_assign_rhs1 (stmt); +- tree op0 = valueize_op (TREE_OPERAND (rhs1, 0)); +- res_op->set_op (code, type, op0, +- TREE_OPERAND (rhs1, 1), +- TREE_OPERAND (rhs1, 2), +- REF_REVERSE_STORAGE_ORDER (rhs1)); +- return true; +- } +- else if (code == SSA_NAME) +- { +- tree op0 = gimple_assign_rhs1 (stmt); +- res_op->set_op (TREE_CODE (op0), type, valueize_op (op0)); +- return true; +- } +- break; +- case GIMPLE_UNARY_RHS: +- { +- tree rhs1 = gimple_assign_rhs1 (stmt); +- res_op->set_op (code, type, valueize_op (rhs1)); +- return true; +- } +- case GIMPLE_BINARY_RHS: +- { +- tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt)); +- tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt)); +- res_op->set_op (code, type, rhs1, rhs2); +- return true; +- } +- case GIMPLE_TERNARY_RHS: +- { +- tree rhs1 = gimple_assign_rhs1 (stmt); +- if (code == COND_EXPR && COMPARISON_CLASS_P (rhs1)) +- rhs1 = valueize_condition (rhs1); +- else +- rhs1 = valueize_op (rhs1); +- tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt)); +- tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt)); +- res_op->set_op (code, type, rhs1, rhs2, rhs3); +- return true; +- } +- default: +- gcc_unreachable (); +- } +- break; +- } +- +- case GIMPLE_CALL: +- /* ??? This way we can't simplify calls with side-effects. */ +- if (gimple_call_lhs (stmt) != NULL_TREE +- && gimple_call_num_args (stmt) >= 1 +- && gimple_call_num_args (stmt) <= 5) +- { +- combined_fn cfn; +- if (gimple_call_internal_p (stmt)) +- cfn = as_combined_fn (gimple_call_internal_fn (stmt)); +- else +- { +- tree fn = gimple_call_fn (stmt); +- if (!fn) +- return false; +- +- fn = valueize_op (fn); +- if (TREE_CODE (fn) != ADDR_EXPR +- || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL) +- return false; +- +- tree decl = TREE_OPERAND (fn, 0); +- if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL +- || !gimple_builtin_call_types_compatible_p (stmt, decl)) +- return false; +- +- cfn = as_combined_fn (DECL_FUNCTION_CODE (decl)); +- } +- +- unsigned int num_args = gimple_call_num_args (stmt); +- res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args); +- for (unsigned i = 0; i < num_args; ++i) +- res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i)); +- return true; +- } +- break; +- +- case GIMPLE_COND: +- { +- tree lhs = valueize_op (gimple_cond_lhs (stmt)); +- tree rhs = valueize_op (gimple_cond_rhs (stmt)); +- res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs); +- return true; +- } +- +- default: +- break; +- } +- +- return false; +-} +- +-/* Try to describe STMT in RES_OP, returning true on success. +- For GIMPLE_CONDs, describe the condition that is being tested. +- For GIMPLE_ASSIGNs, describe the rhs of the assignment. +- For GIMPLE_CALLs, describe the call. */ +- +-bool +-gimple_extract_op (gimple *stmt, gimple_match_op *res_op) +-{ +- auto nop = [](tree op) { return op; }; +- return gimple_extract (stmt, res_op, nop, nop); +-} +- +-/* The main STMT based simplification entry. It is used by the fold_stmt +- and the fold_stmt_to_constant APIs. */ +- +-bool +-gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq, +- tree (*valueize)(tree), tree (*top_valueize)(tree)) +-{ +- bool valueized = false; +- auto valueize_op = [&](tree op) +- { +- return do_valueize (op, top_valueize, valueized); +- }; +- auto valueize_condition = [&](tree op) -> tree +- { +- bool cond_valueized = false; +- tree lhs = do_valueize (TREE_OPERAND (op, 0), top_valueize, +- cond_valueized); +- tree rhs = do_valueize (TREE_OPERAND (op, 1), top_valueize, +- cond_valueized); +- gimple_match_op res_op2 (res_op->cond, TREE_CODE (op), +- TREE_TYPE (op), lhs, rhs); +- if ((gimple_resimplify2 (seq, &res_op2, valueize) +- || cond_valueized) +- && res_op2.code.is_tree_code ()) +- { +- auto code = tree_code (res_op2.code); +- if (TREE_CODE_CLASS (code) == tcc_comparison) +- { +- valueized = true; +- return build2 (code, TREE_TYPE (op), +- res_op2.ops[0], res_op2.ops[1]); +- } +- else if (code == SSA_NAME +- || code == INTEGER_CST +- || code == VECTOR_CST) +- { +- valueized = true; +- return res_op2.ops[0]; +- } +- } +- return valueize_op (op); +- }; +- +- if (!gimple_extract (stmt, res_op, valueize_op, valueize_condition)) +- return false; +- +- if (res_op->code.is_internal_fn ()) +- { +- internal_fn ifn = internal_fn (res_op->code); +- if (try_conditional_simplification (ifn, res_op, seq, valueize)) +- return true; +- } +- +- if (!res_op->reverse +- && res_op->num_ops +- && res_op->resimplify (seq, valueize)) +- return true; +- +- return valueized; +-} +- +-/* Helper for the autogenerated code, valueize OP. */ +- +-inline tree +-do_valueize (tree (*valueize)(tree), tree op) +-{ +- if (valueize && TREE_CODE (op) == SSA_NAME) +- { +- tree tem = valueize (op); +- if (tem) +- return tem; +- } +- return op; +-} ++tree do_valueize (tree, tree (*)(tree), bool &); ++tree do_valueize (tree (*)(tree), tree); + + /* Helper for the autogenerated code, get at the definition of NAME when + VALUEIZE allows that. */ +@@ -1307,110 +226,3 @@ optimize_successive_divisions_p (tree divisor, tree inner_div) + } + return true; + } +- +-/* Return a canonical form for CODE when operating on TYPE. The idea +- is to remove redundant ways of representing the same operation so +- that code_helpers can be hashed and compared for equality. +- +- The only current canonicalization is to replace built-in functions +- with internal functions, in cases where internal-fn.def defines +- such an internal function. +- +- Note that the new code_helper cannot necessarily be used in place of +- the original code_helper. For example, the new code_helper might be +- an internal function that the target does not support. */ +- +-code_helper +-canonicalize_code (code_helper code, tree type) +-{ +- if (code.is_fn_code ()) +- return associated_internal_fn (combined_fn (code), type); +- return code; +-} +- +-/* Return true if CODE is a binary operation and if CODE is commutative when +- operating on type TYPE. */ +- +-bool +-commutative_binary_op_p (code_helper code, tree type) +-{ +- if (code.is_tree_code ()) +- return commutative_tree_code (tree_code (code)); +- auto cfn = combined_fn (code); +- return commutative_binary_fn_p (associated_internal_fn (cfn, type)); +-} +- +-/* Return true if CODE represents a ternary operation and if the first two +- operands are commutative when CODE is operating on TYPE. */ +- +-bool +-commutative_ternary_op_p (code_helper code, tree type) +-{ +- if (code.is_tree_code ()) +- return commutative_ternary_tree_code (tree_code (code)); +- auto cfn = combined_fn (code); +- return commutative_ternary_fn_p (associated_internal_fn (cfn, type)); +-} +- +-/* If CODE is commutative in two consecutive operands, return the +- index of the first, otherwise return -1. */ +- +-int +-first_commutative_argument (code_helper code, tree type) +-{ +- if (code.is_tree_code ()) +- { +- auto tcode = tree_code (code); +- if (commutative_tree_code (tcode) +- || commutative_ternary_tree_code (tcode)) +- return 0; +- return -1; +- } +- auto cfn = combined_fn (code); +- return first_commutative_argument (associated_internal_fn (cfn, type)); +-} +- +-/* Return true if CODE is a binary operation that is associative when +- operating on type TYPE. */ +- +-bool +-associative_binary_op_p (code_helper code, tree type) +-{ +- if (code.is_tree_code ()) +- return associative_tree_code (tree_code (code)); +- auto cfn = combined_fn (code); +- return associative_binary_fn_p (associated_internal_fn (cfn, type)); +-} +- +-/* Return true if the target directly supports operation CODE on type TYPE. +- QUERY_TYPE acts as for optab_for_tree_code. */ +- +-bool +-directly_supported_p (code_helper code, tree type, optab_subtype query_type) +-{ +- if (code.is_tree_code ()) +- { +- direct_optab optab = optab_for_tree_code (tree_code (code), type, +- query_type); +- return (optab != unknown_optab +- && optab_handler (optab, TYPE_MODE (type)) != CODE_FOR_nothing); +- } +- gcc_assert (query_type == optab_default +- || (query_type == optab_vector && VECTOR_TYPE_P (type)) +- || (query_type == optab_scalar && !VECTOR_TYPE_P (type))); +- internal_fn ifn = associated_internal_fn (combined_fn (code), type); +- return (direct_internal_fn_p (ifn) +- && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED)); +-} +- +-/* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn +- for a code_helper CODE operating on type TYPE. */ +- +-internal_fn +-get_conditional_internal_fn (code_helper code, tree type) +-{ +- if (code.is_tree_code ()) +- return get_conditional_internal_fn (tree_code (code)); +- auto cfn = combined_fn (code); +- return get_conditional_internal_fn (associated_internal_fn (cfn, type)); +-} +-- +2.44.0 + +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21 + +From daac5d2f67656dcf8cc2bbff1c6eaa34f3fb55b9 Mon Sep 17 00:00:00 2001 +From: Tamar Christina +Date: Fri, 5 May 2023 13:38:50 +0100 +Subject: [PATCH 05/15] match.pd: automatically partition *-match.cc files. + +Following on from Richi's RFC[1] this is another attempt to split up match.pd +into multiple gimple-match and generic-match files. This version is fully +automated and requires no human intervention. + +First things first, some perf numbers. The following shows the effect of the +patch on my desktop doing parallel compilation of gimple-match: + ++--------+------------------+--------+------------------+ +| splits | rel. improvement | splits | rel. improvement | ++--------+------------------+--------+------------------+ +| 1 | 0.00% | 33 | 91.03% | +| 2 | 71.77% | 34 | 84.02% | +| 3 | 100.71% | 35 | 83.42% | +| 4 | 143.08% | 36 | 78.80% | +| 5 | 176.18% | 37 | 74.06% | +| 6 | 174.40% | 38 | 55.76% | +| 7 | 176.62% | 39 | 66.90% | +| 8 | 168.35% | 40 | 18.25% | +| 9 | 189.80% | 41 | 16.55% | +| 10 | 171.77% | 42 | 47.02% | +| 11 | 152.82% | 43 | 15.29% | +| 12 | 112.20% | 44 | 21.63% | +| 13 | 158.57% | 45 | 41.53% | +| 14 | 158.57% | 46 | 21.98% | +| 15 | 152.07% | 47 | -42.74% | +| 16 | 151.70% | 48 | -32.62% | +| 17 | 131.52% | 49 | 11.81% | +| 18 | 133.11% | 50 | 34.07% | +| 19 | 137.33% | 51 | 2.71% | +| 20 | 103.83% | 52 | -22.23% | +| 21 | 132.47% | 53 | 32.30% | +| 22 | 116.52% | 54 | 21.45% | +| 23 | 112.73% | 55 | 40.02% | +| 24 | 111.94% | 56 | 42.83% | +| 25 | 112.73% | 57 | -9.98% | +| 26 | 104.07% | 58 | 18.01% | +| 27 | 113.27% | 59 | -4.91% | +| 28 | 96.77% | 60 | 22.94% | +| 29 | 93.42% | 61 | -3.73% | +| 30 | 87.67% | 62 | -27.43% | +| 31 | 89.54% | 63 | -1.05% | +| 32 | 84.42% | 64 | -5.44% | ++--------+------------------+--------+------------------+ + +As can be seen there seems to be a point of diminishing returns in doing splits. +This comes from the fact that these match files consume a sizeable amount of +headers. At a certain point the parsing overhead of the headers dominate and +you start losing in gains. + +As such from this I've made the default 10 splits per file to allow for some +room for growth in the future without needing changes to the split amount. +Since 5-10 show roughly the same gains it means we can afford to double the +file sizes before we need to up the split amount. This can be controlled +by the configure parameter --with-matchpd-partitions=. + +At 10 splits the sizes of the files are: + + 1.2M gimple-match-1.cc + 490K gimple-match-2.cc + 459K gimple-match-3.cc + 462K gimple-match-4.cc + 466K gimple-match-5.cc + 690K gimple-match-6.cc + 517K gimple-match-7.cc + 693K gimple-match-8.cc +1011K gimple-match-9.cc + 490K gimple-match-10.cc + 210K gimple-match-auto.h + +The reason gimple-match-1.cc is so large is because it got allocated a very +large function: gimple_simplify_NE_EXPR. + +Because of these sporadically large functions the allocation to a split happens +based on the amount of data already written to a split instead of just a simple +round robin allocation (though the patch supports that too.). This means that +once gimple_simplify_NE_EXPR is allocated to gimple-match-1.cc nothing uses it +again until the rest of the files catch up. + +To support this split a new header file *-match-auto.h is generated to allow +the individual files to compile separately. + +Lastly for the auto generated files I use pragmas to silence the unused +predicate warnings instead of the previous Makefile way because I couldn't find +a way to set them without knowing the number of split files beforehand. + +Finally with this change, bootstrap time has dropped 8 minutes on AArch64. + +[1] https://gcc.gnu.org/legacy-ml/gcc-patches/2018-04/msg01125.html + +gcc/ChangeLog: + + PR bootstrap/84402 + * genmatch.cc (emit_func, SIZED_BASED_CHUNKS, get_out_file): New. + (decision_tree::gen): Accept list of files instead of single and update + to write function definition to header and main file. + (write_predicate): Likewise. + (write_header): Emit pragmas and new includes. + (main): Create file buffers and cleanup. + (showUsage, write_header_includes): New. + +(cherry picked from commit 703417a030b3d80f55ba1402adc3f1692d3631e5) +--- + gcc/genmatch.cc | 226 ++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 190 insertions(+), 36 deletions(-) + +diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc +index 665d7e2106ff..f80e4b972288 100644 +--- a/gcc/genmatch.cc ++++ b/gcc/genmatch.cc +@@ -183,6 +183,33 @@ fprintf_indent (FILE *f, unsigned int indent, const char *format, ...) + va_end (ap); + } + ++/* Like fprintf, but print to two files, one header one C implementation. */ ++FILE *header_file = NULL; ++ ++static void ++#if GCC_VERSION >= 4001 ++__attribute__((format (printf, 4, 5))) ++#endif ++emit_func (FILE *f, bool open, bool close, const char *format, ...) ++{ ++ va_list ap1, ap2; ++ if (header_file != NULL) ++ { ++ if (open) ++ fprintf (header_file, "extern "); ++ va_start (ap2, format); ++ vfprintf (header_file, format, ap2); ++ va_end (ap2); ++ if (close) ++ fprintf (header_file, ";\n"); ++ } ++ ++ va_start (ap1, format); ++ vfprintf (f, format, ap1); ++ va_end (ap1); ++ fputc ('\n', f); ++} ++ + static void + output_line_directive (FILE *f, location_t location, + bool dumpfile = false, bool fnargs = false) +@@ -217,6 +244,37 @@ output_line_directive (FILE *f, location_t location, + fprintf (f, "/* #line %d \"%s\" */\n", loc.line, loc.file); + } + ++/* Find the file to write into next. We try to evenly distribute the contents ++ over the different files. */ ++ ++#define SIZED_BASED_CHUNKS 1 ++ ++int current_file = 0; ++FILE *get_out_file (vec &parts) ++{ ++#ifdef SIZED_BASED_CHUNKS ++ if (parts.length () == 1) ++ return parts[0]; ++ ++ FILE *f = NULL; ++ long min = 0; ++ /* We've started writing all the files at pos 0, so ftell is equivalent ++ to the size and should be much faster. */ ++ for (unsigned i = 0; i < parts.length (); i++) ++ { ++ long res = ftell (parts[i]); ++ if (!f || res < min) ++ { ++ min = res; ++ f = parts[i]; ++ } ++ } ++ return f; ++#else ++ return parts[current_file++ % parts.length ()]; ++#endif ++} ++ + + /* Pull in tree codes and builtin function codes from their + definition files. */ +@@ -1732,7 +1790,7 @@ public: + dt_node *root; + + void insert (class simplify *, unsigned); +- void gen (FILE *f, bool gimple); ++ void gen (vec &f, bool gimple); + void print (FILE *f = stderr); + + decision_tree () { root = new dt_node (dt_node::DT_NODE, NULL); } +@@ -3832,7 +3890,7 @@ sinfo_hashmap_traits::equal_keys (const key_type &v, + tree. */ + + void +-decision_tree::gen (FILE *f, bool gimple) ++decision_tree::gen (vec &files, bool gimple) + { + sinfo_map_t si; + +@@ -3861,11 +3919,14 @@ decision_tree::gen (FILE *f, bool gimple) + output_line_directive (stderr, s->s->s->result->location); + } + ++ /* Cycle the file buffers. */ ++ FILE *f = get_out_file (files); ++ + /* Generate a split out function with the leaf transform code. */ + s->fname = xasprintf ("%s_simplify_%u", gimple ? "gimple" : "generic", + fcnt++); + if (gimple) +- fprintf (f, "\nstatic bool\n" ++ emit_func (f, true, false, "\nbool\n" + "%s (gimple_match_op *res_op, gimple_seq *seq,\n" + " tree (*valueize)(tree) ATTRIBUTE_UNUSED,\n" + " const tree ARG_UNUSED (type), tree *ARG_UNUSED " +@@ -3873,27 +3934,28 @@ decision_tree::gen (FILE *f, bool gimple) + s->fname); + else + { +- fprintf (f, "\nstatic tree\n" ++ emit_func (f, true, false, "\ntree\n" + "%s (location_t ARG_UNUSED (loc), const tree ARG_UNUSED (type),\n", + (*iter).second->fname); + for (unsigned i = 0; + i < as_a (s->s->s->match)->ops.length (); ++i) +- fprintf (f, " tree ARG_UNUSED (_p%d),", i); +- fprintf (f, " tree *captures\n"); ++ emit_func (f, false, false, " tree ARG_UNUSED (_p%d),", i); ++ emit_func (f, false, false, " tree *captures\n"); + } + for (unsigned i = 0; i < s->s->s->for_subst_vec.length (); ++i) + { + if (! s->s->s->for_subst_vec[i].first->used) + continue; + if (is_a (s->s->s->for_subst_vec[i].second)) +- fprintf (f, ", const enum tree_code ARG_UNUSED (%s)", ++ emit_func (f, false, false, ", const enum tree_code ARG_UNUSED (%s)", + s->s->s->for_subst_vec[i].first->id); + else if (is_a (s->s->s->for_subst_vec[i].second)) +- fprintf (f, ", const combined_fn ARG_UNUSED (%s)", ++ emit_func (f, false, false, ", const combined_fn ARG_UNUSED (%s)", + s->s->s->for_subst_vec[i].first->id); + } + +- fprintf (f, ")\n{\n"); ++ emit_func (f, false, true, ")"); ++ fprintf (f, "{\n"); + fprintf_indent (f, 2, "const bool debug_dump = " + "dump_file && (dump_flags & TDF_FOLDING);\n"); + s->s->gen_1 (f, 2, gimple, s->s->s->result); +@@ -3923,8 +3985,12 @@ decision_tree::gen (FILE *f, bool gimple) + && e->operation->kind != id_base::CODE)) + continue; + ++ ++ /* Cycle the file buffers. */ ++ FILE *f = get_out_file (files); ++ + if (gimple) +- fprintf (f, "\nstatic bool\n" ++ emit_func (f, true, false,"\nbool\n" + "gimple_simplify_%s (gimple_match_op *res_op," + " gimple_seq *seq,\n" + " tree (*valueize)(tree) " +@@ -3933,13 +3999,13 @@ decision_tree::gen (FILE *f, bool gimple) + "ARG_UNUSED (type)\n", + e->operation->id); + else +- fprintf (f, "\nstatic tree\n" ++ emit_func (f, true, false, "\ntree\n" + "generic_simplify_%s (location_t ARG_UNUSED (loc), enum " + "tree_code ARG_UNUSED (code), const tree ARG_UNUSED (type)", + e->operation->id); + for (unsigned i = 0; i < n; ++i) +- fprintf (f, ", tree _p%d", i); +- fprintf (f, ")\n"); ++ emit_func (f, false, false,", tree _p%d", i); ++ emit_func (f, false, true, ")"); + fprintf (f, "{\n"); + fprintf_indent (f, 2, "const bool debug_dump = " + "dump_file && (dump_flags & TDF_FOLDING);\n"); +@@ -3956,18 +4022,22 @@ decision_tree::gen (FILE *f, bool gimple) + with compiler warnings, by generating a simple stub. */ + if (! has_kids_p) + { ++ ++ /* Cycle the file buffers. */ ++ FILE *f = get_out_file (files); ++ + if (gimple) +- fprintf (f, "\nbool\n" ++ emit_func (f, true, false, "\nbool\n" + "gimple_simplify (gimple_match_op*, gimple_seq*,\n" + " tree (*)(tree), code_helper,\n" + " const tree"); + else +- fprintf (f, "\ntree\n" ++ emit_func (f, true, false,"\ntree\n" + "generic_simplify (location_t, enum tree_code,\n" + " const tree"); + for (unsigned i = 0; i < n; ++i) +- fprintf (f, ", tree"); +- fprintf (f, ")\n"); ++ emit_func (f, false, false, ", tree"); ++ emit_func (f, false, true, ")"); + fprintf (f, "{\n"); + if (gimple) + fprintf (f, " return false;\n"); +@@ -3977,20 +4047,24 @@ decision_tree::gen (FILE *f, bool gimple) + continue; + } + ++ ++ /* Cycle the file buffers. */ ++ FILE *f = get_out_file (files); ++ + /* Then generate the main entry with the outermost switch and + tail-calls to the split-out functions. */ + if (gimple) +- fprintf (f, "\nbool\n" ++ emit_func (f, true, false, "\nbool\n" + "gimple_simplify (gimple_match_op *res_op, gimple_seq *seq,\n" + " tree (*valueize)(tree) ATTRIBUTE_UNUSED,\n" + " code_helper code, const tree type"); + else +- fprintf (f, "\ntree\n" ++ emit_func (f, true, false, "\ntree\n" + "generic_simplify (location_t loc, enum tree_code code, " + "const tree type ATTRIBUTE_UNUSED"); + for (unsigned i = 0; i < n; ++i) +- fprintf (f, ", tree _p%d", i); +- fprintf (f, ")\n"); ++ emit_func (f, false, false, ", tree _p%d", i); ++ emit_func (f, false, true, ")"); + fprintf (f, "{\n"); + + if (gimple) +@@ -4045,11 +4119,11 @@ decision_tree::gen (FILE *f, bool gimple) + void + write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple) + { +- fprintf (f, "\nbool\n" +- "%s%s (tree t%s%s)\n" +- "{\n", gimple ? "gimple_" : "tree_", p->id, +- p->nargs > 0 ? ", tree *res_ops" : "", +- gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : ""); ++ emit_func (f, true, true, "\nbool\n%s%s (tree t%s%s)", ++ gimple ? "gimple_" : "tree_", p->id, ++ p->nargs > 0 ? ", tree *res_ops" : "", ++ gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : ""); ++ fprintf (f, "{\n"); + /* Conveniently make 'type' available. */ + fprintf_indent (f, 2, "const tree type = TREE_TYPE (t);\n"); + fprintf_indent (f, 2, "const bool debug_dump = " +@@ -4070,9 +4144,13 @@ write_header (FILE *f, const char *head) + { + fprintf (f, "/* Generated automatically by the program `genmatch' from\n"); + fprintf (f, " a IL pattern matching and simplification description. */\n"); ++ fprintf (f, "#pragma GCC diagnostic push\n"); ++ fprintf (f, "#pragma GCC diagnostic ignored \"-Wunused-variable\"\n"); ++ fprintf (f, "#pragma GCC diagnostic ignored \"-Wunused-function\"\n"); + + /* Include the header instead of writing it awkwardly quoted here. */ +- fprintf (f, "\n#include \"%s\"\n", head); ++ if (head) ++ fprintf (f, "\n#include \"%s\"\n", head); + } + + +@@ -5213,6 +5291,30 @@ round_alloc_size (size_t s) + } + + ++/* Construct and display the help menu. */ ++ ++static void ++showUsage () ++{ ++ fprintf (stderr, "Usage: genmatch [--gimple] [--generic] " ++ "[--header=] [--include=] [-v[v]] input " ++ "[...]\n"); ++ fprintf (stderr, "\nWhen more then one outputfile is specified --header " ++ "is required.\n"); ++} ++ ++/* Write out the correct include to the match-head fle containing the helper ++ files. */ ++ ++static void ++write_header_includes (bool gimple, FILE *header_file) ++{ ++ if (gimple) ++ fprintf (header_file, "#include \"gimple-match-head.cc\"\n"); ++ else ++ fprintf (header_file, "#include \"generic-match-head.cc\"\n"); ++} ++ + /* The genmatch generator program. It reads from a pattern description + and outputs GIMPLE or GENERIC IL matching and simplification routines. */ + +@@ -5227,25 +5329,44 @@ main (int argc, char **argv) + return 1; + + bool gimple = true; +- char *input = argv[argc-1]; +- for (int i = 1; i < argc - 1; ++i) ++ char *s_header_file = NULL; ++ char *s_include_file = NULL; ++ auto_vec files; ++ char *input = NULL; ++ int last_file = argc - 1; ++ for (int i = argc - 1; i >= 1; --i) + { + if (strcmp (argv[i], "--gimple") == 0) + gimple = true; + else if (strcmp (argv[i], "--generic") == 0) + gimple = false; ++ else if (strncmp (argv[i], "--header=", 9) == 0) ++ s_header_file = &argv[i][9]; ++ else if (strncmp (argv[i], "--include=", 10) == 0) ++ s_include_file = &argv[i][10]; + else if (strcmp (argv[i], "-v") == 0) + verbose = 1; + else if (strcmp (argv[i], "-vv") == 0) + verbose = 2; ++ else if (strncmp (argv[i], "--", 2) != 0 && last_file-- == i) ++ files.safe_push (argv[i]); + else + { +- fprintf (stderr, "Usage: genmatch " +- "[--gimple] [--generic] [-v[v]] input\n"); ++ showUsage (); + return 1; + } + } + ++ /* Validate if the combinations are valid. */ ++ if ((files.length () > 1 && !s_header_file) || files.is_empty ()) ++ showUsage (); ++ ++ if (!s_include_file) ++ s_include_file = s_header_file; ++ ++ /* Input file is the last in the reverse list. */ ++ input = files.pop (); ++ + line_table = XCNEW (class line_maps); + linemap_init (line_table, 0); + line_table->reallocator = xrealloc; +@@ -5292,10 +5413,28 @@ main (int argc, char **argv) + /* Parse ahead! */ + parser p (r, gimple); + +- if (gimple) +- write_header (stdout, "gimple-match-head.cc"); ++ /* Create file buffers. */ ++ int n_parts = files.is_empty () ? 1 : files.length (); ++ auto_vec parts (n_parts); ++ if (files.is_empty ()) ++ { ++ parts.quick_push (stdout); ++ write_header (stdout, s_include_file); ++ write_header_includes (gimple, stdout); ++ } + else +- write_header (stdout, "generic-match-head.cc"); ++ { ++ for (char *s_file : files) ++ { ++ parts.quick_push (fopen (s_file, "w")); ++ write_header (parts.last (), s_include_file); ++ } ++ ++ header_file = fopen (s_header_file, "w"); ++ fprintf (header_file, "#ifndef GCC_GIMPLE_MATCH_AUTO_H\n" ++ "#define GCC_GIMPLE_MATCH_AUTO_H\n"); ++ write_header_includes (gimple, header_file); ++ } + + /* Go over all predicates defined with patterns and perform + lowering and code generation. */ +@@ -5315,7 +5454,10 @@ main (int argc, char **argv) + if (verbose == 2) + dt.print (stderr); + +- write_predicate (stdout, pred, dt, gimple); ++ /* Cycle the file buffers. */ ++ FILE *f = get_out_file (parts); ++ ++ write_predicate (f, pred, dt, gimple); + } + + /* Lower the main simplifiers and generate code for them. */ +@@ -5332,7 +5474,19 @@ main (int argc, char **argv) + if (verbose == 2) + dt.print (stderr); + +- dt.gen (stdout, gimple); ++ dt.gen (parts, gimple); ++ ++ for (FILE *f : parts) ++ { ++ fprintf (f, "#pragma GCC diagnostic pop\n"); ++ fclose (f); ++ } ++ ++ if (header_file) ++ { ++ fprintf (header_file, "#endif /* GCC_GIMPLE_MATCH_AUTO_H. */\n"); ++ fclose (header_file); ++ } + + /* Finalize. */ + cpp_finish (r, NULL); +-- +2.44.0 + +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21 + +From dcfebe060ee266f364bb60f1cdf0cec58818c4f7 Mon Sep 17 00:00:00 2001 +From: Tamar Christina +Date: Fri, 5 May 2023 13:42:17 +0100 +Subject: [PATCH 06/15] match.pd: Use splits in makefile and make configurable. + +This updates the build system to split up match.pd files into chunks of 10. +This also introduces a new flag --with-matchpd-partitions which can be used to +change the number of partitions. + +For the analysis of why 10 please look at the previous patch in the series. + +gcc/ChangeLog: + + PR bootstrap/84402 + * Makefile.in (NUM_MATCH_SPLITS, MATCH_SPLITS_SEQ, + GIMPLE_MATCH_PD_SEQ_SRC, GIMPLE_MATCH_PD_SEQ_O, + GENERIC_MATCH_PD_SEQ_SRC, GENERIC_MATCH_PD_SEQ_O): New. + (OBJS, MOSTLYCLEANFILES, .PRECIOUS): Use them. + (s-match): Split into s-generic-match and s-gimple-match. + * configure.ac (with-matchpd-partitions, + DEFAULT_MATCHPD_PARTITIONS): New. + * configure: Regenerate. + +(cherry picked from commit 0a85544e1aaeca41133ecfc438cda913dbc0f122) +--- + gcc/Makefile.in | 67 +++++++++++++++++++++++++++++++++--------------- + gcc/config.in | 6 +++++ + gcc/configure | 29 +++++++++++++++++++-- + gcc/configure.ac | 15 +++++++++++ + 4 files changed, 95 insertions(+), 22 deletions(-) + +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index 406856acde1c..f0c34d00ecbc 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -214,6 +214,14 @@ rtl-ssa-warn = $(STRICT_WARN) + GCC_WARN_CFLAGS = $(LOOSE_WARN) $(C_LOOSE_WARN) $($(@D)-warn) $(if $(filter-out $(STRICT_WARN),$($(@D)-warn)),,$(C_STRICT_WARN)) $(NOCOMMON_FLAG) $($@-warn) + GCC_WARN_CXXFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn) + ++# The number of splits to be made for the match.pd files. ++NUM_MATCH_SPLITS = @DEFAULT_MATCHPD_PARTITIONS@ ++MATCH_SPLITS_SEQ = $(shell seq 1 $(NUM_MATCH_SPLITS)) ++GIMPLE_MATCH_PD_SEQ_SRC = $(patsubst %, gimple-match-%.cc, $(MATCH_SPLITS_SEQ)) ++GIMPLE_MATCH_PD_SEQ_O = $(patsubst %, gimple-match-%.o, $(MATCH_SPLITS_SEQ)) ++GENERIC_MATCH_PD_SEQ_SRC = $(patsubst %, generic-match-%.cc, $(MATCH_SPLITS_SEQ)) ++GENERIC_MATCH_PD_SEQ_O = $(patsubst %, generic-match-%.o, $(MATCH_SPLITS_SEQ)) ++ + # These files are to have specific diagnostics suppressed, or are not to + # be subject to -Werror: + # flex output may yield harmless "no previous prototype" warnings +@@ -222,9 +230,8 @@ gengtype-lex.o-warn = -Wno-error + libgcov-util.o-warn = -Wno-error + libgcov-driver-tool.o-warn = -Wno-error + libgcov-merge-tool.o-warn = -Wno-error +-gimple-match.o-warn = -Wno-unused ++gimple-match-head.o-warn = -Wno-unused + gimple-match-exports.o-warn = -Wno-unused +-generic-match.o-warn = -Wno-unused + dfp.o-warn = -Wno-strict-aliasing + + # All warnings have to be shut off in stage1 if the compiler used then +@@ -1312,9 +1319,9 @@ ANALYZER_OBJS = \ + # will build them sooner, because they are large and otherwise tend to be + # the last objects to finish building. + OBJS = \ +- gimple-match.o \ ++ $(GIMPLE_MATCH_PD_SEQ_O) \ + gimple-match-exports.o \ +- generic-match.o \ ++ $(GENERIC_MATCH_PD_SEQ_O) \ + insn-attrtab.o \ + insn-automata.o \ + insn-dfatab.o \ +@@ -1807,7 +1814,8 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \ + insn-output.cc insn-recog.cc insn-emit.cc insn-extract.cc insn-peep.cc \ + insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \ + insn-latencytab.cc insn-opinit.cc insn-opinit.h insn-preds.cc insn-constants.h \ +- tm-preds.h tm-constrs.h checksum-options gimple-match.cc generic-match.cc \ ++ tm-preds.h tm-constrs.h checksum-options $(GIMPLE_MATCH_PD_SEQ_SRC) \ ++ $(GENERIC_MATCH_PD_SEQ_SRC) gimple-match-auto.h generic-match-auto.h \ + tree-check.h min-insn-modes.cc insn-modes.cc insn-modes.h insn-modes-inline.h \ + genrtl.h gt-*.h gtype-*.h gtype-desc.cc gtyp-input.list \ + case-cfn-macros.h cfn-operators.pd \ +@@ -2422,7 +2430,8 @@ $(common_out_object_file): $(common_out_file) + .PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \ + insn-emit.cc insn-recog.cc insn-extract.cc insn-output.cc insn-peep.cc \ + insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \ +- insn-latencytab.cc insn-preds.cc gimple-match.cc generic-match.cc \ ++ insn-latencytab.cc insn-preds.cc $(GIMPLE_MATCH_PD_SEQ_SRC) \ ++ $(GENERIC_MATCH_PD_SEQ_SRC) gimple-match-auto.h generic-match-auto.h \ + insn-target-def.h + + # Dependencies for the md file. The first time through, we just assume +@@ -2665,19 +2674,36 @@ s-tm-texi: build/genhooks$(build_exeext) $(srcdir)/doc/tm.texi.in + false; \ + fi + +-gimple-match.cc: s-match gimple-match-head.cc gimple-match-exports.cc ; @true +-generic-match.cc: s-match generic-match-head.cc ; @true +- +-s-match: build/genmatch$(build_exeext) $(srcdir)/match.pd cfn-operators.pd +- $(RUN_GEN) build/genmatch$(build_exeext) --gimple $(srcdir)/match.pd \ +- > tmp-gimple-match.cc +- $(RUN_GEN) build/genmatch$(build_exeext) --generic $(srcdir)/match.pd \ +- > tmp-generic-match.cc +- $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match.cc \ +- gimple-match.cc +- $(SHELL) $(srcdir)/../move-if-change tmp-generic-match.cc \ +- generic-match.cc +- $(STAMP) s-match ++$(GIMPLE_MATCH_PD_SEQ_SRC): s-gimple-match gimple-match-head.cc \ ++ gimple-match-exports.cc; @true ++gimple-match-auto.h: s-gimple-match gimple-match-head.cc \ ++ gimple-match-exports.cc; @true ++$(GENERIC_MATCH_PD_SEQ_SRC): s-generic-match generic-match-head.cc; @true ++generic-match-auto.h: s-generic-match generic-match-head.cc; @true ++ ++s-gimple-match: build/genmatch$(build_exeext) \ ++ $(srcdir)/match.pd cfn-operators.pd ++ $(RUN_GEN) build/genmatch$(build_exeext) --gimple \ ++ --header=tmp-gimple-match-auto.h --include=gimple-match-auto.h \ ++ $(srcdir)/match.pd $(patsubst %, tmp-%, $(GIMPLE_MATCH_PD_SEQ_SRC)) ++ $(foreach id, $(MATCH_SPLITS_SEQ), \ ++ $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match-$(id).cc \ ++ gimple-match-$(id).cc;) ++ $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match-auto.h \ ++ gimple-match-auto.h ++ $(STAMP) s-gimple-match ++ ++s-generic-match: build/genmatch$(build_exeext) \ ++ $(srcdir)/match.pd cfn-operators.pd ++ $(RUN_GEN) build/genmatch$(build_exeext) --generic \ ++ --header=tmp-generic-match-auto.h --include=generic-match-auto.h \ ++ $(srcdir)/match.pd $(patsubst %, tmp-%, $(GENERIC_MATCH_PD_SEQ_SRC)) ++ $(foreach id, $(MATCH_SPLITS_SEQ), \ ++ $(SHELL) $(srcdir)/../move-if-change tmp-generic-match-$(id).cc \ ++ generic-match-$(id).cc;) ++ $(SHELL) $(srcdir)/../move-if-change tmp-generic-match-auto.h \ ++ generic-match-auto.h ++ $(STAMP) s-generic-match + + GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ + $(host_xm_file_list) \ +@@ -2812,7 +2838,8 @@ generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_H) multilib.h \ + $(ALL_GTFILES_H) gtype-desc.cc gtype-desc.h version.h \ + options.h target-hooks-def.h insn-opinit.h \ + common/common-target-hooks-def.h pass-instances.def \ +- gimple-match.cc generic-match.cc \ ++ $(GIMPLE_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \ ++ gimple-match-auto.h generic-match-auto.h \ + c-family/c-target-hooks-def.h d/d-target-hooks-def.h \ + case-cfn-macros.h \ + cfn-operators.pd omp-device-properties.h +diff --git a/gcc/config.in b/gcc/config.in +index 5281a12a707c..ea60c5b11fc5 100644 +--- a/gcc/config.in ++++ b/gcc/config.in +@@ -67,6 +67,12 @@ + #endif + + ++/* Define to larger than one set the number of match.pd partitions to make. */ ++#ifndef USED_FOR_TARGET ++#undef DEFAULT_MATCHPD_PARTITIONS ++#endif ++ ++ + /* Define to larger than zero set the default stack clash protector size. */ + #ifndef USED_FOR_TARGET + #undef DEFAULT_STK_CLASH_GUARD_SIZE +diff --git a/gcc/configure b/gcc/configure +index ade0af23e8cc..542d100c2b73 100755 +--- a/gcc/configure ++++ b/gcc/configure +@@ -838,6 +838,7 @@ enable_gcov + enable_shared + enable_fixed_point + enable_decimal_float ++DEFAULT_MATCHPD_PARTITIONS + with_float + with_cpu + enable_multiarch +@@ -965,6 +966,7 @@ enable_valgrind_annotations + enable_multilib + enable_multiarch + with_stack_clash_protection_guard_size ++with_matchpd_partitions + enable___cxa_atexit + enable_decimal_float + enable_fixed_point +@@ -1832,6 +1834,9 @@ Optional Packages: + --with-stack-clash-protection-guard-size=size + Set the default stack clash protection guard size + for specific targets as a power of two in bytes. ++ --with-matchpd-partitions=num ++ Set the number of partitions to make for gimple and ++ generic when splitting match.pd. [default=10] + --with-dwarf2 force the default debug format to be DWARF 2 (or + later) + --with-specs=SPECS add SPECS to driver command-line processing +@@ -7918,6 +7923,26 @@ cat >>confdefs.h <<_ACEOF + _ACEOF + + ++# Specify the number of splits of match.pd to generate. ++ ++# Check whether --with-matchpd-partitions was given. ++if test "${with_matchpd_partitions+set}" = set; then : ++ withval=$with_matchpd_partitions; DEFAULT_MATCHPD_PARTITIONS="$with_matchpd_partitions" ++else ++ DEFAULT_MATCHPD_PARTITIONS=10 ++fi ++ ++if (test $DEFAULT_MATCHPD_PARTITIONS -lt 1); then ++ as_fn_error $? "Invalid value $DEFAULT_MATCHPD_PARTITIONS for --with-matchpd-partitions. Cannot be negative." "$LINENO" 5 ++fi ++ ++ ++cat >>confdefs.h <<_ACEOF ++#define DEFAULT_MATCHPD_PARTITIONS $DEFAULT_MATCHPD_PARTITIONS ++_ACEOF ++ ++ ++ + # Enable __cxa_atexit for C++. + # Check whether --enable-__cxa_atexit was given. + if test "${enable___cxa_atexit+set}" = set; then : +@@ -19871,7 +19896,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 19874 "configure" ++#line 19899 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +@@ -19977,7 +20002,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 19980 "configure" ++#line 20005 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +diff --git a/gcc/configure.ac b/gcc/configure.ac +index bf8ff4d63906..31aa8566a3e7 100644 +--- a/gcc/configure.ac ++++ b/gcc/configure.ac +@@ -943,6 +943,21 @@ fi + AC_DEFINE_UNQUOTED(DEFAULT_STK_CLASH_GUARD_SIZE, $DEFAULT_STK_CLASH_GUARD_SIZE, + [Define to larger than zero set the default stack clash protector size.]) + ++# Specify the number of splits of match.pd to generate. ++AC_ARG_WITH(matchpd-partitions, ++[AS_HELP_STRING([--with-matchpd-partitions=num], ++[Set the number of partitions to make for gimple and generic when splitting match.pd. [default=10]])], ++[DEFAULT_MATCHPD_PARTITIONS="$with_matchpd_partitions"], [DEFAULT_MATCHPD_PARTITIONS=10]) ++if (test $DEFAULT_MATCHPD_PARTITIONS -lt 1); then ++ AC_MSG_ERROR(m4_normalize([ ++ Invalid value $DEFAULT_MATCHPD_PARTITIONS for --with-matchpd-partitions. \ ++ Cannot be negative.])) ++fi ++ ++AC_DEFINE_UNQUOTED(DEFAULT_MATCHPD_PARTITIONS, $DEFAULT_MATCHPD_PARTITIONS, ++ [Define to larger than one set the number of match.pd partitions to make.]) ++AC_SUBST(DEFAULT_MATCHPD_PARTITIONS) ++ + # Enable __cxa_atexit for C++. + AC_ARG_ENABLE(__cxa_atexit, + [AS_HELP_STRING([--enable-__cxa_atexit], [enable __cxa_atexit for C++])], +-- +2.44.0 + +From 2c1f550db00c7dd9abede5644a3acd915767e0ad Mon Sep 17 00:00:00 2001 +From: Alexander Monakov +Date: Fri, 5 May 2023 19:46:25 +0300 +Subject: [PATCH 07/15] Makefile.in: clean up match.pd-related dependencies + +Clean up confusing changes from the recent refactoring for +parallel match.pd build. + +gimple-match-head.o is not built. Remove related flags adjustment. + +Autogenerated gimple-match-N.o files do not depend on +gimple-match-exports.cc. + +{gimple,generic)-match-auto.h only depend on the prerequisites of the +corresponding s-{gimple,generic}-match stamp file, not any .cc file. + +gcc/ChangeLog: + + * Makefile.in: (gimple-match-head.o-warn): Remove. + (GIMPLE_MATCH_PD_SEQ_SRC): Do not depend on + gimple-match-exports.cc. + (gimple-match-auto.h): Only depend on s-gimple-match. + (generic-match-auto.h): Likewise. + +(cherry picked from commit 31c70a7daa368767f0f58e0389deb2c69d9e14fd) +--- + gcc/Makefile.in | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index f0c34d00ecbc..fe3af5c8008c 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -230,7 +230,6 @@ gengtype-lex.o-warn = -Wno-error + libgcov-util.o-warn = -Wno-error + libgcov-driver-tool.o-warn = -Wno-error + libgcov-merge-tool.o-warn = -Wno-error +-gimple-match-head.o-warn = -Wno-unused + gimple-match-exports.o-warn = -Wno-unused + dfp.o-warn = -Wno-strict-aliasing + +@@ -2674,12 +2673,10 @@ s-tm-texi: build/genhooks$(build_exeext) $(srcdir)/doc/tm.texi.in + false; \ + fi + +-$(GIMPLE_MATCH_PD_SEQ_SRC): s-gimple-match gimple-match-head.cc \ +- gimple-match-exports.cc; @true +-gimple-match-auto.h: s-gimple-match gimple-match-head.cc \ +- gimple-match-exports.cc; @true ++$(GIMPLE_MATCH_PD_SEQ_SRC): s-gimple-match gimple-match-head.cc; @true ++gimple-match-auto.h: s-gimple-match; @true + $(GENERIC_MATCH_PD_SEQ_SRC): s-generic-match generic-match-head.cc; @true +-generic-match-auto.h: s-generic-match generic-match-head.cc; @true ++generic-match-auto.h: s-generic-match; @true + + s-gimple-match: build/genmatch$(build_exeext) \ + $(srcdir)/match.pd cfn-operators.pd +-- +2.44.0 + +https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=319aef8d2fde32be5cfed99f321c7f90e33d1f1d + +From a18a994030d16f58ebced231e778ec4e06a98abb Mon Sep 17 00:00:00 2001 +From: Jakub Jelinek +Date: Sat, 6 May 2023 02:32:17 +0200 +Subject: [PATCH 08/15] build: Replace seq for portability with GNU Make + variant + +Some hosts like AIX don't have seq command, this patch replaces it +with something that uses just GNU make features we've been using +for this already before for the parallel make check. + +2023-05-06 Jakub Jelinek + + * Makefile.in (check_p_numbers): Rename to one_to_9999, move + earlier with helper variables also renamed. + (MATCH_SPLUT_SEQ): Use $(wordlist 1,$(NUM_MATCH_SPLITS),$(one_to_9999)) + instead of $(shell seq 1 $(NUM_MATCH_SPLITS)). + (check_p_subdirs): Use $(one_to_9999) instead of $(check_p_numbers). + +(cherry picked from commit 319aef8d2fde32be5cfed99f321c7f90e33d1f1d) +--- + gcc/Makefile.in | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index fe3af5c8008c..975fbb61ea8a 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -214,9 +214,19 @@ rtl-ssa-warn = $(STRICT_WARN) + GCC_WARN_CFLAGS = $(LOOSE_WARN) $(C_LOOSE_WARN) $($(@D)-warn) $(if $(filter-out $(STRICT_WARN),$($(@D)-warn)),,$(C_STRICT_WARN)) $(NOCOMMON_FLAG) $($@-warn) + GCC_WARN_CXXFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn) + ++# 1 2 3 ... 9999 ++one_to_9999_0:=1 2 3 4 5 6 7 8 9 ++one_to_9999_1:=0 $(one_to_9999_0) ++one_to_9999_2:=$(foreach i,$(one_to_9999_0),$(addprefix $(i),$(one_to_9999_1))) ++one_to_9999_3:=$(addprefix 0,$(one_to_9999_1)) $(one_to_9999_2) ++one_to_9999_4:=$(foreach i,$(one_to_9999_0),$(addprefix $(i),$(one_to_9999_3))) ++one_to_9999_5:=$(addprefix 0,$(one_to_9999_3)) $(one_to_9999_4) ++one_to_9999_6:=$(foreach i,$(one_to_9999_0),$(addprefix $(i),$(one_to_9999_5))) ++one_to_9999:=$(one_to_9999_0) $(one_to_9999_2) $(one_to_9999_4) $(one_to_9999_6) ++ + # The number of splits to be made for the match.pd files. + NUM_MATCH_SPLITS = @DEFAULT_MATCHPD_PARTITIONS@ +-MATCH_SPLITS_SEQ = $(shell seq 1 $(NUM_MATCH_SPLITS)) ++MATCH_SPLITS_SEQ = $(wordlist 1,$(NUM_MATCH_SPLITS),$(one_to_9999)) + GIMPLE_MATCH_PD_SEQ_SRC = $(patsubst %, gimple-match-%.cc, $(MATCH_SPLITS_SEQ)) + GIMPLE_MATCH_PD_SEQ_O = $(patsubst %, gimple-match-%.o, $(MATCH_SPLITS_SEQ)) + GENERIC_MATCH_PD_SEQ_SRC = $(patsubst %, generic-match-%.cc, $(MATCH_SPLITS_SEQ)) +@@ -4224,18 +4234,10 @@ $(patsubst %,%-subtargets,$(lang_checks)): check-%-subtargets: + check_p_tool=$(firstword $(subst _, ,$*)) + check_p_count=$(check_$(check_p_tool)_parallelize) + check_p_subno=$(word 2,$(subst _, ,$*)) +-check_p_numbers0:=1 2 3 4 5 6 7 8 9 +-check_p_numbers1:=0 $(check_p_numbers0) +-check_p_numbers2:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers1))) +-check_p_numbers3:=$(addprefix 0,$(check_p_numbers1)) $(check_p_numbers2) +-check_p_numbers4:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers3))) +-check_p_numbers5:=$(addprefix 0,$(check_p_numbers3)) $(check_p_numbers4) +-check_p_numbers6:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers5))) +-check_p_numbers:=$(check_p_numbers0) $(check_p_numbers2) $(check_p_numbers4) $(check_p_numbers6) + check_p_subdir=$(subst _,,$*) + check_p_subdirs=$(wordlist 1,$(check_p_count),$(wordlist 1, \ + $(if $(GCC_TEST_PARALLEL_SLOTS),$(GCC_TEST_PARALLEL_SLOTS),128), \ +- $(check_p_numbers))) ++ $(one_to_9999))) + + # For parallelized check-% targets, this decides whether parallelization + # is desirable (if -jN is used). If desirable, recursive make is run with +-- +2.44.0 + +https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=bc45e18d433f879a02e369d027829f90f9e85724 + +From b60091fe7d22e0cac71461dceeb804e37555b5d3 Mon Sep 17 00:00:00 2001 +From: Tamar Christina +Date: Mon, 12 Jun 2023 14:06:08 +0100 +Subject: [PATCH 09/15] Remove DEFAULT_MATCHPD_PARTITIONS macro + +As Jakub pointed out, DEFAULT_MATCHPD_PARTITIONS +is now unused and can be removed. + +gcc/ChangeLog: + + * config.in: Regenerate. + * configure: Regenerate. + * configure.ac: Remove DEFAULT_MATCHPD_PARTITIONS. + +(cherry picked from commit bc45e18d433f879a02e369d027829f90f9e85724) +--- + gcc/config.in | 6 ------ + gcc/configure | 9 ++------- + gcc/configure.ac | 2 -- + 3 files changed, 2 insertions(+), 15 deletions(-) + +diff --git a/gcc/config.in b/gcc/config.in +index ea60c5b11fc5..5281a12a707c 100644 +--- a/gcc/config.in ++++ b/gcc/config.in +@@ -67,12 +67,6 @@ + #endif + + +-/* Define to larger than one set the number of match.pd partitions to make. */ +-#ifndef USED_FOR_TARGET +-#undef DEFAULT_MATCHPD_PARTITIONS +-#endif +- +- + /* Define to larger than zero set the default stack clash protector size. */ + #ifndef USED_FOR_TARGET + #undef DEFAULT_STK_CLASH_GUARD_SIZE +diff --git a/gcc/configure b/gcc/configure +index 542d100c2b73..cc8247037569 100755 +--- a/gcc/configure ++++ b/gcc/configure +@@ -7937,11 +7937,6 @@ if (test $DEFAULT_MATCHPD_PARTITIONS -lt 1); then + fi + + +-cat >>confdefs.h <<_ACEOF +-#define DEFAULT_MATCHPD_PARTITIONS $DEFAULT_MATCHPD_PARTITIONS +-_ACEOF +- +- + + # Enable __cxa_atexit for C++. + # Check whether --enable-__cxa_atexit was given. +@@ -19896,7 +19891,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 19899 "configure" ++#line 19894 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +@@ -20002,7 +19997,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 20005 "configure" ++#line 20000 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +diff --git a/gcc/configure.ac b/gcc/configure.ac +index 31aa8566a3e7..d02ffc22a3a3 100644 +--- a/gcc/configure.ac ++++ b/gcc/configure.ac +@@ -954,8 +954,6 @@ if (test $DEFAULT_MATCHPD_PARTITIONS -lt 1); then + Cannot be negative.])) + fi + +-AC_DEFINE_UNQUOTED(DEFAULT_MATCHPD_PARTITIONS, $DEFAULT_MATCHPD_PARTITIONS, +- [Define to larger than one set the number of match.pd partitions to make.]) + AC_SUBST(DEFAULT_MATCHPD_PARTITIONS) + + # Enable __cxa_atexit for C++. +-- +2.44.0 + -- cgit v1.2.3-70-g09d2