diff options
author | Sam James <sam@gentoo.org> | 2024-09-29 19:55:57 +0100 |
---|---|---|
committer | Sam James <sam@gentoo.org> | 2024-09-29 19:55:57 +0100 |
commit | e8a4b41686079087418212a10b3b32263355135a (patch) | |
tree | ffd68ac1c5a47e2c839d9edea6f6a2795d9df3d7 | |
parent | 13.2.0: add Ada LTO patch (diff) | |
download | gcc-patches-e8a4b41686079087418212a10b3b32263355135a.tar.gz gcc-patches-e8a4b41686079087418212a10b3b32263355135a.tar.bz2 gcc-patches-e8a4b41686079087418212a10b3b32263355135a.zip |
13.3.0: add, clone of 13.3.0 with LTO patch
Signed-off-by: Sam James <sam@gentoo.org>
44 files changed, 7060 insertions, 0 deletions
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]; + + static void +-print_code (RTX_CODE code) ++print_code (RTX_CODE code, FILE *file) + { + const char *p1; + for (p1 = GET_RTX_NAME (code); *p1; p1++) +- putchar (TOUPPER (*p1)); ++ fprintf (file, "%c", TOUPPER (*p1)); + } + + static void +-gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) ++gen_rtx_scratch (rtx x, enum rtx_code subroutine_type, FILE *file) + { + if (subroutine_type == DEFINE_PEEPHOLE2) + { +- printf ("operand%d", XINT (x, 0)); ++ fprintf (file, "operand%d", XINT (x, 0)); + } + else + { +- printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); ++ fprintf (file, "gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); + } + } + +@@ -79,7 +79,8 @@ gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) + substituting any operand references appearing within. */ + + static void +-gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) ++gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info, ++ FILE *file) + { + RTX_CODE code; + int i; +@@ -89,7 +90,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + + if (x == 0) + { +- printf ("NULL_RTX"); ++ fprintf (file, "NULL_RTX"); + return; + } + +@@ -103,67 +104,67 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + { + if (used[XINT (x, 0)]) + { +- printf ("copy_rtx (operand%d)", XINT (x, 0)); ++ fprintf (file, "copy_rtx (operand%d)", XINT (x, 0)); + return; + } + used[XINT (x, 0)] = 1; + } +- printf ("operand%d", XINT (x, 0)); ++ fprintf (file, "operand%d", XINT (x, 0)); + return; + + case MATCH_OP_DUP: +- printf ("gen_rtx_fmt_"); ++ fprintf (file, "gen_rtx_fmt_"); + for (i = 0; i < XVECLEN (x, 1); i++) +- printf ("e"); +- printf (" (GET_CODE (operand%d), ", XINT (x, 0)); ++ fprintf (file, "e"); ++ fprintf (file, " (GET_CODE (operand%d), ", XINT (x, 0)); + if (GET_MODE (x) == VOIDmode) +- printf ("GET_MODE (operand%d)", XINT (x, 0)); ++ fprintf (file, "GET_MODE (operand%d)", XINT (x, 0)); + else +- printf ("%smode", GET_MODE_NAME (GET_MODE (x))); ++ fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x))); + for (i = 0; i < XVECLEN (x, 1); i++) + { +- printf (",\n\t\t"); +- gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info); ++ fprintf (file, ",\n\t\t"); ++ gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info, file); + } +- printf (")"); ++ fprintf (file, ")"); + return; + + case MATCH_OPERATOR: +- printf ("gen_rtx_fmt_"); ++ fprintf (file, "gen_rtx_fmt_"); + for (i = 0; i < XVECLEN (x, 2); i++) +- printf ("e"); +- printf (" (GET_CODE (operand%d)", XINT (x, 0)); +- printf (", %smode", GET_MODE_NAME (GET_MODE (x))); ++ fprintf (file, "e"); ++ fprintf (file, " (GET_CODE (operand%d)", XINT (x, 0)); ++ fprintf (file, ", %smode", GET_MODE_NAME (GET_MODE (x))); + for (i = 0; i < XVECLEN (x, 2); i++) + { +- printf (",\n\t\t"); +- gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info); ++ fprintf (file, ",\n\t\t"); ++ gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info, file); + } +- printf (")"); ++ fprintf (file, ")"); + return; + + case MATCH_PARALLEL: + case MATCH_PAR_DUP: +- printf ("operand%d", XINT (x, 0)); ++ fprintf (file, "operand%d", XINT (x, 0)); + return; + + case MATCH_SCRATCH: +- gen_rtx_scratch (x, subroutine_type); ++ gen_rtx_scratch (x, subroutine_type, file); + return; + + case PC: +- printf ("pc_rtx"); ++ fprintf (file, "pc_rtx"); + return; + case RETURN: +- printf ("ret_rtx"); ++ fprintf (file, "ret_rtx"); + return; + case SIMPLE_RETURN: +- printf ("simple_return_rtx"); ++ fprintf (file, "simple_return_rtx"); + return; + case CLOBBER: + if (REG_P (XEXP (x, 0))) + { +- printf ("gen_hard_reg_clobber (%smode, %i)", ++ fprintf (file, "gen_hard_reg_clobber (%smode, %i)", + GET_MODE_NAME (GET_MODE (XEXP (x, 0))), + REGNO (XEXP (x, 0))); + return; +@@ -172,22 +173,22 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + + case CONST_INT: + if (INTVAL (x) == 0) +- printf ("const0_rtx"); ++ fprintf (file, "const0_rtx"); + else if (INTVAL (x) == 1) +- printf ("const1_rtx"); ++ fprintf (file, "const1_rtx"); + else if (INTVAL (x) == -1) +- printf ("constm1_rtx"); ++ fprintf (file, "constm1_rtx"); + else if (-MAX_SAVED_CONST_INT <= INTVAL (x) + && INTVAL (x) <= MAX_SAVED_CONST_INT) +- printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", ++ fprintf (file, "const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", + (int) INTVAL (x)); + else if (INTVAL (x) == STORE_FLAG_VALUE) +- printf ("const_true_rtx"); ++ fprintf (file, "const_true_rtx"); + else + { +- printf ("GEN_INT ("); +- printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x)); +- printf (")"); ++ fprintf (file, "GEN_INT ("); ++ fprintf (file, HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x)); ++ fprintf (file, ")"); + } + return; + +@@ -195,7 +196,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + /* Handle `const_double_zero' rtx. */ + if (CONST_DOUBLE_REAL_VALUE (x)->cl == rvc_zero) + { +- printf ("CONST_DOUBLE_ATOF (\"0\", %smode)", ++ fprintf (file, "CONST_DOUBLE_ATOF (\"0\", %smode)", + GET_MODE_NAME (GET_MODE (x))); + return; + } +@@ -210,12 +211,12 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + break; + } + +- printf ("gen_rtx_"); +- print_code (code); +- printf (" ("); ++ fprintf (file, "gen_rtx_"); ++ print_code (code, file); ++ fprintf (file, " ("); + if (!always_void_p (code)) + { +- printf ("%smode", GET_MODE_NAME (GET_MODE (x))); ++ fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x))); + sep = ",\n\t"; + } + +@@ -225,41 +226,41 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + { + if (fmt[i] == '0') + break; +- fputs (sep, stdout); ++ fputs (sep, file); + switch (fmt[i]) + { + case 'e': case 'u': +- gen_exp (XEXP (x, i), subroutine_type, used, info); ++ gen_exp (XEXP (x, i), subroutine_type, used, info, file); + break; + + case 'i': +- printf ("%u", XINT (x, i)); ++ fprintf (file, "%u", XINT (x, i)); + break; + + case 'r': +- printf ("%u", REGNO (x)); ++ fprintf (file, "%u", REGNO (x)); + break; + + case 'p': + /* We don't have a way of parsing polynomial offsets yet, + and hopefully never will. */ +- printf ("%d", SUBREG_BYTE (x).to_constant ()); ++ fprintf (file, "%d", SUBREG_BYTE (x).to_constant ()); + break; + + case 's': +- printf ("\"%s\"", XSTR (x, i)); ++ fprintf (file, "\"%s\"", XSTR (x, i)); + break; + + case 'E': + { + int j; +- printf ("gen_rtvec (%d", XVECLEN (x, i)); ++ fprintf (file, "gen_rtvec (%d", XVECLEN (x, i)); + for (j = 0; j < XVECLEN (x, i); j++) + { +- printf (",\n\t\t"); +- gen_exp (XVECEXP (x, i, j), subroutine_type, used, info); ++ fprintf (file, ",\n\t\t"); ++ gen_exp (XVECEXP (x, i, j), subroutine_type, used, info, file); + } +- printf (")"); ++ fprintf (file, ")"); + break; + } + +@@ -268,14 +269,14 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) + } + sep = ",\n\t"; + } +- printf (")"); ++ fprintf (file, ")"); + } + + /* Output code to emit the instruction patterns in VEC, with each element + becoming a separate instruction. USED is as for gen_exp. */ + + static void +-gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) ++gen_emit_seq (rtvec vec, char *used, md_rtx_info *info, FILE *file) + { + for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) + { +@@ -283,17 +284,17 @@ gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) + rtx next = RTVEC_ELT (vec, i); + if (const char *name = get_emit_function (next)) + { +- printf (" %s (", name); +- gen_exp (next, DEFINE_EXPAND, used, info); +- printf (");\n"); ++ fprintf (file, " %s (", name); ++ gen_exp (next, DEFINE_EXPAND, used, info, file); ++ fprintf (file, ");\n"); + if (!last_p && needs_barrier_p (next)) +- printf (" emit_barrier ();"); ++ fprintf (file, " emit_barrier ();"); + } + else + { +- printf (" emit ("); +- gen_exp (next, DEFINE_EXPAND, used, info); +- printf (", %s);\n", last_p ? "false" : "true"); ++ fprintf (file, " emit ("); ++ gen_exp (next, DEFINE_EXPAND, used, info, file); ++ fprintf (file, ", %s);\n", last_p ? "false" : "true"); + } + } + } +@@ -303,27 +304,27 @@ gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) + for use in error messages. */ + + static void +-emit_c_code (const char *code, bool can_fail_p, const char *name) ++emit_c_code (const char *code, bool can_fail_p, const char *name, FILE *file) + { + if (can_fail_p) +- printf ("#define FAIL return (end_sequence (), _val)\n"); ++ fprintf (file, "#define FAIL return (end_sequence (), _val)\n"); + else +- printf ("#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" ++ fprintf (file, "#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" + " (void)0\n", name); +- printf ("#define DONE return (_val = get_insns (), " ++ fprintf (file, "#define DONE return (_val = get_insns (), " + "end_sequence (), _val)\n"); + +- rtx_reader_ptr->print_md_ptr_loc (code); +- printf ("%s\n", code); ++ rtx_reader_ptr->print_md_ptr_loc (code, file); ++ fprintf (file, "%s\n", code); + +- printf ("#undef DONE\n"); +- printf ("#undef FAIL\n"); ++ fprintf (file, "#undef DONE\n"); ++ fprintf (file, "#undef FAIL\n"); + } + + /* Generate the `gen_...' function for a DEFINE_INSN. */ + + static void +-gen_insn (md_rtx_info *info) ++gen_insn (md_rtx_info *info, FILE *file) + { + struct pattern_stats stats; + int i; +@@ -409,7 +410,7 @@ gen_insn (md_rtx_info *info) + if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*') + return; + +- printf ("/* %s:%d */\n", info->loc.filename, info->loc.lineno); ++ fprintf (file, "/* %s:%d */\n", info->loc.filename, info->loc.lineno); + + /* Find out how many operands this function has. */ + get_pattern_stats (&stats, XVEC (insn, 1)); +@@ -417,17 +418,17 @@ gen_insn (md_rtx_info *info) + fatal_at (info->loc, "match_dup operand number has no match_operand"); + + /* Output the function name and argument declarations. */ +- printf ("rtx\ngen_%s (", XSTR (insn, 0)); ++ fprintf (file, "rtx\ngen_%s (", XSTR (insn, 0)); + if (stats.num_generator_args) + for (i = 0; i < stats.num_generator_args; i++) + if (i) +- printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i); ++ fprintf (file, ",\n\trtx operand%d ATTRIBUTE_UNUSED", i); + else +- printf ("rtx operand%d ATTRIBUTE_UNUSED", i); ++ fprintf (file, "rtx operand%d ATTRIBUTE_UNUSED", i); + else +- printf ("void"); +- printf (")\n"); +- printf ("{\n"); ++ fprintf (file, "void"); ++ fprintf (file, ")\n"); ++ fprintf (file, "{\n"); + + /* Output code to construct and return the rtl for the instruction body. */ + +@@ -436,16 +437,16 @@ gen_insn (md_rtx_info *info) + char *used = (XVECLEN (insn, 1) == 1 + ? NULL + : XCNEWVEC (char, stats.num_generator_args)); +- printf (" return "); +- gen_exp (pattern, DEFINE_INSN, used, info); +- printf (";\n}\n\n"); ++ fprintf (file, " return "); ++ gen_exp (pattern, DEFINE_INSN, used, info, file); ++ fprintf (file, ";\n}\n\n"); + XDELETEVEC (used); + } + + /* Generate the `gen_...' function for a DEFINE_EXPAND. */ + + static void +-gen_expand (md_rtx_info *info) ++gen_expand (md_rtx_info *info, FILE *file) + { + struct pattern_stats stats; + int i; +@@ -466,17 +467,17 @@ gen_expand (md_rtx_info *info) + "numbers above all other operands", XSTR (expand, 0)); + + /* Output the function name and argument declarations. */ +- printf ("rtx\ngen_%s (", XSTR (expand, 0)); ++ fprintf (file, "rtx\ngen_%s (", XSTR (expand, 0)); + if (stats.num_generator_args) + for (i = 0; i < stats.num_generator_args; i++) + if (i) +- printf (",\n\trtx operand%d", i); ++ fprintf (file, ",\n\trtx operand%d", i); + else +- printf ("rtx operand%d", i); ++ fprintf (file, "rtx operand%d", i); + else +- printf ("void"); +- printf (")\n"); +- printf ("{\n"); ++ fprintf (file, "void"); ++ fprintf (file, ")\n"); ++ fprintf (file, "{\n"); + + /* If we don't have any C code to write, only one insn is being written, + and no MATCH_DUPs are present, we can just return the desired insn +@@ -485,18 +486,18 @@ gen_expand (md_rtx_info *info) + && stats.max_opno >= stats.max_dup_opno + && XVECLEN (expand, 1) == 1) + { +- printf (" return "); +- gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info); +- printf (";\n}\n\n"); ++ fprintf (file, " return "); ++ gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info, file); ++ fprintf (file, ";\n}\n\n"); + return; + } + + /* For each operand referred to only with MATCH_DUPs, + make a local variable. */ + for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++) +- printf (" rtx operand%d;\n", i); +- printf (" rtx_insn *_val = 0;\n"); +- printf (" start_sequence ();\n"); ++ fprintf (file, " rtx operand%d;\n", i); ++ fprintf (file, " rtx_insn *_val = 0;\n"); ++ fprintf (file, " start_sequence ();\n"); + + /* The fourth operand of DEFINE_EXPAND is some code to be executed + before the actual construction. +@@ -506,13 +507,13 @@ gen_expand (md_rtx_info *info) + So copy the operand values there before executing it. */ + if (XSTR (expand, 3) && *XSTR (expand, 3)) + { +- printf (" {\n"); ++ fprintf (file, " {\n"); + if (stats.num_operand_vars > 0) +- printf (" rtx operands[%d];\n", stats.num_operand_vars); ++ fprintf (file, " rtx operands[%d];\n", stats.num_operand_vars); + + /* Output code to copy the arguments into `operands'. */ + for (i = 0; i < stats.num_generator_args; i++) +- printf (" operands[%d] = operand%d;\n", i, i); ++ fprintf (file, " operands[%d] = operand%d;\n", i, i); + + /* Output the special code to be executed before the sequence + is generated. */ +@@ -524,7 +525,7 @@ gen_expand (md_rtx_info *info) + if (nofail_optabs[p.op]) + can_fail_p = false; + } +- emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0)); ++ emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0), file); + + /* Output code to copy the arguments back out of `operands' + (unless we aren't going to use them at all). */ +@@ -532,29 +533,29 @@ gen_expand (md_rtx_info *info) + { + for (i = 0; i <= MAX (stats.max_opno, stats.max_dup_opno); i++) + { +- printf (" operand%d = operands[%d];\n", i, i); +- printf (" (void) operand%d;\n", i); ++ fprintf (file, " operand%d = operands[%d];\n", i, i); ++ fprintf (file, " (void) operand%d;\n", i); + } + } +- printf (" }\n"); ++ fprintf (file, " }\n"); + } + + used = XCNEWVEC (char, stats.num_operand_vars); +- gen_emit_seq (XVEC (expand, 1), used, info); ++ gen_emit_seq (XVEC (expand, 1), used, info, file); + XDELETEVEC (used); + + /* Call `get_insns' to extract the list of all the + insns emitted within this gen_... function. */ + +- printf (" _val = get_insns ();\n"); +- printf (" end_sequence ();\n"); +- printf (" return _val;\n}\n\n"); ++ fprintf (file, " _val = get_insns ();\n"); ++ fprintf (file, " end_sequence ();\n"); ++ fprintf (file, " return _val;\n}\n\n"); + } + + /* Like gen_expand, but generates insns resulting from splitting SPLIT. */ + + static void +-gen_split (md_rtx_info *info) ++gen_split (md_rtx_info *info, FILE *file) + { + struct pattern_stats stats; + int i; +@@ -580,62 +581,62 @@ gen_split (md_rtx_info *info) + /* Output the prototype, function name and argument declarations. */ + if (GET_CODE (split) == DEFINE_PEEPHOLE2) + { +- printf ("extern rtx_insn *gen_%s_%d (rtx_insn *, rtx *);\n", ++ fprintf (file, "extern rtx_insn *gen_%s_%d (rtx_insn *, rtx *);\n", + name, info->index); +- printf ("rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED," ++ fprintf (file, "rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED," + " rtx *operands%s)\n", + name, info->index, unused); + } + else + { +- printf ("extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n", ++ fprintf (file, "extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n", + info->index); +- printf ("rtx_insn *\ngen_split_%d " ++ fprintf (file, "rtx_insn *\ngen_split_%d " + "(rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", + info->index, unused); + } +- printf ("{\n"); ++ fprintf (file, "{\n"); + + /* Declare all local variables. */ + for (i = 0; i < stats.num_operand_vars; i++) +- printf (" rtx operand%d;\n", i); +- printf (" rtx_insn *_val = NULL;\n"); ++ fprintf (file, " rtx operand%d;\n", i); ++ fprintf (file, " rtx_insn *_val = NULL;\n"); + + if (GET_CODE (split) == DEFINE_PEEPHOLE2) +- output_peephole2_scratches (split); ++ output_peephole2_scratches (split, file); + + const char *fn = info->loc.filename; + for (const char *p = fn; *p; p++) + if (*p == '/') + fn = p + 1; + +- printf (" if (dump_file)\n"); +- printf (" fprintf (dump_file, \"Splitting with gen_%s_%d (%s:%d)\\n\");\n", ++ fprintf (file, " if (dump_file)\n"); ++ fprintf (file, " fprintf (dump_file, \"Splitting with gen_%s_%d (%s:%d)\\n\");\n", + name, info->index, fn, info->loc.lineno); + +- printf (" start_sequence ();\n"); ++ fprintf (file, " start_sequence ();\n"); + + /* The fourth operand of DEFINE_SPLIT is some code to be executed + before the actual construction. */ + + if (XSTR (split, 3)) +- emit_c_code (XSTR (split, 3), true, name); ++ emit_c_code (XSTR (split, 3), true, name, file); + + /* Output code to copy the arguments back out of `operands' */ + for (i = 0; i < stats.num_operand_vars; i++) + { +- printf (" operand%d = operands[%d];\n", i, i); +- printf (" (void) operand%d;\n", i); ++ fprintf (file, " operand%d = operands[%d];\n", i, i); ++ fprintf (file, " (void) operand%d;\n", i); + } + +- gen_emit_seq (XVEC (split, 2), used, info); ++ gen_emit_seq (XVEC (split, 2), used, info, file); + + /* Call `get_insns' to make a list of all the + insns emitted within this gen_... function. */ + +- printf (" _val = get_insns ();\n"); +- printf (" end_sequence ();\n"); +- printf (" return _val;\n}\n\n"); ++ fprintf (file, " _val = get_insns ();\n"); ++ fprintf (file, " end_sequence ();\n"); ++ fprintf (file, " return _val;\n}\n\n"); + + free (used); + } +@@ -645,37 +646,37 @@ gen_split (md_rtx_info *info) + the end of the vector. */ + + static void +-output_add_clobbers (md_rtx_info *info) ++output_add_clobbers (md_rtx_info *info, FILE *file) + { + struct clobber_pat *clobber; + struct clobber_ent *ent; + int i; + +- printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n"); +- printf ("{\n"); +- printf (" switch (insn_code_number)\n"); +- printf (" {\n"); ++ fprintf (file, "\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n"); ++ fprintf (file, "{\n"); ++ fprintf (file, " switch (insn_code_number)\n"); ++ fprintf (file, " {\n"); + + for (clobber = clobber_list; clobber; clobber = clobber->next) + { + for (ent = clobber->insns; ent; ent = ent->next) +- printf (" case %d:\n", ent->code_number); ++ fprintf (file, " case %d:\n", ent->code_number); + + for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) + { +- printf (" XVECEXP (pattern, 0, %d) = ", i); ++ fprintf (file, " XVECEXP (pattern, 0, %d) = ", i); + gen_exp (XVECEXP (clobber->pattern, 1, i), +- GET_CODE (clobber->pattern), NULL, info); +- printf (";\n"); ++ GET_CODE (clobber->pattern), NULL, info, file); ++ fprintf (file, ";\n"); + } + +- printf (" break;\n\n"); ++ fprintf (file, " break;\n\n"); + } + +- printf (" default:\n"); +- printf (" gcc_unreachable ();\n"); +- printf (" }\n"); +- printf ("}\n"); ++ fprintf (file, " default:\n"); ++ fprintf (file, " gcc_unreachable ();\n"); ++ fprintf (file, " }\n"); ++ fprintf (file, "}\n"); + } + + /* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code +@@ -684,16 +685,16 @@ output_add_clobbers (md_rtx_info *info) + SCRATCH. */ + + static void +-output_added_clobbers_hard_reg_p (void) ++output_added_clobbers_hard_reg_p (FILE *file) + { + struct clobber_pat *clobber; + struct clobber_ent *ent; + int clobber_p, used; + +- printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n"); +- printf ("{\n"); +- printf (" switch (insn_code_number)\n"); +- printf (" {\n"); ++ fprintf (file, "\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n"); ++ fprintf (file, "{\n"); ++ fprintf (file, " switch (insn_code_number)\n"); ++ fprintf (file, " {\n"); + + for (clobber_p = 0; clobber_p <= 1; clobber_p++) + { +@@ -702,25 +703,25 @@ output_added_clobbers_hard_reg_p (void) + if (clobber->has_hard_reg == clobber_p) + for (ent = clobber->insns; ent; ent = ent->next) + { +- printf (" case %d:\n", ent->code_number); ++ fprintf (file, " case %d:\n", ent->code_number); + used++; + } + + if (used) +- printf (" return %d;\n\n", clobber_p); ++ fprintf (file, " return %d;\n\n", clobber_p); + } + +- printf (" default:\n"); +- printf (" gcc_unreachable ();\n"); +- printf (" }\n"); +- printf ("}\n"); ++ fprintf (file, " default:\n"); ++ fprintf (file, " gcc_unreachable ();\n"); ++ fprintf (file, " }\n"); ++ fprintf (file, "}\n"); + } + + /* Generate code to invoke find_free_register () as needed for the + scratch registers used by the peephole2 pattern in SPLIT. */ + + static void +-output_peephole2_scratches (rtx split) ++output_peephole2_scratches (rtx split, FILE *file) + { + int i; + int insn_nr = 0; +@@ -745,12 +746,12 @@ output_peephole2_scratches (rtx split) + + if (first) + { +- printf (" HARD_REG_SET _regs_allocated;\n"); +- printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n"); ++ fprintf (file, " HARD_REG_SET _regs_allocated;\n"); ++ fprintf (file, " CLEAR_HARD_REG_SET (_regs_allocated);\n"); + first = false; + } + +- printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ ++ fprintf (file, " if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ + return NULL;\n", + XINT (elt, 0), + insn_nr, last_insn_nr, +@@ -766,50 +767,50 @@ output_peephole2_scratches (rtx split) + /* Print "arg<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); + } + ++/* Count the number of patterns in all queues and return the count. */ ++int ++count_patterns () ++{ ++ int count = 0, truth = 1; ++ rtx def; ++ class queue_elem *cur = define_attr_queue; ++ while (cur) ++ { ++ def = cur->data; ++ ++ truth = maybe_eval_c_test (get_c_test (def)); ++ if (truth || !insn_elision) ++ count++; ++ cur = cur->next; ++ } ++ ++ cur = define_pred_queue; ++ while (cur) ++ { ++ def = cur->data; ++ ++ truth = maybe_eval_c_test (get_c_test (def)); ++ if (truth || !insn_elision) ++ count++; ++ cur = cur->next; ++ } ++ ++ cur = define_insn_queue; ++ truth = 1; ++ while (cur) ++ { ++ def = cur->data; ++ ++ truth = maybe_eval_c_test (get_c_test (def)); ++ if (truth || !insn_elision) ++ count++; ++ cur = cur->next; ++ } ++ ++ cur = other_queue; ++ truth = 1; ++ while (cur) ++ { ++ def = cur->data; ++ ++ truth = maybe_eval_c_test (get_c_test (def)); ++ if (truth || !insn_elision) ++ count++; ++ cur = cur->next; ++ } ++ ++ return count; ++} ++ + /* Try to read a single rtx from the file. Return true on success, + describing it in *INFO. */ + +diff --git a/gcc/gensupport.h b/gcc/gensupport.h +index a1edfbd71908..510ba19405e4 100644 +--- a/gcc/gensupport.h ++++ b/gcc/gensupport.h +@@ -129,6 +129,7 @@ extern rtx add_implicit_parallel (rtvec); + extern rtx_reader *init_rtx_reader_args_cb (int, const char **, + bool (*)(const char *)); + extern rtx_reader *init_rtx_reader_args (int, const char **); ++extern int count_patterns (); + extern bool read_md_rtx (md_rtx_info *); + extern unsigned int get_num_insn_codes (); + +diff --git a/gcc/read-md.cc b/gcc/read-md.cc +index fd38818e3a3e..46ab9065e3e4 100644 +--- a/gcc/read-md.cc ++++ b/gcc/read-md.cc +@@ -132,9 +132,9 @@ md_reader::fprint_md_ptr_loc (FILE *outf, const void *ptr) + + /* Special fprint_md_ptr_loc for writing to STDOUT. */ + void +-md_reader::print_md_ptr_loc (const void *ptr) ++md_reader::print_md_ptr_loc (const void *ptr, FILE *file) + { +- fprint_md_ptr_loc (stdout, ptr); ++ fprint_md_ptr_loc (file, ptr); + } + + /* Return a condition that satisfies both COND1 and COND2. Either string +diff --git a/gcc/read-md.h b/gcc/read-md.h +index b309c9c3deb6..2adcb58478fe 100644 +--- a/gcc/read-md.h ++++ b/gcc/read-md.h +@@ -194,7 +194,7 @@ class md_reader + const struct ptr_loc *get_md_ptr_loc (const void *ptr); + void copy_md_ptr_loc (const void *new_ptr, const void *old_ptr); + void fprint_md_ptr_loc (FILE *outf, const void *ptr); +- void print_md_ptr_loc (const void *ptr); ++ void print_md_ptr_loc (const void *ptr, FILE * = stdout); + + struct enum_type *lookup_enum_type (const char *name); + void traverse_enum_types (htab_trav callback, void *info); +-- +2.44.0 + diff --git a/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 |