public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/gcc-patches:master commit in: 13.3.0/musl/, 13.3.0/gentoo/
@ 2024-09-29 18:56 Sam James
  0 siblings, 0 replies; only message in thread
From: Sam James @ 2024-09-29 18:56 UTC (permalink / raw
  To: gentoo-commits

commit:     e8a4b41686079087418212a10b3b32263355135a
Author:     Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Sun Sep 29 18:55:57 2024 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Sun Sep 29 18:55:57 2024 +0000
URL:        https://gitweb.gentoo.org/proj/gcc-patches.git/commit/?id=e8a4b416

13.3.0: add, clone of 13.3.0 with LTO patch

Signed-off-by: Sam James <sam <AT> gentoo.org>

 13.3.0/gentoo/01_all_default-fortify-source.patch  |   26 +
 .../02_all_default-warn-format-security.patch      |   22 +
 .../gentoo/03_all_default-warn-trampolines.patch   |   13 +
 13.3.0/gentoo/04_all_nossp-on-nostdlib.patch       |   27 +
 13.3.0/gentoo/05_all_alpha-mieee-default.patch     |   39 +
 13.3.0/gentoo/06_all_ia64_note.GNU-stack.patch     |   92 +
 13.3.0/gentoo/07_all_libiberty-asprintf.patch      |   18 +
 13.3.0/gentoo/08_all_libiberty-pic.patch           |   10 +
 13.3.0/gentoo/09_all_nopie-all-flags.patch         |   18 +
 13.3.0/gentoo/10_all_sh-drop-sysroot-suffix.patch  |   26 +
 13.3.0/gentoo/11_all_ia64-TEXTREL.patch            |   22 +
 13.3.0/gentoo/14_all_respect-build-cxxflags.patch  |   39 +
 .../15_all_DEF_GENTOO_GLIBCXX_ASSERTIONS.patch     |   14 +
 13.3.0/gentoo/20_all_libstdcxx-no-vtv.patch        |   61 +
 13.3.0/gentoo/22_all_default_ssp-buffer-size.patch |   14 +
 13.3.0/gentoo/23_all_DEF_GENTOO_ZNOW-z-now.patch   |   26 +
 ...ll_DEF_GENTOO_SCP-fstack-clash-protection.patch |   65 +
 .../25_all_lto-intl-workaround-PR95194.patch       |   20 +
 13.3.0/gentoo/26_all_enable-cet.patch              |  193 ++
 13.3.0/gentoo/28_all_drop_CFLAGS_sed.patch         |   35 +
 13.3.0/gentoo/29_all_msgfmt-libstdc++-link.patch   |   39 +
 13.3.0/gentoo/30_all_tar_libstdc++-link.patch      |   57 +
 13.3.0/gentoo/31_all_gm2_make_P_var.patch          |   49 +
 ...l_match.pd-don-t-emit-label-if-not-needed.patch |  114 +
 ...move-commented-out-line-pragmas-unless-vv.patch |   41 +
 ...78_all_match.pd-CSE-the-dump-output-check.patch |   70 +
 ...lit-shared-code-to-gimple-match-exports.c.patch | 2560 ++++++++++++++++++++
 ...pd-automatically-partition-match.cc-files.patch |  524 ++++
 ...e-splits-in-makefile-and-make-configurabl.patch |  276 +++
 ...in-clean-up-match.pd-related-dependencies.patch |   60 +
 ...ce-seq-for-portability-with-GNU-Make-vari.patch |   73 +
 ...l_Remove-DEFAULT_MATCHPD_PARTITIONS-macro.patch |   90 +
 ....in-Make-TM_P_H-depend-on-TREE_H-PR111021.patch |   66 +
 ...in-Make-recog.h-depend-on-TREE_H-PR111021.patch |   45 +
 ...genemit-Split-insn-emit.cc-into-ten-files.patch | 1404 +++++++++++
 .../91_all_riscv_PR106271-multilib-bootstrap.patch |   37 +
 .../gentoo/92_all_riscv_PR109760-gstreamer.patch   |  337 +++
 13.3.0/gentoo/93_all_PR115917-ada-lto.patch        |   52 +
 13.3.0/gentoo/README.history                       |   40 +
 13.3.0/musl/25_all_multilib_pure64.patch           |   83 +
 13.3.0/musl/50_all_libssp_unconditionally.patch    |   24 +
 13.3.0/musl/50_all_posix_memalign.patch            |   28 +
 13.3.0/musl/50_all_sanitizer_lfs.patch             |  197 ++
 13.3.0/musl/README.history                         |   14 +
 44 files changed, 7060 insertions(+)

diff --git a/13.3.0/gentoo/01_all_default-fortify-source.patch b/13.3.0/gentoo/01_all_default-fortify-source.patch
new file mode 100644
index 0000000..4cdf5f6
--- /dev/null
+++ b/13.3.0/gentoo/01_all_default-fortify-source.patch
@@ -0,0 +1,26 @@
+Taken Debian's patch and removed docs matches:
+    https://salsa.debian.org/toolchain-team/gcc.git
+Also see https://bugs.gentoo.org/621036 where
+initially Gentoo used too complicated macro.
+
+# DP: Turn on -D_FORTIFY_SOURCE=2 by default for C, C++, ObjC, ObjC++,
+# DP: if the optimization level is > 0
+--- a/gcc/c-family/c-cppbuiltin.cc
++++ b/gcc/c-family/c-cppbuiltin.cc
+@@ -1510,6 +1510,16 @@ c_cpp_builtins (cpp_reader *pfile)
+   builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
+   builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
+ 
++#if !defined(ACCEL_COMPILER)
++  #ifndef GENTOO_FORTIFY_SOURCE_LEVEL
++    #define GENTOO_FORTIFY_SOURCE_LEVEL 2
++  #endif
++
++  /* F_S enabled by default for optimization levels > 0, except for ASAN: https://github.com/google/sanitizers/issues/247 */
++  if (optimize && ! (flag_sanitize & SANITIZE_ADDRESS))
++    builtin_define_with_int_value ("_FORTIFY_SOURCE", GENTOO_FORTIFY_SOURCE_LEVEL);
++#endif
++
+   /* Misc.  */
+   if (flag_gnu89_inline)
+     cpp_define (pfile, "__GNUC_GNU_INLINE__");

diff --git a/13.3.0/gentoo/02_all_default-warn-format-security.patch b/13.3.0/gentoo/02_all_default-warn-format-security.patch
new file mode 100644
index 0000000..9723a1c
--- /dev/null
+++ b/13.3.0/gentoo/02_all_default-warn-format-security.patch
@@ -0,0 +1,22 @@
+Enable -Wformat and -Wformat-security by default.
+
+--- a/gcc/c-family/c.opt
++++ b/gcc/c-family/c.opt
+@@ -696,7 +696,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)
++C ObjC C++ ObjC++ Var(warn_format_security) Init(1) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 2, 0)
+ Warn about possible security problems with format functions.
+ 
+ Wformat-signedness
+@@ -717,7 +717,7 @@ C ObjC C++ ObjC++ Var(warn_format_zero_length) Warning LangEnabledBy(C ObjC C++
+ Warn about zero-length formats.
+ 
+ Wformat=
+-C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0) IntegerRange(0, 2)
++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.
+ 
+ Wformat-overflow=

diff --git a/13.3.0/gentoo/03_all_default-warn-trampolines.patch b/13.3.0/gentoo/03_all_default-warn-trampolines.patch
new file mode 100644
index 0000000..fb6d8bc
--- /dev/null
+++ b/13.3.0/gentoo/03_all_default-warn-trampolines.patch
@@ -0,0 +1,13 @@
+Enable -Wtrampolines by default.
+
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -798,7 +798,7 @@ Common Var(warn_system_headers) Warning
+ Do not suppress warnings from system headers.
+ 
+ Wtrampolines
+-Common Var(warn_trampolines) Warning
++Common Var(warn_trampolines) Init(1) Warning
+ Warn whenever a trampoline is generated.
+ 
+ Wtrivial-auto-var-init

diff --git a/13.3.0/gentoo/04_all_nossp-on-nostdlib.patch b/13.3.0/gentoo/04_all_nossp-on-nostdlib.patch
new file mode 100644
index 0000000..b633d7f
--- /dev/null
+++ b/13.3.0/gentoo/04_all_nossp-on-nostdlib.patch
@@ -0,0 +1,27 @@
+Disable ssp on -nostdlib, -nodefaultlibs and -ffreestanding 
+
+https://bugs.gentoo.org/484714
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -984,6 +984,12 @@ proper position among the other output files.  */
+ #define LINK_GCC_C_SEQUENCE_SPEC "%G %{!nolibc:%L %G}"
+ #endif
+ 
++#ifdef ENABLE_DEFAULT_SSP
++#define NO_SSP_SPEC "%{nostdlib|nodefaultlibs|ffreestanding:-fno-stack-protector} "
++#else
++#define NO_SSP_SPEC ""
++#endif
++
+ #ifndef LINK_SSP_SPEC
+ #ifdef TARGET_LIBC_PROVIDES_SSP
+ #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+@@ -1280,7 +1286,7 @@ static const char *cc1_options =
+  %{-version:--version}\
+  %{-help=*:--help=%*}\
+  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}}\
+- %{fsyntax-only:-o %j} %{-param*}\
++ %{fsyntax-only:-o %j} %{-param*} " NO_SSP_SPEC "\
+  %{coverage:-fprofile-arcs -ftest-coverage}\
+  %{fprofile-arcs|fprofile-generate*|coverage:\
+    %{!fprofile-update=single:\

diff --git a/13.3.0/gentoo/05_all_alpha-mieee-default.patch b/13.3.0/gentoo/05_all_alpha-mieee-default.patch
new file mode 100644
index 0000000..fd1de71
--- /dev/null
+++ b/13.3.0/gentoo/05_all_alpha-mieee-default.patch
@@ -0,0 +1,39 @@
+Set the default behavior on alpha to use -mieee since the large majority of
+time we want this (bad/weird things can happen with packages built without
+it).
+
+To satisfy those people who may not want -mieee forced on them all the time,
+we also provide -mno-ieee.
+
+Patch by Mike Frysinger <vapier@gentoo.org>
+
+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/13.3.0/gentoo/06_all_ia64_note.GNU-stack.patch b/13.3.0/gentoo/06_all_ia64_note.GNU-stack.patch
new file mode 100644
index 0000000..7a1d4c6
--- /dev/null
+++ b/13.3.0/gentoo/06_all_ia64_note.GNU-stack.patch
@@ -0,0 +1,92 @@
+http://gcc.gnu.org/PR21098
+
+
+2004-09-20  Jakub Jelinek  <jakub@redhat.com>
+
+	* config/rs6000/ppc-asm.h: Add .note.GNU-stack section also
+	on ppc64-linux.
+
+	* config/ia64/lib1funcs.asm: Add .note.GNU-stack section on
+	ia64-linux.
+	* config/ia64/crtbegin.asm: Likewise.
+	* config/ia64/crtend.asm: Likewise.
+	* config/ia64/crti.asm: Likewise.
+	* config/ia64/crtn.asm: Likewise.
+
+2004-05-14  Jakub Jelinek  <jakub@redhat.com>
+
+	* config/ia64/linux.h (TARGET_ASM_FILE_END): Define.
+
+
+--- a/gcc/config/ia64/linux.h
++++ b/gcc/config/ia64/linux.h
+@@ -23,6 +23,8 @@ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ <http://www.gnu.org/licenses/>.  */
+ 
++#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
++
+ /* This is for -profile to use -lc_p instead of -lc.  */
+ #undef CC1_SPEC
+ #define CC1_SPEC "%{profile:-p} %{G*}"
+--- a/gcc/config/rs6000/ppc-asm.h
++++ b/gcc/config/rs6000/ppc-asm.h
+@@ -384,7 +384,7 @@ GLUE(.L,name): \
+ #endif
+ #endif
+ 
+-#if defined __linux__ && !defined __powerpc64__
++#if defined __linux__
+ 	.section .note.GNU-stack
+ 	.previous
+ #endif
+--- a/libgcc/config/ia64/crtbegin.S
++++ b/libgcc/config/ia64/crtbegin.S
+@@ -185,3 +185,7 @@ __do_jv_register_classes:
+ .weak __cxa_finalize
+ #endif
+ .weak _Jv_RegisterClasses
++
++#ifdef __linux__
++.section .note.GNU-stack; .previous
++#endif
+--- a/libgcc/config/ia64/crtend.S
++++ b/libgcc/config/ia64/crtend.S
+@@ -114,3 +114,6 @@ __do_global_ctors_aux:
+ 
+ 	br.ret.sptk.many rp
+ 	.endp __do_global_ctors_aux
++#ifdef __linux__
++.section .note.GNU-stack; .previous
++#endif
+--- a/libgcc/config/ia64/crti.S
++++ b/libgcc/config/ia64/crti.S
+@@ -49,5 +49,8 @@ _fini:
+ 	.save rp, r33
+ 	mov	r33 = b0
+ 	.body
++#ifdef __linux__
++.section .note.GNU-stack; .previous
++#endif
+ 
+ # end of crti.S
+--- a/libgcc/config/ia64/crtn.S
++++ b/libgcc/config/ia64/crtn.S
+@@ -39,5 +39,8 @@
+ 	.restore sp
+ 	mov	r12 = r35
+ 	br.ret.sptk.many b0
++#ifdef __linux__
++.section .note.GNU-stack; .previous
++#endif
+ 
+ # end of crtn.S
+--- a/libgcc/config/ia64/lib1funcs.S
++++ b/libgcc/config/ia64/lib1funcs.S
+@@ -793,3 +793,6 @@ __floattitf:
+ 	.endp __floattitf
+ #endif
+ #endif
++#ifdef __linux__
++.section .note.GNU-stack; .previous
++#endif

diff --git a/13.3.0/gentoo/07_all_libiberty-asprintf.patch b/13.3.0/gentoo/07_all_libiberty-asprintf.patch
new file mode 100644
index 0000000..1ed2ba3
--- /dev/null
+++ b/13.3.0/gentoo/07_all_libiberty-asprintf.patch
@@ -0,0 +1,18 @@
+2008-07-25  Magnus Granberg  <zorry@ume.nu>
+
+	* include/libiberty.h (asprintf): Don't declare if defined as a macro
+
+--- a/include/libiberty.h
++++ b/include/libiberty.h
+@@ -652,8 +652,11 @@ extern void *bsearch_r (const void *, const void *,
+ /* Like sprintf but provides a pointer to malloc'd storage, which must
+    be freed by the caller.  */
+ 
++/* asprintf may be declared as a macro by glibc with __USE_FORTIFY_LEVEL.  */
++#ifndef asprintf
+ extern int asprintf (char **, const char *, ...) ATTRIBUTE_PRINTF_2;
+ #endif
++#endif
+ 
+ /* Like asprintf but allocates memory without fail. This works like
+    xmalloc.  */

diff --git a/13.3.0/gentoo/08_all_libiberty-pic.patch b/13.3.0/gentoo/08_all_libiberty-pic.patch
new file mode 100644
index 0000000..3f0bae1
--- /dev/null
+++ b/13.3.0/gentoo/08_all_libiberty-pic.patch
@@ -0,0 +1,10 @@
+--- a/libiberty/Makefile.in
++++ b/libiberty/Makefile.in
+@@ -265,6 +265,7 @@ $(TARGETLIB): $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS)
+ 	  $(AR) $(AR_FLAGS) $(TARGETLIB) \
+ 	    $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS); \
+ 	  $(RANLIB) $(TARGETLIB); \
++	  cp $(TARGETLIB) ../ ; \
+ 	  cd ..; \
+ 	else true; fi
+ 

diff --git a/13.3.0/gentoo/09_all_nopie-all-flags.patch b/13.3.0/gentoo/09_all_nopie-all-flags.patch
new file mode 100644
index 0000000..fe1cd80
--- /dev/null
+++ b/13.3.0/gentoo/09_all_nopie-all-flags.patch
@@ -0,0 +1,18 @@
+We need to pass NO_PIE_CFLAGS to ALL_* so gcc don't fail when
+we compile it with older gcc and pie.
+
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1054,10 +1054,10 @@ ALL_CXXFLAGS = $(T_CFLAGS) $(CFLAGS-$@)
+ ALL_CPPFLAGS = $(INCLUDES) $(CPPFLAGS)
+ 
+ # This is the variable to use when using $(COMPILER).
+-ALL_COMPILERFLAGS = $(ALL_CXXFLAGS)
++ALL_COMPILERFLAGS = $(NO_PIE_CFLAGS) $(ALL_CXXFLAGS)
+ 
+ # This is the variable to use when using $(LINKER).
+-ALL_LINKERFLAGS = $(ALL_CXXFLAGS)
++ALL_LINKERFLAGS = $(NO_PIE_CFLAGS) $(ALL_CXXFLAGS)
+ 
+ # Build and host support libraries.
+ 

diff --git a/13.3.0/gentoo/10_all_sh-drop-sysroot-suffix.patch b/13.3.0/gentoo/10_all_sh-drop-sysroot-suffix.patch
new file mode 100644
index 0000000..e778f81
--- /dev/null
+++ b/13.3.0/gentoo/10_all_sh-drop-sysroot-suffix.patch
@@ -0,0 +1,26 @@
+From 5eeeff19bb4978a8d3c0d53bc81744bc25d82993 Mon Sep 17 00:00:00 2001
+From: Sergei Trofimovich <slyfox@gentoo.org>
+Date: Sat, 14 Apr 2018 13:07:39 +0100
+Subject: [PATCH] gcc/config.gcc: sh-*: Disable sysroot-suffix (PR42947)
+
+sh-* is a multilib target. It is also one of 2 sysroot-prefix targets.
+Unfortunately two options do not mix well. Attempt to use default
+multilib flavour always prepends sysroot-prefix.
+
+Bug: https://bugs.gentoo.org/511548
+Bug: https://gcc.gnu.org/PR42947
+Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -3328,8 +3328,6 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
+ 	if test x${enable_incomplete_targets} = xyes ; then
+ 		tm_defines="$tm_defines SUPPORT_SH1=1 SUPPORT_SH2E=1 SUPPORT_SH4=1 SUPPORT_SH4_SINGLE=1 SUPPORT_SH2A=1 SUPPORT_SH2A_SINGLE=1"
+ 	fi
+-	tm_file="$tm_file ./sysroot-suffix.h"
+-	tmake_file="$tmake_file t-sysroot-suffix"
+ 	;;
+ sh-*-rtems*)
+ 	tmake_file="${tmake_file} sh/t-sh sh/t-rtems"
+-- 
+2.17.0
+

diff --git a/13.3.0/gentoo/11_all_ia64-TEXTREL.patch b/13.3.0/gentoo/11_all_ia64-TEXTREL.patch
new file mode 100644
index 0000000..f5d0a99
--- /dev/null
+++ b/13.3.0/gentoo/11_all_ia64-TEXTREL.patch
@@ -0,0 +1,22 @@
+Fix textrels on -rdynamic binaries:
+Bug: https://gcc.gnu.org/PR84553
+Bug: https://bugs.gentoo.org/566118
+--- a/gcc/config/ia64/ia64.cc
++++ b/gcc/config/ia64/ia64.cc
+@@ -10840,12 +10840,14 @@ ia64_hpux_reloc_rw_mask (void)
+ 
+ /* For others, relax this so that relocations to local data goes in
+    read-only segments, but we still cannot allow global relocations
+-   in read-only segments.  */
++   in read-only segments.  Except that use of -rdynamic at link time
++   may make any local data global, so we can't allow local data in
++   read-only segments either.  */
+ 
+ static int
+ ia64_reloc_rw_mask (void)
+ {
+-  return flag_pic ? 3 : 2;
++  return flag_pic ? 3 : 3;
+ }
+ 
+ /* Return the section to use for X.  The only special thing we do here

diff --git a/13.3.0/gentoo/14_all_respect-build-cxxflags.patch b/13.3.0/gentoo/14_all_respect-build-cxxflags.patch
new file mode 100644
index 0000000..1f9a774
--- /dev/null
+++ b/13.3.0/gentoo/14_all_respect-build-cxxflags.patch
@@ -0,0 +1,39 @@
+Pass CXXFLAGS as CXXFLAGS_FOR_BUILD to stage1.
+
+Fixes build failure when CXXFLAGS contains
+TARGET-specific flags.
+
+Tested on x86_64-pc-linux-gnu host as:
+    # CFLAGS='-O2 -mfpu=neon-vfpv4' CXXFLAGS='-O2 -mfpu=neon-vfpv4' \
+        armv7a-unknown-linux-gnueabihf-emerge -v1 sys-devel/gcc --quiet-build=n
+
+Fix by Peter Levine.
+https://bugs.gentoo.org/581406
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -176,6 +176,7 @@
+ # built for the build system to override those in BASE_FLAGS_TO_PASS.
+ EXTRA_BUILD_FLAGS = \
+ 	CFLAGS="$(CFLAGS_FOR_BUILD)" \
++	CXXFLAGS="$(CXXFLAGS_FOR_BUILD)" \
+ 	LDFLAGS="$(LDFLAGS_FOR_BUILD)"
+ 
+ # This is the list of directories to built for the host system.
+@@ -842,6 +843,7 @@
+ 	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ 	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+ 	"CXX_FOR_BUILD=$(CXX_FOR_BUILD)" \
++	"CXXFLAGS_FOR_BUILD=$(CXXFLAGS_FOR_BUILD)" \
+ 	"EXPECT=$(EXPECT)" \
+ 	"FLEX=$(FLEX)" \
+ 	"INSTALL=$(INSTALL)" \
+--- a/Makefile.tpl
++++ b/Makefile.tpl
+@@ -179,6 +179,7 @@
+ # built for the build system to override those in BASE_FLAGS_TO_PASS.
+ EXTRA_BUILD_FLAGS = \
+ 	CFLAGS="$(CFLAGS_FOR_BUILD)" \
++	CXXFLAGS="$(CXXFLAGS_FOR_BUILD)" \
+ 	LDFLAGS="$(LDFLAGS_FOR_BUILD)"
+ 
+ # This is the list of directories to built for the host system.

diff --git a/13.3.0/gentoo/15_all_DEF_GENTOO_GLIBCXX_ASSERTIONS.patch b/13.3.0/gentoo/15_all_DEF_GENTOO_GLIBCXX_ASSERTIONS.patch
new file mode 100644
index 0000000..2daf73b
--- /dev/null
+++ b/13.3.0/gentoo/15_all_DEF_GENTOO_GLIBCXX_ASSERTIONS.patch
@@ -0,0 +1,14 @@
+https://bugs.gentoo.org/876895
+--- a/gcc/c-family/c-cppbuiltin.cc
++++ b/gcc/c-family/c-cppbuiltin.cc
+@@ -957,6 +957,10 @@ c_cpp_builtins (cpp_reader *pfile)
+ 	  cpp_define (pfile, "__cpp_rtti=199711L");
+ 	}
+ 
++      #ifdef DEF_GENTOO_GLIBCXX_ASSERTIONS
++	  cpp_define (pfile, "_GLIBCXX_ASSERTIONS");
++      #endif
++
+       if (cxx_dialect >= cxx11)
+         cpp_define (pfile, "__GXX_EXPERIMENTAL_CXX0X__");
+ 

diff --git a/13.3.0/gentoo/20_all_libstdcxx-no-vtv.patch b/13.3.0/gentoo/20_all_libstdcxx-no-vtv.patch
new file mode 100644
index 0000000..2719e2d
--- /dev/null
+++ b/13.3.0/gentoo/20_all_libstdcxx-no-vtv.patch
@@ -0,0 +1,61 @@
+Final libstdc++.so should not contain rpath to make libvtv usable.
+It's up to final binaries to link against proper libvtv.
+
+Bug: https://bugs.gentoo.org/582524
+Bug: https://gcc.gnu.org/PR85884
+--- a/libstdc++-v3/src/Makefile.am
++++ b/libstdc++-v3/src/Makefile.am
+@@ -277,7 +277,6 @@ CXXLINK = \
+ 	$(LIBTOOL) --tag CXX \
+ 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ 	--mode=link $(CXX) \
+-	$(VTV_CXXLINKFLAGS) \
+ 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) \
+ 	$(LTLDFLAGS) $(LTLIBICONV) \
+ 	-o $@
+--- a/libstdc++-v3/src/Makefile.in
++++ b/libstdc++-v3/src/Makefile.in
+@@ -642,7 +642,6 @@ CXXLINK = \
+ 	$(LIBTOOL) --tag CXX \
+ 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ 	--mode=link $(CXX) \
+-	$(VTV_CXXLINKFLAGS) \
+ 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) \
+ 	$(LTLDFLAGS) $(LTLIBICONV) \
+ 	-o $@
+--- a/libstdc++-v3/src/c++11/Makefile.am
++++ b/libstdc++-v3/src/c++11/Makefile.am
+@@ -214,5 +214,4 @@ CXXLINK = \
+ 	$(LIBTOOL) --tag CXX --tag disable-shared \
+ 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ 	--mode=link $(CXX) \
+-	$(VTV_CXXLINKFLAGS) \
+ 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
+--- a/libstdc++-v3/src/c++11/Makefile.in
++++ b/libstdc++-v3/src/c++11/Makefile.in
+@@ -588,7 +588,6 @@ CXXLINK = \
+ 	$(LIBTOOL) --tag CXX --tag disable-shared \
+ 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ 	--mode=link $(CXX) \
+-	$(VTV_CXXLINKFLAGS) \
+ 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
+ 
+ all: all-am
+--- a/libstdc++-v3/src/c++98/Makefile.am
++++ b/libstdc++-v3/src/c++98/Makefile.am
+@@ -268,5 +268,4 @@ CXXLINK = \
+ 	$(LIBTOOL) --tag CXX --tag disable-shared \
+ 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ 	--mode=link $(CXX) \
+-	$(VTV_CXXLINKFLAGS) \
+ 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
+--- a/libstdc++-v3/src/c++98/Makefile.in
++++ b/libstdc++-v3/src/c++98/Makefile.in
+@@ -590,7 +590,6 @@ CXXLINK = \
+ 	$(LIBTOOL) --tag CXX --tag disable-shared \
+ 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ 	--mode=link $(CXX) \
+-	$(VTV_CXXLINKFLAGS) \
+ 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
+ 
+ all: all-am

diff --git a/13.3.0/gentoo/22_all_default_ssp-buffer-size.patch b/13.3.0/gentoo/22_all_default_ssp-buffer-size.patch
new file mode 100644
index 0000000..0e0dd42
--- /dev/null
+++ b/13.3.0/gentoo/22_all_default_ssp-buffer-size.patch
@@ -0,0 +1,14 @@
+Change the minimal SSP buffer size.
+
+https://bugs.gentoo.org/484714
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -1012,7 +1012,7 @@ Common Joined UInteger Var(param_ssa_name_def_chain_limit) Init(512) Param Optim
+ The maximum number of SSA_NAME assignments to follow in determining a value.
+ 
+ -param=ssp-buffer-size=
+-Common Joined UInteger Var(param_ssp_buffer_size) Init(8) IntegerRange(1, 65536) Param Optimization
++Common Joined UInteger Var(param_ssp_buffer_size) Init(4) IntegerRange(1, 65536) Param Optimization
+ The lower bound for a buffer to be considered for stack smashing protection.
+ 
+ -param=stack-clash-protection-guard-size=

diff --git a/13.3.0/gentoo/23_all_DEF_GENTOO_ZNOW-z-now.patch b/13.3.0/gentoo/23_all_DEF_GENTOO_ZNOW-z-now.patch
new file mode 100644
index 0000000..2ed7968
--- /dev/null
+++ b/13.3.0/gentoo/23_all_DEF_GENTOO_ZNOW-z-now.patch
@@ -0,0 +1,26 @@
+If requested we add -z now
+
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -1001,6 +1001,12 @@ proper position among the other output files.  */
+ #endif
+ #endif
+ 
++#ifdef DEF_GENTOO_ZNOW
++#define LINK_NOW_SPEC "%{!nonow:-z now} "
++#else
++#define LINK_NOW_SPEC ""
++#endif
++
+ #ifdef ENABLE_DEFAULT_PIE
+ #define PIE_SPEC		"!no-pie"
+ #define NO_FPIE1_SPEC		"fno-pie"
+@@ -1161,7 +1167,7 @@ proper position among the other output files.  */
+     %(linker) " \
+     LINK_PLUGIN_SPEC \
+    "%{flto|flto=*:%<fcompare-debug*} \
+-    %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \
++    %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC LINK_NOW_SPEC \
+    "%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \
+    "%X %{o*} %{e*} %{N} %{n} %{r}\
+     %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!r:%{!nostartfiles:%S}}} \

diff --git a/13.3.0/gentoo/24_all_DEF_GENTOO_SCP-fstack-clash-protection.patch b/13.3.0/gentoo/24_all_DEF_GENTOO_SCP-fstack-clash-protection.patch
new file mode 100644
index 0000000..b13215d
--- /dev/null
+++ b/13.3.0/gentoo/24_all_DEF_GENTOO_SCP-fstack-clash-protection.patch
@@ -0,0 +1,65 @@
+We add -fstack-clash-protection if requested
+
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2698,7 +2698,7 @@ Common Alias(fstack-check=, specific, no
+ Insert stack checking code into the program.  Same as -fstack-check=specific.
+ 
+ fstack-clash-protection
+-Common Var(flag_stack_clash_protection) Optimization
++Common Var(flag_stack_clash_protection) Optimization Init(-1)
+ Insert code to probe each page of stack space as it is allocated to protect
+ from stack-clash style attacks.
+ 
+--- a/gcc/defaults.h
++++ b/gcc/defaults.h
+@@ -1425,6 +1425,15 @@ see the files COPYING3 and COPYING.RUNTI
+ #define STACK_CHECK_MAX_VAR_SIZE (STACK_CHECK_MAX_FRAME_SIZE / 100)
+ #endif
+ 
++/* Default value for flag_clash_protector when flag_clash_protector is
++   initialized to -1.  */
++#ifdef DEF_GENTOO_SCP
++#define DEFAULT_FLAG_SCP 1
++#endif
++#ifndef DEFAULT_FLAG_SCP
++#define DEFAULT_FLAG_SCP 0
++#endif
++
+ /* By default, the C++ compiler will use function addresses in the
+    vtable entries.  Setting this nonzero tells the compiler to use
+    function descriptors instead.  The value of this macro says how
+--- a/gcc/toplev.cc
++++ b/gcc/toplev.cc
+@@ -1610,6 +1610,10 @@ process_options (void)
+ 
+   /* -fstack-clash-protection is not currently supported on targets
+      where the stack grows up.  */
++  if (flag_stack_clash_protection == -1)
++    {
++      flag_stack_clash_protection = DEFAULT_FLAG_SCP;
++    }
+   if (flag_stack_clash_protection && !STACK_GROWS_DOWNWARD)
+     {
+       warning_at (UNKNOWN_LOCATION, 0,
+
+--- a/libgcc/Makefile.in
++++ b/libgcc/Makefile.in
+@@ -246,7 +246,7 @@ endif
+ LIBGCC2_DEBUG_CFLAGS = -g
+ LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
+ 		 $(LIBGCC2_DEBUG_CFLAGS) -DIN_LIBGCC2 \
+-		 -fbuilding-libgcc -fno-stack-protector \
++		 -fbuilding-libgcc -fno-stack-protector -fno-stack-clash-protection \
+ 		 $(INHIBIT_LIBC_CFLAGS)
+ 
+ # Additional options to use when compiling libgcc2.a.
+@@ -302,7 +302,7 @@ INTERNAL_CFLAGS = $(CFLAGS) $(LIBGCC2_CF
+   $(NO_PIE_CFLAGS) -finhibit-size-directive -fno-inline -fno-exceptions \
+   -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
+   -fbuilding-libgcc -fno-stack-protector $(FORCE_EXPLICIT_EH_REGISTRY) \
+-  $(INHIBIT_LIBC_CFLAGS) $(USE_TM_CLONE_REGISTRY)
++  -fno-stack-clash-protection $(INHIBIT_LIBC_CFLAGS) $(USE_TM_CLONE_REGISTRY)
+ 
+ # Extra flags to use when compiling crt{begin,end}.o.
+ CRTSTUFF_T_CFLAGS =

diff --git a/13.3.0/gentoo/25_all_lto-intl-workaround-PR95194.patch b/13.3.0/gentoo/25_all_lto-intl-workaround-PR95194.patch
new file mode 100644
index 0000000..9613216
--- /dev/null
+++ b/13.3.0/gentoo/25_all_lto-intl-workaround-PR95194.patch
@@ -0,0 +1,20 @@
+Trick libintl not to use '_INTL_REDIRECT_ASM' mode as it's
+incompatible with LTO builds.
+
+glibc does not normally use libintl implementations and uses
+it's own primitives. But musl ond others do fall back to libintl.
+
+Reported-by: Andrew Savchenko
+Bug: https://bugs.gentoo.org/723370
+Bug: https://gcc.gnu.org/PR95194
+--- a/intl/libgnuintl.h
++++ b/intl/libgnuintl.h
+@@ -93,7 +93,7 @@ extern "C" {
+    If he doesn't, we choose the method.  A third possible method is
+    _INTL_REDIRECT_ASM, supported only by GCC.  */
+ #if !(defined _INTL_REDIRECT_INLINE || defined _INTL_REDIRECT_MACROS)
+-# if __GNUC__ >= 2 && !defined __APPLE_CC__ && (defined __STDC__ || defined __cplusplus)
++# if __GNUC__ >= 2 && !defined __APPLE_CC__ && (defined __STDC__ || defined __cplusplus) && USE_ASM_ALIASES_THAT_BREAK_LTO
+ #  define _INTL_REDIRECT_ASM
+ # else
+ #  ifdef __cplusplus

diff --git a/13.3.0/gentoo/26_all_enable-cet.patch b/13.3.0/gentoo/26_all_enable-cet.patch
new file mode 100644
index 0000000..b13abab
--- /dev/null
+++ b/13.3.0/gentoo/26_all_enable-cet.patch
@@ -0,0 +1,193 @@
+https://bugs.gentoo.org/822036
+https://salsa.debian.org/toolchain-team/gcc/-/blob/master/debian/patches/gcc-distro-specs.diff
+
+From: Sam James <sam@gentoo.org>
+Subject: [PATCH] Enable CET (-fcf-protection=full) by default
+
+Needs:
+- CET to be enabled for GCC
+- -DEXTRA_OPTIONS_CF to be passed during build (via toolchain.eclass).
+
+Only supported on amd64.
+--- a/gcc/cp/lang-specs.h
++++ b/gcc/cp/lang-specs.h
+@@ -51,7 +51,7 @@ along with GCC; see the file COPYING3.  If not see
+       " 	   %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
+       "  %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
+       "  %{fmodules-ts:-fmodule-header %{fpreprocessed:-fdirectives-only}}"
+-      "  %(cc1_options) %2"
++      "  %(cc1_options) %(default_flag_cf_spec) %2"
+       "  %{!fsyntax-only:"
+       "    %{!S:-o %g.s%V}"
+       "    %{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
+@@ -72,7 +72,7 @@ along with GCC; see the file COPYING3.  If not see
+       "  %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
+       "  %{fmodules-ts:-fmodule-header=system"
+       "    %{fpreprocessed:-fdirectives-only}}"
+-      "  %(cc1_options) %2"
++      "  %(cc1_options) %(default_flag_cf_spec) %2"
+       "  %{!fsyntax-only:"
+       "    %{!S:-o %g.s%V}"
+       "    %{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
+@@ -92,7 +92,7 @@ along with GCC; see the file COPYING3.  If not see
+       " 	   %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
+       "  %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
+       "  %{fmodules-ts:-fmodule-header=user %{fpreprocessed:-fdirectives-only}}"
+-      "  %(cc1_options) %2"
++      "  %(cc1_options) %(default_flag_cf_spec) %2"
+       "  %{!fsyntax-only:"
+       "    %{!S:-o %g.s%V}"
+       "    %{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
+@@ -107,7 +107,7 @@ along with GCC; see the file COPYING3.  If not see
+       "  cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed"
+       " 	   %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
+       "  %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
+-      "  %(cc1_options) %2"
++      "  %(cc1_options) %(default_flag_cf_spec) %2"
+       "  %{!fsyntax-only:"
+       "    %{fmodule-only:%{!S:-o %g.s%V}}"
+       "    %{!fmodule-only:%(invoke_as)}}"
+@@ -116,7 +116,7 @@ along with GCC; see the file COPYING3.  If not see
+   {".ii", "@c++-cpp-output", 0, 0, 0},
+   {"@c++-cpp-output",
+       "%{!E:%{!M:%{!MM:"
+-      "  cc1plus -fpreprocessed %i %(cc1_options) %2"
++      "  cc1plus -fpreprocessed %i %(cc1_options) %(default_flag_cf_spec) %2"
+       "  %{!fsyntax-only:"
+       "    %{fmodule-only:%{!S:-o %g.s%V}}"
+       "    %{!fmodule-only:%{!fmodule-header*:%(invoke_as)}}}"
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -994,6 +994,18 @@ proper position among the other output files.  */
+ #define LINK_NOW_SPEC ""
+ #endif
+ 
++/* Default value for flag_cf_protection when flag_cf_protection is
++   initialized to CF_FULL.
++
++   We use a new option (EXTRA_OPTIONS_CF) here to avoid turning
++   this on accidentally for other arches. */
++#ifdef EXTRA_OPTIONS_CF
++#define DEFAULT_FLAG_CF_SPEC " %{!m16:%{!m32:%{!fcf-protection*:%{!fno-cf-protection:-fcf-protection}}}}"
++#endif
++#ifndef DEFAULT_FLAG_CF_SPEC
++#define DEFAULT_FLAG_CF_SPEC ""
++#endif
++
+ #ifdef ENABLE_DEFAULT_PIE
+ #define PIE_SPEC		"!no-pie"
+ #define NO_FPIE1_SPEC		"fno-pie"
+@@ -1196,6 +1208,7 @@ static const char *cpp_spec = CPP_SPEC;
+ static const char *cc1_spec = CC1_SPEC OS_CC1_SPEC;
+ static const char *cc1plus_spec = CC1PLUS_SPEC;
+ static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
++static const char *default_flag_cf_spec = DEFAULT_FLAG_CF_SPEC;
+ static const char *link_ssp_spec = LINK_SSP_SPEC;
+ static const char *asm_spec = ASM_SPEC;
+ static const char *asm_final_spec = ASM_FINAL_SPEC;
+@@ -1254,7 +1267,7 @@ static const char *cpp_options =
+ "%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
+  %{f*} %{g*:%{%:debug-level-gt(0):%{g*}\
+  %{!fno-working-directory:-fworking-directory}}} %{O*}\
+- %{undef} %{save-temps*:-fpch-preprocess}";
++ %{undef} %{save-temps*:-fpch-preprocess} %(default_flag_cf_spec)";
+ 
+ /* Pass -d* flags, possibly modifying -dumpdir, -dumpbase et al.
+ 
+@@ -1448,9 +1461,9 @@ static const struct compiler default_compilers[] =
+       %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+ 	  %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+ 	    cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
+-	  %(cc1_options)}\
++	  %(cc1_options)%(default_flag_cf_spec)}\
+       %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
+-	  cc1 %(cpp_unique_options) %(cc1_options)}}}\
++	  cc1 %(cpp_unique_options) %(cc1_options) %(default_flag_cf_spec)}}}\
+       %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 1},
+   {"-",
+    "%{!E:%e-E or -x required when input is from standard input}\
+@@ -1475,7 +1488,7 @@ static const struct compiler default_compilers[] =
+ 					   %W{o*:--output-pch %*}}%V}}}}}}}", 0, 0, 0},
+   {".i", "@cpp-output", 0, 0, 0},
+   {"@cpp-output",
+-   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
++   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %(default_flag_cf_spec) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+   {".s", "@assembler", 0, 0, 0},
+   {"@assembler",
+    "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 0, 0},
+@@ -1707,6 +1720,7 @@ static struct spec_list static_specs[] =
+   INIT_STATIC_SPEC ("cc1_options",		&cc1_options),
+   INIT_STATIC_SPEC ("cc1plus",			&cc1plus_spec),
+   INIT_STATIC_SPEC ("link_gcc_c_sequence",	&link_gcc_c_sequence_spec),
++  INIT_STATIC_SPEC ("default_flag_cf_spec",     &default_flag_cf_spec),
+   INIT_STATIC_SPEC ("link_ssp",			&link_ssp_spec),
+   INIT_STATIC_SPEC ("endfile",			&endfile_spec),
+   INIT_STATIC_SPEC ("link",			&link_spec),
+--- a/gcc/objc/lang-specs.h
++++ b/gcc/objc/lang-specs.h
+@@ -29,9 +29,9 @@ along with GCC; see the file COPYING3.  If not see
+ 	%{traditional|traditional-cpp:\
+ %eGNU Objective C no longer supports traditional compilation}\
+ 	%{save-temps*|no-integrated-cpp:cc1obj -E %(cpp_options) -o %{save-temps*:%b.mi} %{!save-temps*:%g.mi} \n\
+-	    cc1obj -fpreprocessed %{save-temps*:%b.mi} %{!save-temps*:%g.mi} %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}\
++	    cc1obj -fpreprocessed %{save-temps*:%b.mi} %{!save-temps*:%g.mi} %(cc1_options) %(default_flag_cf_spec) %{print-objc-runtime-info} %{gen-decls}}\
+ 	%{!save-temps*:%{!no-integrated-cpp:\
+-	    cc1obj %(cpp_unique_options) %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}}\
++	    cc1obj %(cpp_unique_options) %(cc1_options) %(default_flag_cf_spec) %{print-objc-runtime-info} %{gen-decls}}}\
+         %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+   {"@objective-c-header",
+      "%{E|M|MM:cc1obj -E %{traditional|traditional-cpp:-traditional-cpp}\
+@@ -40,18 +40,18 @@ along with GCC; see the file COPYING3.  If not see
+ 	%{traditional|traditional-cpp:\
+ %eGNU Objective C no longer supports traditional compilation}\
+ 	%{save-temps*|no-integrated-cpp:cc1obj -E %(cpp_options) -o %{save-temps*:%b.mi} %{!save-temps*:%g.mi} \n\
+-	    cc1obj -fpreprocessed %b.mi %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\
++	    cc1obj -fpreprocessed %b.mi %(cc1_options) %(default_flag_cf_spec) %{print-objc-runtime-info} %{gen-decls}\
+                         -o %g.s %{!o*:--output-pch %i.gch}\
+                         %W{o*:--output-pch %*}%V}\
+ 	%{!save-temps*:%{!no-integrated-cpp:\
+-	    cc1obj %(cpp_unique_options) %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\
++	    cc1obj %(cpp_unique_options) %(cc1_options) %(default_flag_cf_spec) %{print-objc-runtime-info} %{gen-decls}\
+                         -o %g.s %{!o*:--output-pch %i.gch}\
+                         %W{o*:--output-pch %*}%V}}}}}", 0, 0, 0},
+   {".mi", "@objective-c-cpp-output", 0, 0, 0},
+   {"@objective-c-cpp-output",
+-     "%{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\
++     "%{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %(default_flag_cf_spec) %{print-objc-runtime-info} %{gen-decls}\
+ 			     %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+   {"@objc-cpp-output",
+       "%nobjc-cpp-output is deprecated; please use objective-c-cpp-output instead\n\
+-       %{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\
++       %{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %(default_flag_cf_spec) %{print-objc-runtime-info} %{gen-decls}\
+ 			     %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+--- a/gcc/objcp/lang-specs.h
++++ b/gcc/objcp/lang-specs.h
+@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3.  If not see
+ 		%(cpp_options) %2 -o %{save-temps*:%b.mii} %{!save-temps*:%g.mii} \n}\
+       cc1objplus %{save-temps*|no-integrated-cpp:-fpreprocessed %{save-temps*:%b.mii} %{!save-temps*:%g.mii}}\
+ 	      %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}\
+-	%(cc1_options) %2\
++	%(cc1_options) %(default_flag_cf_spec) %2\
+         -o %g.s %{!o*:--output-pch %i.gch} %W{o*:--output-pch %*}%V}}}",
+      CPLUSPLUS_CPP_SPEC, 0, 0},
+   {"@objective-c++",
+@@ -46,16 +46,16 @@ along with GCC; see the file COPYING3.  If not see
+ 		%(cpp_options) %2 -o %{save-temps*:%b.mii} %{!save-temps*:%g.mii} \n}\
+       cc1objplus %{save-temps*|no-integrated-cpp:-fpreprocessed %{save-temps*:%b.mii} %{!save-temps*:%g.mii}}\
+ 	      %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}\
+-	%(cc1_options) %2\
++	%(cc1_options) %(default_flag_cf_spec) %2\
+        %{!fsyntax-only:%(invoke_as)}}}}",
+      CPLUSPLUS_CPP_SPEC, 0, 0},
+   {".mii", "@objective-c++-cpp-output", 0, 0, 0},
+   {"@objective-c++-cpp-output",
+    "%{!M:%{!MM:%{!E:\
+-    cc1objplus -fpreprocessed %i %(cc1_options) %2\
++    cc1objplus -fpreprocessed %i %(cc1_options) %(default_flag_cf_spec) %2\
+     %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+   {"@objc++-cpp-output",
+    "%nobjc++-cpp-output is deprecated; please use objective-c++-cpp-output instead\n\
+     %{!M:%{!MM:%{!E:\
+-    cc1objplus -fpreprocessed %i %(cc1_options) %2\
++    cc1objplus -fpreprocessed %i %(cc1_options) %(default_flag_cf_spec) %2\
+     %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},

diff --git a/13.3.0/gentoo/28_all_drop_CFLAGS_sed.patch b/13.3.0/gentoo/28_all_drop_CFLAGS_sed.patch
new file mode 100644
index 0000000..764f34c
--- /dev/null
+++ b/13.3.0/gentoo/28_all_drop_CFLAGS_sed.patch
@@ -0,0 +1,35 @@
+https://bugs.gentoo.org/849722
+https://github.com/InBetweenNames/gentooLTO/issues/846
+https://github.com/vaeth/portage-bashrc-mv/issues/11
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -5388,13 +5388,6 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex
+ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+ 
+ 
+-# Remove the -O2: for historical reasons, unless bootstrapping we prefer
+-# optimizations to be activated explicitly by the toplevel.
+-case "$CC" in
+-  */prev-gcc/xgcc*) ;;
+-  *) CFLAGS=`echo "$CFLAGS " | sed -e "s/-Ofast[ 	]//" -e "s/-O[gs][ 	]//" -e "s/-O[0-9]*[ 	]//" `
+-     CXXFLAGS=`echo "$CXXFLAGS " | sed -e "s/-Ofast[ 	]//" -e "s/-O[gs][ 	]//" -e "s/-O[0-9]*[ 	]//" ` ;;
+-esac
+ 
+ 
+ 
+--- a/gcc/configure.ac
++++ b/gcc/configure.ac
+@@ -440,13 +440,6 @@ ACX_PROG_GDC([-I"$srcdir"/d])
+ # Do configure tests with the C++ compiler, since that's what we build with.
+ AC_LANG(C++)
+ 
+-# Remove the -O2: for historical reasons, unless bootstrapping we prefer
+-# optimizations to be activated explicitly by the toplevel.
+-case "$CC" in
+-  */prev-gcc/xgcc*) ;;
+-  *) CFLAGS=`echo "$CFLAGS " | sed -e "s/-Ofast[[ 	]]//" -e "s/-O[[gs]][[ 	]]//" -e "s/-O[[0-9]]*[[ 	]]//" `
+-     CXXFLAGS=`echo "$CXXFLAGS " | sed -e "s/-Ofast[[ 	]]//" -e "s/-O[[gs]][[ 	]]//" -e "s/-O[[0-9]]*[[ 	]]//" ` ;;
+-esac
+ AC_SUBST(CFLAGS)
+ AC_SUBST(CXXFLAGS)
+ AC_SUBST(GDCFLAGS)

diff --git a/13.3.0/gentoo/29_all_msgfmt-libstdc++-link.patch b/13.3.0/gentoo/29_all_msgfmt-libstdc++-link.patch
new file mode 100644
index 0000000..0d2f113
--- /dev/null
+++ b/13.3.0/gentoo/29_all_msgfmt-libstdc++-link.patch
@@ -0,0 +1,39 @@
+Ensure that msgfmt doesn't encounter problems during gcc bootstrapping.
+
+Solves error messages like the following:
+
+msgfmt: /var/tmp/portage/sys-devel/gcc-4.1.2/work/build/./gcc/libgcc_s.so.1: version `GCC_4.2.0' not found (required by /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/libstdc++.so.6)
+
+The libgcc_s.so used during build doesn't satisfy the needs of the
+libstdc++.so that msgfmt is linked against. On the other hand, msgfmt
+is used as a stand-alone application here, and what library it uses
+behind the scenes is of no concern to the gcc build process.
+Therefore, simply invoking it "as usual", i.e. without any special
+library path, will make it work as expected here.
+
+2011-09-19 Martin von Gagern
+
+References:
+https://bugs.gentoo.org/372377
+https://bugs.gentoo.org/295480
+https://bugs.gentoo.org/843119
+--- a/libstdc++-v3/po/Makefile.am
++++ b/libstdc++-v3/po/Makefile.am
+@@ -39,6 +39,7 @@ MSGFMT = msgfmt
+ EXTRA_DIST = string_literals.cc POTFILES.in $(PACKAGE).pot $(LOCALE_IN)
+ 
+ .po.mo:
++	env --unset=LD_LIBRARY_PATH \
+ 	$(MSGFMT) -o $@ $<
+ 
+ all-local: all-local-$(USE_NLS)
+--- a/libstdc++-v3/po/Makefile.in
++++ b/libstdc++-v3/po/Makefile.in
+@@ -419,6 +419,7 @@ uninstall-am: uninstall-info-am
+ 
+ 
+ .po.mo:
++	env --unset=LD_LIBRARY_PATH \
+ 	$(MSGFMT) -o $@ $<
+ 
+ all-local: all-local-$(USE_NLS)

diff --git a/13.3.0/gentoo/30_all_tar_libstdc++-link.patch b/13.3.0/gentoo/30_all_tar_libstdc++-link.patch
new file mode 100644
index 0000000..adb414a
--- /dev/null
+++ b/13.3.0/gentoo/30_all_tar_libstdc++-link.patch
@@ -0,0 +1,57 @@
+From eae11e896edef4199a128bf6720b5bd4e5edc2f9 Mon Sep 17 00:00:00 2001
+From: Sam James <sam@gentoo.org>
+Date: Sat, 17 Dec 2022 02:42:59 +0000
+Subject: [PATCH] Fix calling libarchive's tar
+
+https://bugs.gentoo.org/886447
+
+Very similar to 33_all_msgfmt-libstdc++-link.patch, whose description is:
+"""
+Ensure that msgfmt doesn't encounter problems during gcc bootstrapping.
+
+Solves error messages like the following:
+
+msgfmt: /var/tmp/portage/sys-devel/gcc-4.1.2/work/build/./gcc/libgcc_s.so.1: version `GCC_4.2.0' not found (required by /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/libstdc++.so.6)
+
+The libgcc_s.so used during build doesn't satisfy the needs of the
+libstdc++.so that msgfmt is linked against. On the other hand, msgfmt
+is used as a stand-alone application here, and what library it uses
+behind the scenes is of no concern to the gcc build process.
+Therefore, simply invoking it "as usual", i.e. without any special
+library path, will make it work as expected here.
+
+2011-09-19 Martin von Gagern
+
+References:
+https://bugs.gentoo.org/372377
+https://bugs.gentoo.org/295480
+https://bugs.gentoo.org/843119
+"""
+
+Signed-off-by: Sam James <sam@gentoo.org>
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -3955,10 +3955,10 @@ install-headers-tar: stmp-int-hdrs install-include-dir
+ # Unless a full pathname is provided, some shells would print the new CWD,
+ # found in CDPATH, corrupting the output.  We could just redirect the
+ # output of `cd', but some shells lose on redirection within `()'s
+-	(cd `${PWD_COMMAND}`/include ; \
+-	 tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include; tar xpf - )
+-	(cd `${PWD_COMMAND}`/include-fixed ; \
+-	 tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include-fixed; tar xpf - )
++	(unset LD_LIBRARY_PATH ; cd `${PWD_COMMAND}`/include ; \
++	 tar -cf - .; exit 0) | (unset LD_LIBRARY_PATH ; cd $(DESTDIR)$(libsubdir)/include; tar xpf - )
++	(unset LD_LIBRARY_PATH ; cd `${PWD_COMMAND}`/include-fixed ; \
++	 tar -cf - .; exit 0) | (unset LD_LIBRARY_PATH ; cd $(DESTDIR)$(libsubdir)/include-fixed; tar xpf - )
+ # /bin/sh on some systems returns the status of the first tar,
+ # and that can lose with GNU tar which always writes a full block.
+ # So use `exit 0' to ignore its exit status.
+@@ -3979,7 +3979,7 @@ install-headers-cp: stmp-int-hdrs install-include-dir
+ # Targets without dependencies, for use in prev-gcc during bootstrap.
+ real-install-headers-tar:
+ 	(cd `${PWD_COMMAND}`/include-fixed ; \
+-	 tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include-fixed; tar xpf - )
++	 unset LD_LIBRARY_PATH; tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include-fixed; unset LD_LIBRARY_PATH; tar xpf - )
+ 
+ real-install-headers-cpio:
+ 	cd `${PWD_COMMAND}`/include-fixed ; \

diff --git a/13.3.0/gentoo/31_all_gm2_make_P_var.patch b/13.3.0/gentoo/31_all_gm2_make_P_var.patch
new file mode 100644
index 0000000..74b3925
--- /dev/null
+++ b/13.3.0/gentoo/31_all_gm2_make_P_var.patch
@@ -0,0 +1,49 @@
+https://bugs.gentoo.org/904714
+https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=79c73122fab213f218b85b2c579ffe3cf5e98ad0
+
+From 275c516a40b7044895c4920f52ec19c7bceedd54 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= <arsen@aarsen.me>
+Date: Fri, 21 Apr 2023 18:07:29 +0200
+Subject: [PATCH] gcc/m2: Drop references to $(P)
+
+$(P) seems to have been a workaround for some old, proprietary make
+implementations that we no longer support.  It was removed in
+r0-31149-gb8dad04b688e9c.
+
+gcc/m2/ChangeLog:
+
+       * Make-lang.in: Remove references to $(P).
+       * Make-maintainer.in: Ditto.
+
+(cherry picked from commit 79c73122fab213f218b85b2c579ffe3cf5e98ad0)
+--- a/gcc/m2/Make-lang.in
++++ b/gcc/m2/Make-lang.in
+@@ -532,7 +532,7 @@ m2_OBJS = $(GM2_C_OBJS) m2/gm2-gcc/rtegraph.o \
+ cc1gm2$(exeext): m2/stage1/cc1gm2$(exeext) $(m2.prev)
+ 	cp -p $< $@
+ 
+-m2/stage2/cc1gm2$(exeext): m2/stage1/cc1gm2$(exeext) m2/gm2-compiler/m2flex.o $(P) \
++m2/stage2/cc1gm2$(exeext): m2/stage1/cc1gm2$(exeext) m2/gm2-compiler/m2flex.o \
+                             $(GM2_C_OBJS) $(BACKEND) $(LIBDEPS) $(GM2_LIBS) \
+                             m2/gm2-gcc/rtegraph.o $(M2RTE_PLUGIN_SO)
+ 	-test -d $(@D) || $(mkinstalldirs) $(@D)
+@@ -545,7 +545,7 @@ m2/stage2/cc1gm2$(exeext): m2/stage1/cc1gm2$(exeext) m2/gm2-compiler/m2flex.o $(
+ 	@$(call LINK_PROGRESS,$(INDEX.m2),end)
+ 
+ m2/stage1/cc1gm2$(exeext): gm2$(exeext) m2/gm2-compiler-boot/m2flex.o \
+-                            $(P) $(GM2_C_OBJS) $(BACKEND) $(LIBDEPS) \
++                            $(GM2_C_OBJS) $(BACKEND) $(LIBDEPS) \
+                             $(GM2_LIBS_BOOT) $(MC_LIBS) \
+                             m2/gm2-gcc/rtegraph.o $(M2RTE_PLUGIN_SO) \
+                             $(m2.prev)
+--- a/gcc/m2/Make-maintainer.in
++++ b/gcc/m2/Make-maintainer.in
+@@ -852,7 +852,7 @@ GM2_LIBS_PARANOID = m2/gm2-compiler-paranoid/gm2.a \
+ gm2.paranoid: m2/m2obj3/cc1gm2$(exeext) gm2.verifyparanoid
+ 
+ m2/m2obj3/cc1gm2$(exeext): m2/m2obj2/cc1gm2$(exeext) m2/gm2-compiler-paranoid/m2flex.o \
+-                            $(P) $(GM2_C_OBJS) $(BACKEND) $(LIBDEPS) $(GM2_LIBS_PARANOID) \
++                            $(GM2_C_OBJS) $(BACKEND) $(LIBDEPS) $(GM2_LIBS_PARANOID) \
+                             m2/gm2-gcc/rtegraph.o plugin/m2rte$(exeext).so
+ 	-test -d m2/m2obj3 || $(mkinstalldirs) m2/m2obj3
+ 	@$(call LINK_PROGRESS,$(INDEX.m2),start)

diff --git a/13.3.0/gentoo/76_all_match.pd-don-t-emit-label-if-not-needed.patch b/13.3.0/gentoo/76_all_match.pd-don-t-emit-label-if-not-needed.patch
new file mode 100644
index 0000000..95da940
--- /dev/null
+++ b/13.3.0/gentoo/76_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 <tamar.christina@arm.com>
+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 <expr *> (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/13.3.0/gentoo/77_all_match.pd-Remove-commented-out-line-pragmas-unless-vv.patch b/13.3.0/gentoo/77_all_match.pd-Remove-commented-out-line-pragmas-unless-vv.patch
new file mode 100644
index 0000000..ea61987
--- /dev/null
+++ b/13.3.0/gentoo/77_all_match.pd-Remove-commented-out-line-pragmas-unless-vv.patch
@@ -0,0 +1,41 @@
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21
+
+From 2be19327b38b4e3e183d47529871614a3ef0c3ad Mon Sep 17 00:00:00 2001
+From: Tamar Christina <tamar.christina@arm.com>
+Date: Fri, 5 May 2023 13:36:01 +0100
+Subject: [PATCH 02/15] match.pd: Remove commented out line pragmas unless -vv
+ is used.
+
+genmatch currently outputs commented out line directives that have no effect
+but the compiler still has to parse only to discard.
+
+They are however handy when debugging genmatch output.  As such this moves them
+behind the -vv flag.
+
+gcc/ChangeLog:
+
+	PR bootstrap/84402
+	* genmatch.cc (output_line_directive): Only emit commented directive
+	when -vv.
+
+(cherry picked from commit e487fcc0f7466ea663a0fea52076337bebd42b8b)
+---
+ gcc/genmatch.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
+index 9ecd0a462b4f..45e49c790b6d 100644
+--- a/gcc/genmatch.cc
++++ b/gcc/genmatch.cc
+@@ -209,7 +209,7 @@ output_line_directive (FILE *f, location_t location,
+       else
+ 	fprintf (f, "%s:%d", file, loc.line);
+     }
+-  else
++  else if (verbose >= 2)
+     /* Other gen programs really output line directives here, at least for
+        development it's right now more convenient to have line information
+        from the generated file.  Still keep the directives as comment for now
+-- 
+2.44.0
+

diff --git a/13.3.0/gentoo/78_all_match.pd-CSE-the-dump-output-check.patch b/13.3.0/gentoo/78_all_match.pd-CSE-the-dump-output-check.patch
new file mode 100644
index 0000000..e084c4c
--- /dev/null
+++ b/13.3.0/gentoo/78_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 <tamar.christina@arm.com>
+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/13.3.0/gentoo/79_all_genmatch-split-shared-code-to-gimple-match-exports.c.patch b/13.3.0/gentoo/79_all_genmatch-split-shared-code-to-gimple-match-exports.c.patch
new file mode 100644
index 0000000..1f7769f
--- /dev/null
+++ b/13.3.0/gentoo/79_all_genmatch-split-shared-code-to-gimple-match-exports.c.patch
@@ -0,0 +1,2560 @@
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21
+
+From 49ed8cead428b48bf46afbbb37a4d043d00702d6 Mon Sep 17 00:00:00 2001
+From: Tamar Christina <tamar.christina@arm.com>
+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
+ 
+@@ -1308,6 +1309,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 \
+@@ -2659,7 +2661,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
++<http://www.gnu.org/licenses/>.  */
++
++#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<typename ValueizeOp, typename ValueizeCondition>
++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<typename ValueizeOp, typename ValueizeCondition>
+-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
+

diff --git a/13.3.0/gentoo/80_all_match.pd-automatically-partition-match.cc-files.patch b/13.3.0/gentoo/80_all_match.pd-automatically-partition-match.cc-files.patch
new file mode 100644
index 0000000..6405bf8
--- /dev/null
+++ b/13.3.0/gentoo/80_all_match.pd-automatically-partition-match.cc-files.patch
@@ -0,0 +1,524 @@
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21
+
+From daac5d2f67656dcf8cc2bbff1c6eaa34f3fb55b9 Mon Sep 17 00:00:00 2001
+From: Tamar Christina <tamar.christina@arm.com>
+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 <FILE *> &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 <FILE *> &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 <FILE *> &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 <expr *>(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 <operator_id *> (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 <fn_id *> (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=<filename>] [--include=<filename>] [-v[v]] input "
++		   "[<outputfile>...]\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 <char *> 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 <FILE *> 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
+

diff --git a/13.3.0/gentoo/81_all_match.pd-Use-splits-in-makefile-and-make-configurabl.patch b/13.3.0/gentoo/81_all_match.pd-Use-splits-in-makefile-and-make-configurabl.patch
new file mode 100644
index 0000000..f525f63
--- /dev/null
+++ b/13.3.0/gentoo/81_all_match.pd-Use-splits-in-makefile-and-make-configurabl.patch
@@ -0,0 +1,276 @@
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109927#c21
+
+From dcfebe060ee266f364bb60f1cdf0cec58818c4f7 Mon Sep 17 00:00:00 2001
+From: Tamar Christina <tamar.christina@arm.com>
+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
+@@ -1308,9 +1315,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 \
+@@ -1803,7 +1810,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 \
+@@ -2418,7 +2426,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
+@@ -2661,19 +2670,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) \
+@@ -2808,7 +2834,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
+

diff --git a/13.3.0/gentoo/82_all_Makefile.in-clean-up-match.pd-related-dependencies.patch b/13.3.0/gentoo/82_all_Makefile.in-clean-up-match.pd-related-dependencies.patch
new file mode 100644
index 0000000..2512660
--- /dev/null
+++ b/13.3.0/gentoo/82_all_Makefile.in-clean-up-match.pd-related-dependencies.patch
@@ -0,0 +1,60 @@
+From 2c1f550db00c7dd9abede5644a3acd915767e0ad Mon Sep 17 00:00:00 2001
+From: Alexander Monakov <amonakov@ispras.ru>
+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
+ 
+@@ -2670,12 +2669,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
+

diff --git a/13.3.0/gentoo/86_all_build-Replace-seq-for-portability-with-GNU-Make-vari.patch b/13.3.0/gentoo/86_all_build-Replace-seq-for-portability-with-GNU-Make-vari.patch
new file mode 100644
index 0000000..892adbc
--- /dev/null
+++ b/13.3.0/gentoo/86_all_build-Replace-seq-for-portability-with-GNU-Make-vari.patch
@@ -0,0 +1,73 @@
+https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=319aef8d2fde32be5cfed99f321c7f90e33d1f1d
+
+From a18a994030d16f58ebced231e778ec4e06a98abb Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek <jakub@redhat.com>
+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  <jakub@redhat.com>
+
+	* 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))
+@@ -4220,18 +4230,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
+

diff --git a/13.3.0/gentoo/87_all_Remove-DEFAULT_MATCHPD_PARTITIONS-macro.patch b/13.3.0/gentoo/87_all_Remove-DEFAULT_MATCHPD_PARTITIONS-macro.patch
new file mode 100644
index 0000000..1f47154
--- /dev/null
+++ b/13.3.0/gentoo/87_all_Remove-DEFAULT_MATCHPD_PARTITIONS-macro.patch
@@ -0,0 +1,90 @@
+https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=bc45e18d433f879a02e369d027829f90f9e85724
+
+From b60091fe7d22e0cac71461dceeb804e37555b5d3 Mon Sep 17 00:00:00 2001
+From: Tamar Christina <tamar.christina@arm.com>
+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
+

diff --git a/13.3.0/gentoo/88_all_Makefile.in-Make-TM_P_H-depend-on-TREE_H-PR111021.patch b/13.3.0/gentoo/88_all_Makefile.in-Make-TM_P_H-depend-on-TREE_H-PR111021.patch
new file mode 100644
index 0000000..0a92592
--- /dev/null
+++ b/13.3.0/gentoo/88_all_Makefile.in-Make-TM_P_H-depend-on-TREE_H-PR111021.patch
@@ -0,0 +1,66 @@
+https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=8353b9c5f5af0e65cb04fcbb7325d6a566006cd4
+
+From 87192b63d3ab56543461cb456c4f8b2f1085fd6c Mon Sep 17 00:00:00 2001
+From: Kewen Lin <linkw@linux.ibm.com>
+Date: Fri, 18 Aug 2023 05:03:40 -0500
+Subject: [PATCH 11/15] Makefile.in: Make TM_P_H depend on $(TREE_H) [PR111021]
+
+As PR111021 shows, the below ${port}-protos.h include tree.h
+for code_helper and tree_code:
+
+  arm/arm-protos.h:#include "tree.h"
+  cris/cris-protos.h:#include "tree.h" (H-P removed this in r14-3218)
+  microblaze/microblaze-protos.h:#include "tree.h"
+  rl78/rl78-protos.h:#include "tree.h"
+  stormy16/stormy16-protos.h:#include "tree.h"
+
+, when compiling build/gencondmd.cc, the include hierarchy
+makes it depend on tm_p.h -> ${port}-protos.h -> tree.h,
+which further includes (depends on) some files that are
+generated during the building, such as: all-tree.def,
+tree-check.h and so on.  The previous commit r14-3215
+should already force build/gencondmd.cc to depend on
+${TREE_H}, so the reported build failure should be gone.
+
+But for a long term maintenance, especially one day some
+build/xxx.cc requires tm_p.h but not recog.h, the ${TREE_H}
+dependence could be missed and a build failure will show
+up.  So this patch is to make TM_P_H depend on $(TREE_H),
+any new build/xxx.cc depending on tm_p.h will be able to
+consider ${TREE_H}.
+
+It's tested with cross-builds for the affected ports with
+steps:
+ 1) dropped the fix r14-3215;
+ 2) reproduced the build failure with serial build;
+ 3) applied this patch, serial built and verified all passed;
+ 4) added back r14-3215, serial built and verified all passed;
+
+	PR bootstrap/111021
+
+gcc/ChangeLog:
+
+	* Makefile.in (TM_P_H): Add $(TREE_H) as dependence.
+
+(cherry picked from commit 8353b9c5f5af0e65cb04fcbb7325d6a566006cd4)
+---
+ gcc/Makefile.in | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 975fbb61ea8a..115d2a6d9b76 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -886,7 +886,8 @@ OPTIONS_C_EXTRA = $(PRETTY_PRINT_H)
+ BCONFIG_H = bconfig.h $(build_xm_file_list)
+ CONFIG_H  = config.h  $(host_xm_file_list)
+ TCONFIG_H = tconfig.h $(xm_file_list)
+-TM_P_H    = tm_p.h    $(tm_p_file_list)
++# Some $(target)-protos.h depends on tree.h
++TM_P_H    = tm_p.h    $(tm_p_file_list) $(TREE_H)
+ TM_D_H    = tm_d.h    $(tm_d_file_list)
+ GTM_H     = tm.h      $(tm_file_list) insn-constants.h
+ TM_H      = $(GTM_H) insn-flags.h $(OPTIONS_H)
+-- 
+2.44.0
+

diff --git a/13.3.0/gentoo/89_all_Makefile.in-Make-recog.h-depend-on-TREE_H-PR111021.patch b/13.3.0/gentoo/89_all_Makefile.in-Make-recog.h-depend-on-TREE_H-PR111021.patch
new file mode 100644
index 0000000..e0c84ae
--- /dev/null
+++ b/13.3.0/gentoo/89_all_Makefile.in-Make-recog.h-depend-on-TREE_H-PR111021.patch
@@ -0,0 +1,45 @@
+https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=ecb95399f43873e1f34119ac260bbea2ef358e53
+
+From 45b0ac72b82e483ac2b8380ce08cedcfd021afb0 Mon Sep 17 00:00:00 2001
+From: Kewen Lin <linkw@linux.ibm.com>
+Date: Tue, 15 Aug 2023 03:01:20 -0500
+Subject: [PATCH 12/15] Makefile.in: Make recog.h depend on $(TREE_H)
+ [PR111021]
+
+Commit r14-3093 introduced a random build failure on
+build/gencondmd.cc building.  Since r14-3093 make recog.h
+include tree.h, which further includes (depends on) some
+files that are generated during the building, such as:
+all-tree.def, tree-check.h etc, when building file
+build/gencondmd.cc, the build can fail if these dependences
+are not ready.  So this patch is to teach this dependence.
+
+Thank Jan-Benedict Glaw for testing this!
+
+	PR bootstrap/111021
+
+gcc/ChangeLog:
+
+	* Makefile.in (RECOG_H): Add $(TREE_H) as dependence.
+
+(cherry picked from commit ecb95399f43873e1f34119ac260bbea2ef358e53)
+---
+ gcc/Makefile.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 115d2a6d9b76..2c16b14ad0f3 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -985,7 +985,7 @@ GIMPLE_H = gimple.h gimple.def gsstruct.def $(VEC_H) \
+ 	$(GGC_H) $(BASIC_BLOCK_H) $(TREE_H) tree-ssa-operands.h \
+ 	tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H) is-a.h
+ GCOV_IO_H = gcov-io.h version.h auto-host.h gcov-counter.def
+-RECOG_H = recog.h
++RECOG_H = recog.h $(TREE_H)
+ EMIT_RTL_H = emit-rtl.h
+ FLAGS_H = flags.h flag-types.h $(OPTIONS_H)
+ OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
+-- 
+2.44.0
+

diff --git a/13.3.0/gentoo/90_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.patch b/13.3.0/gentoo/90_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.patch
new file mode 100644
index 0000000..f6ded53
--- /dev/null
+++ b/13.3.0/gentoo/90_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.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 <rdapp.gcc@gmail.com>
+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 <rdapp@ventanamicro.com>
+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
+@@ -1331,7 +1338,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 \
+@@ -1817,7 +1824,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) \
+@@ -2434,11 +2442,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
+@@ -2461,7 +2469,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
+ 
+@@ -2490,8 +2498,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 <X>_optab if that optab isn't allowed to fail.  */
+ static bool nofail_optabs[NUM_OPTABS];
+ \f
+ 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");
+ }
+ \f
+ /* 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);
+ }
+ \f
+ /* 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");
+ }
+ \f
+ /* 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");
+ }
+ \f
+ /* 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<N>" 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<N>".  */
+ 
+ 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<const char *, 10> 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);
+ }
+ \f
++/* 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;
++}
++\f
+ /* 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/13.3.0/gentoo/91_all_riscv_PR106271-multilib-bootstrap.patch b/13.3.0/gentoo/91_all_riscv_PR106271-multilib-bootstrap.patch
new file mode 100644
index 0000000..2d2933f
--- /dev/null
+++ b/13.3.0/gentoo/91_all_riscv_PR106271-multilib-bootstrap.patch
@@ -0,0 +1,37 @@
+https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=47f95bc4be4eb14730ab3eaaaf8f6e71fda47690
+https://gcc.gnu.org/PR106271
+https://bugs.gentoo.org/890636
+
+From 976280d3fbfc5c1315befb36cebf07a6f1f0c518 Mon Sep 17 00:00:00 2001
+From: Raphael Moreira Zinsly <rzinsly@ventanamicro.com>
+Date: Tue, 22 Aug 2023 11:37:04 -0600
+Subject: [PATCH] RISC-V: Add multiarch support on riscv-linux-gnu
+
+This adds multiarch support to the RISC-V port so that bootstraps work with
+Debian out-of-the-box.  Without this patch the stage1 compiler is unable to
+find headers/libraries when building the stage1 runtime.
+
+This is functionally (and possibly textually) equivalent to Debian's fix for
+the same problem.
+
+gcc/
+	* config/riscv/t-linux: Add MULTIARCH_DIRNAME.
+
+(cherry picked from commit 47f95bc4be4eb14730ab3eaaaf8f6e71fda47690)
+---
+ gcc/config/riscv/t-linux | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/gcc/config/riscv/t-linux b/gcc/config/riscv/t-linux
+index 216d2776a183..a6f64f88d25c 100644
+--- a/gcc/config/riscv/t-linux
++++ b/gcc/config/riscv/t-linux
+@@ -1,3 +1,5 @@
+ # Only XLEN and ABI affect Linux multilib dir names, e.g. /lib32/ilp32d/
+ MULTILIB_DIRNAMES := $(patsubst rv32%,lib32,$(patsubst rv64%,lib64,$(MULTILIB_DIRNAMES)))
+ MULTILIB_OSDIRNAMES := $(patsubst lib%,../lib%,$(MULTILIB_DIRNAMES))
++
++MULTIARCH_DIRNAME := $(call if_multiarch,$(firstword $(subst -, ,$(target)))-linux-gnu)
+-- 
+2.44.0
+

diff --git a/13.3.0/gentoo/92_all_riscv_PR109760-gstreamer.patch b/13.3.0/gentoo/92_all_riscv_PR109760-gstreamer.patch
new file mode 100644
index 0000000..ef79d70
--- /dev/null
+++ b/13.3.0/gentoo/92_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 <lidie@eswincomputing.com>
+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 <gaofei@eswincomputing.com>
+Signed-off-by: Die Li <lidie@eswincomputing.com>
+
+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
+@@ -3488,7 +3488,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))
+@@ -3497,7 +3497,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/13.3.0/gentoo/93_all_PR115917-ada-lto.patch b/13.3.0/gentoo/93_all_PR115917-ada-lto.patch
new file mode 100644
index 0000000..023c0d1
--- /dev/null
+++ b/13.3.0/gentoo/93_all_PR115917-ada-lto.patch
@@ -0,0 +1,52 @@
+From f55ac7e8ceabaf54ba9fc3ca4393abeae2ee1c19 Mon Sep 17 00:00:00 2001
+Message-ID: <f55ac7e8ceabaf54ba9fc3ca4393abeae2ee1c19.1727635911.git.sam@gentoo.org>
+From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= <arsen@aarsen.me>
+Date: Thu, 15 Aug 2024 19:17:41 +0200
+Subject: [PATCH] gnat: fix lto-type-mismatch between C_Version_String and
+ gnat_version_string [PR115917]
+
+gcc/ada/ChangeLog:
+
+	PR ada/115917
+	* gnatvsn.ads: Add note about the duplication of this value in
+	version.c.
+	* version.c (VER_LEN_MAX): Define to the same value as
+	Gnatvsn.Ver_Len_Max.
+	(gnat_version_string): Use VER_LEN_MAX as bound.
+
+(cherry picked from commit 9cbcf8d1de159e6113fafb5dc2feb4a7e467a302)
+---
+ gcc/ada/gnatvsn.ads | 3 ++-
+ gcc/ada/version.c   | 5 ++++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/ada/gnatvsn.ads b/gcc/ada/gnatvsn.ads
+index b6edc9dabed9..308986afc182 100644
+--- a/gcc/ada/gnatvsn.ads
++++ b/gcc/ada/gnatvsn.ads
+@@ -83,7 +83,8 @@ package Gnatvsn is
+    --  space to store any possible version string value for checks. This
+    --  value should never be decreased in the future, but it would be
+    --  OK to increase it if absolutely necessary. If it is increased,
+-   --  be sure to increase GNAT.Compiler.Version.Ver_Len_Max as well.
++   --  be sure to increase GNAT.Compiler.Version.Ver_Len_Max, and to update
++   --  the VER_LEN_MAX define in version.c as well.
+ 
+    Ver_Prefix : constant String := "GNAT Version: ";
+    --  Prefix generated by binder. If it is changed, be sure to change
+diff --git a/gcc/ada/version.c b/gcc/ada/version.c
+index 5e64edd0b17d..2fa9b8c2c859 100644
+--- a/gcc/ada/version.c
++++ b/gcc/ada/version.c
+@@ -31,4 +31,7 @@
+ 
+ #include "version.h"
+ 
+-char gnat_version_string[] = version_string;
++/* Logically a reference to Gnatvsn.Ver_Len_Max.  Please keep in sync.  */
++#define VER_LEN_MAX 256
++
++char gnat_version_string[VER_LEN_MAX] = version_string;
+-- 
+2.46.2
+

diff --git a/13.3.0/gentoo/README.history b/13.3.0/gentoo/README.history
new file mode 100644
index 0000000..a1120c2
--- /dev/null
+++ b/13.3.0/gentoo/README.history
@@ -0,0 +1,40 @@
+1	29 Sept 2024
+
+	+ 01_all_default-fortify-source.patch
+	+ 02_all_default-warn-format-security.patch
+	+ 03_all_default-warn-trampolines.patch
+	+ 04_all_nossp-on-nostdlib.patch
+	+ 05_all_alpha-mieee-default.patch
+	+ 06_all_ia64_note.GNU-stack.patch
+	+ 07_all_libiberty-asprintf.patch
+	+ 08_all_libiberty-pic.patch
+	+ 09_all_nopie-all-flags.patch
+	+ 10_all_sh-drop-sysroot-suffix.patch
+	+ 11_all_ia64-TEXTREL.patch
+	+ 14_all_respect-build-cxxflags.patch
+	+ 15_all_DEF_GENTOO_GLIBCXX_ASSERTIONS.patch
+	+ 20_all_libstdcxx-no-vtv.patch
+	+ 22_all_default_ssp-buffer-size.patch
+	+ 23_all_DEF_GENTOO_ZNOW-z-now.patch
+	+ 24_all_DEF_GENTOO_SCP-fstack-clash-protection.patch
+	+ 25_all_lto-intl-workaround-PR95194.patch
+	+ 26_all_enable-cet.patch
+	+ 28_all_drop_CFLAGS_sed.patch
+	+ 29_all_msgfmt-libstdc++-link.patch
+	+ 30_all_tar_libstdc++-link.patch
+	+ 31_all_gm2_make_P_var.patch
+	+ 76_all_match.pd-don-t-emit-label-if-not-needed.patch
+	+ 77_all_match.pd-Remove-commented-out-line-pragmas-unless-vv.patch
+	+ 78_all_match.pd-CSE-the-dump-output-check.patch
+	+ 79_all_genmatch-split-shared-code-to-gimple-match-exports.c.patch
+	+ 80_all_match.pd-automatically-partition-match.cc-files.patch
+	+ 81_all_match.pd-Use-splits-in-makefile-and-make-configurabl.patch
+	+ 82_all_Makefile.in-clean-up-match.pd-related-dependencies.patch
+	+ 86_all_build-Replace-seq-for-portability-with-GNU-Make-vari.patch
+	+ 87_all_Remove-DEFAULT_MATCHPD_PARTITIONS-macro.patch
+	+ 88_all_Makefile.in-Make-TM_P_H-depend-on-TREE_H-PR111021.patch
+	+ 89_all_Makefile.in-Make-recog.h-depend-on-TREE_H-PR111021.patch
+	+ 90_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.patch
+	+ 91_all_riscv_PR106271-multilib-bootstrap.patch
+	+ 92_all_riscv_PR109760-gstreamer.patch
+	+ 93_all_PR115917-ada-lto.patch

diff --git a/13.3.0/musl/25_all_multilib_pure64.patch b/13.3.0/musl/25_all_multilib_pure64.patch
new file mode 100644
index 0000000..d55c04c
--- /dev/null
+++ b/13.3.0/musl/25_all_multilib_pure64.patch
@@ -0,0 +1,83 @@
+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
+ 
+ AARCH_BE = $(if $(findstring TARGET_BIG_ENDIAN_DEFAULT=1, $(tm_defines)),_be)
+-MULTILIB_OSDIRNAMES = mabi.lp64=../lib64$(call if_multiarch,:aarch64$(AARCH_BE)-linux-gnu)
++MULTILIB_OSDIRNAMES = mabi.lp64=../lib
+ MULTIARCH_DIRNAME = $(call if_multiarch,aarch64$(AARCH_BE)-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
++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)))
+ ifneq (,$(findstring powerpc64,$(target)))
+-MULTILIB_OSDIRNAMES := .=../lib64$(call if_multiarch,:powerpc64-linux-gnu)
++MULTILIB_OSDIRNAMES := m64=../lib
++MULTILIB_OSDIRNAMES += m32=../lib32
+ else
+ 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)))
+-MULTILIB_OSDIRNAMES := $(subst -linux,le-linux,$(MULTILIB_OSDIRNAMES))
++MULTILIB_OSDIRNAMES := m64=../lib
++MULTILIB_OSDIRNAMES += m32=../lib32
+ endif
+ endif
+ 
+--- a/gcc/config/rs6000/t-linux64
++++ b/gcc/config/rs6000/t-linux64
+@@ -28,8 +28,8 @@
+ MULTILIB_OPTIONS    := m64/m32
+ MULTILIB_DIRNAMES   := 64 32
+ MULTILIB_EXTRA_OPTS := 
+-MULTILIB_OSDIRNAMES := m64=../lib64$(call if_multiarch,:powerpc64-linux-gnu)
+-MULTILIB_OSDIRNAMES += m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:powerpc-linux-gnu)
++MULTILIB_OSDIRNAMES := m64=../lib
++MULTILIB_OSDIRNAMES += m32=../lib32
+ 
+ rs6000-linux.o: $(srcdir)/config/rs6000/rs6000-linux.c
+ 	$(COMPILE) $<
+--- a/gcc/config/rs6000/t-linux64bele
++++ b/gcc/config/rs6000/t-linux64bele
+@@ -2,6 +2,6 @@
+ 
+ MULTILIB_OPTIONS    += mlittle
+ MULTILIB_DIRNAMES   += le
+-MULTILIB_OSDIRNAMES += $(subst =,.mlittle=,$(subst lible32,lib32le,$(subst lible64,lib64le,$(subst lib,lible,$(subst -linux,le-linux,$(MULTILIB_OSDIRNAMES))))))
+-MULTILIB_OSDIRNAMES += $(subst $(if $(findstring 64,$(target)),m64,m32).,,$(filter $(if $(findstring 64,$(target)),m64,m32).mlittle%,$(MULTILIB_OSDIRNAMES)))
++MULTILIB_OSDIRNAMES = m64=../lib
++MULTILIB_OSDIRNAMES+= m32=../lib32
+ MULTILIB_MATCHES    := ${MULTILIB_MATCHES_ENDIAN}
+--- a/gcc/config/rs6000/t-linux64lebe
++++ b/gcc/config/rs6000/t-linux64lebe
+@@ -2,6 +2,6 @@
+ 
+ MULTILIB_OPTIONS    += mbig
+ MULTILIB_DIRNAMES   += be
+-MULTILIB_OSDIRNAMES += $(subst =,.mbig=,$(subst libbe32,lib32be,$(subst libbe64,lib64be,$(subst lib,libbe,$(subst le-linux,-linux,$(MULTILIB_OSDIRNAMES))))))
+-MULTILIB_OSDIRNAMES += $(subst $(if $(findstring 64,$(target)),m64,m32).,,$(filter $(if $(findstring 64,$(target)),m64,m32).mbig%,$(MULTILIB_OSDIRNAMES)))
++MULTILIB_OSDIRNAMES := m64=../lib
++MULTILIB_OSDIRNAMES += m32=../lib32
+ MULTILIB_MATCHES    := ${MULTILIB_MATCHES_ENDIAN}

diff --git a/13.3.0/musl/50_all_libssp_unconditionally.patch b/13.3.0/musl/50_all_libssp_unconditionally.patch
new file mode 100644
index 0000000..a3b5984
--- /dev/null
+++ b/13.3.0/musl/50_all_libssp_unconditionally.patch
@@ -0,0 +1,24 @@
+https://bugs.gentoo.org/706210
+https://bugs.gentoo.org/747346
+
+Author: Timo Teräs <timo.teras@iki.fi>
+
+"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
+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."
+
+(We do the same in Gentoo.)
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -870,8 +870,7 @@
+ 
+ #ifndef LINK_SSP_SPEC
+ #ifdef TARGET_LIBC_PROVIDES_SSP
+-#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+-		       "|fstack-protector-strong|fstack-protector-explicit:}"
++#define LINK_SSP_SPEC "-lssp_nonshared"
+ #else
+ #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+ 		       "|fstack-protector-strong|fstack-protector-explicit" \

diff --git a/13.3.0/musl/50_all_posix_memalign.patch b/13.3.0/musl/50_all_posix_memalign.patch
new file mode 100644
index 0000000..dd75a93
--- /dev/null
+++ b/13.3.0/musl/50_all_posix_memalign.patch
@@ -0,0 +1,28 @@
+--- a/gcc/config/i386/pmm_malloc.h
++++ b/gcc/config/i386/pmm_malloc.h
+@@ -27,12 +27,13 @@
+ #include <stdlib.h>
+ 
+ /* We can't depend on <stdlib.h> since the prototype of posix_memalign
+-   may not be visible.  */
++   may not be visible and we can't pollute the namespace either.  */
+ #ifndef __cplusplus
+-extern int posix_memalign (void **, size_t, size_t);
++extern int __gcc_posix_memalign (void **, size_t, size_t)
+ #else
+-extern "C" int posix_memalign (void **, size_t, size_t) throw ();
++extern "C" int __gcc_posix_memalign (void **, size_t, size_t) throw ()
+ #endif
++__asm__("posix_memalign");
+ 
+ static __inline void *
+ _mm_malloc (size_t __size, size_t __alignment)
+@@ -42,7 +43,7 @@
+     return malloc (__size);
+   if (__alignment == 2 || (sizeof (void *) == 8 && __alignment == 4))
+     __alignment = sizeof (void *);
+-  if (posix_memalign (&__ptr, __alignment, __size) == 0)
++  if (__gcc_posix_memalign (&__ptr, __alignment, __size) == 0)
+     return __ptr;
+   else
+     return NULL;

diff --git a/13.3.0/musl/50_all_sanitizer_lfs.patch b/13.3.0/musl/50_all_sanitizer_lfs.patch
new file mode 100644
index 0000000..65baea2
--- /dev/null
+++ b/13.3.0/musl/50_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 <sys/ustat.h> 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/13.3.0/musl/README.history b/13.3.0/musl/README.history
new file mode 100644
index 0000000..fcda95a
--- /dev/null
+++ b/13.3.0/musl/README.history
@@ -0,0 +1,14 @@
+3	????
+
+	- 50_all_cpu_indicator.patch
+
+2	10 May 2023
+
+	+ 50_all_sanitizer_lfs.patch
+
+1	26 Apr 2023
+
+	+ 25_all_multilib_pure64.patch
+	+ 50_all_posix_memalign.patch
+	+ 50_all_cpu_indicator.patch
+	+ 50_all_libssp_unconditionally.patch


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2024-09-29 18:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-29 18:56 [gentoo-commits] proj/gcc-patches:master commit in: 13.3.0/musl/, 13.3.0/gentoo/ Sam James

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox