aboutsummaryrefslogtreecommitdiff
path: root/14.0.0
diff options
context:
space:
mode:
authorSam James <sam@gentoo.org>2023-10-16 13:33:30 +0100
committerSam James <sam@gentoo.org>2023-10-16 13:40:58 +0100
commitcfe1a42149964e54a250698e9d8dc50f4745caf9 (patch)
tree107d08a4c6fbeae99c4f1b655ea9e2592d9961e7 /14.0.0
parent13.2.0: backport insn-emit split patches (diff)
downloadgcc-patches-cfe1a42149964e54a250698e9d8dc50f4745caf9.tar.gz
gcc-patches-cfe1a42149964e54a250698e9d8dc50f4745caf9.tar.bz2
gcc-patches-cfe1a42149964e54a250698e9d8dc50f4745caf9.zip
14.0.0: backport insn-emit split patches
For parity with 13.x. This is a continuation of 7a6b2d23ec02e75475a6123254ccd44d73827f39 ('13.2.0: backport split match.pd changes') in a sense - see that commit for rationale for backporting. Motivated here again by more reports of OOMs with insn-match.cc. Bug: https://gcc.gnu.org/PR54179 Bug: https://gcc.gnu.org/PR84402 Bug: https://gcc.gnu.org/PR111600 Signed-off-by: Sam James <sam@gentoo.org>
Diffstat (limited to '14.0.0')
-rw-r--r--14.0.0/gentoo/75_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.patch1453
-rw-r--r--14.0.0/gentoo/README.history6
2 files changed, 1459 insertions, 0 deletions
diff --git a/14.0.0/gentoo/75_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.patch b/14.0.0/gentoo/75_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.patch
new file mode 100644
index 0000000..dbcea97
--- /dev/null
+++ b/14.0.0/gentoo/75_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.patch
@@ -0,0 +1,1453 @@
+https://gcc.gnu.org/PR54179
+https://inbox.sourceware.org/gcc-patches/de0f7bdc-d236-4f5b-9504-d5bfb215d023@gmail.com/
+
+From mboxrd@z Thu Jan 1 00:00:00 1970
+Return-Path: <SRS0=V+kJ=F6=gmail.com=rdapp.gcc@sourceware.org>
+Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435])
+ by sourceware.org (Postfix) with ESMTPS id 494063858D33
+ for <gcc-patches@gcc.gnu.org>; Mon, 16 Oct 2023 10:17:21 +0000 (GMT)
+DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 494063858D33
+Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com
+Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com
+ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 494063858D33
+Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::435
+ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1697451446; cv=none;
+ b=p7qdXp6tA02vcm8FYp8Z94RsTNBTMF12iWlVcXVLWFaSW8HGwwCYhMGYoGFaifZQRu4UKyuAB+IzEF6a/yAg4YIoSatzLygSXd8C4Y5pTzNOedtsXKySOf2H5tU0JllZhFiL0j839yK0ULkru902Fm5qYfCWOI/oclFGFv0QJhk=
+ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key;
+ t=1697451446; c=relaxed/simple;
+ bh=F5nvjfODgAkwvN6oz045m/y2cCq1Y5w/bjL6/Zx7/us=;
+ h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From; b=Irn6EDwgJ++gSjzeSooV3KQnHee12GYc2RQmTDoYZo/FSdddOhiPTfdaC7P29HmOXa4CPBOS8Yv9BTZMwm6YLK9J2wCQws5N76sMTuINsJ4seyvCF4hUO/2icjNn/K1NCpiAh/hGfqdO7ASiqbVBoFfgM7fwtCOYLKF6sIY1lyM=
+ARC-Authentication-Results: i=1; server2.sourceware.org
+Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-32d834ec222so4107319f8f.0
+ for <gcc-patches@gcc.gnu.org>; Mon, 16 Oct 2023 03:17:21 -0700 (PDT)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=gmail.com; s=20230601; t=1697451440; x=1698056240; darn=gcc.gnu.org;
+ h=content-transfer-encoding:in-reply-to:from:references:to
+ :content-language:subject:cc:user-agent:mime-version:date:message-id
+ :from:to:cc:subject:date:message-id:reply-to;
+ bh=wq5w+s2m/P53eb5oT6XaK+NiaOj7NqTTS7VH5l0hPUk=;
+ b=ir8fQ9LhX/rsjkKQE99tm5M/K+iNNIYZ/1cdZ5bz4WDndMrk52oidsfzruyMfSbRhB
+ rHSI1uSAzTr3Hp0f3ugYQInO3KFgdrvSiZ1sUhIcSA9SG7fCECczgD7GcW6OZn6F8c9u
+ XbFgqbWLIFtqXeKsmQs+CY2nS4KS/CRT9eoUafES8rZNYXDOe9QVbHjblx7rtXWO2HXQ
+ lmfzqTktf3I7JxtYpl0r0MYMcjSfcq0DOuL80NWyMDlBWOQT3IBAdyulrLAEW+jH/Z8p
+ xQ15SULgu0m2yiv/KGWXTkZfr7tvRGnSmmdtRRH0FCoXSf8jg/zHFTkl/j+SzlSzDwGs
+ c1qg==
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=1e100.net; s=20230601; t=1697451440; x=1698056240;
+ h=content-transfer-encoding:in-reply-to:from:references:to
+ :content-language:subject:cc:user-agent:mime-version:date:message-id
+ :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;
+ bh=wq5w+s2m/P53eb5oT6XaK+NiaOj7NqTTS7VH5l0hPUk=;
+ b=kKfXLuOWBPVcAyFOUh31XizZ+aCfxMvezPMmblFS/UpzD2W/C0uFKwEGnChfefXi2/
+ +bzYReU5vtLu8pAloncEatu5L4GV1u+WdTSbW1T5xIy+5oMx++9PpyY4AE247J0yd86k
+ 1y7iJTKapjRfltZuFYEXFXtk+EUb6KM8JtlwJvoxl1WA5eUMF3QS7mrB/a4aM4x6i+Eg
+ YlOoTXYO0bLGOCdeXOLJfjDEkck1ELrHj2LtlRHyrlB9cfOgf17T6ndeeHGFfXNQHPZ9
+ 6ozlhvhckpJQgI9lmwx9y62sUeq7EvLbrq6iRQm/urmU7ONjSXtvH9MhuU6vUBxvHZ7m
+ L7/Q==
+X-Gm-Message-State: AOJu0Yx8eFwSIp03QtdxQpmlUlQqKK5PYRJxvpOd/sAQ1a6DUl745e7C
+ /BMIbVYdWvfmdTlOA4Fq7wwu2tV7IwY=
+X-Google-Smtp-Source: AGHT+IHxbooDFrEU9aYJYA4rfQo2Hg5vBRYXtzpX5blf0iOYdzDMzsRxuyqHl6Jlfcy9/43ovuJMnQ==
+X-Received: by 2002:a5d:4402:0:b0:32d:8907:2b18 with SMTP id z2-20020a5d4402000000b0032d89072b18mr12076090wrq.66.1697451439584;
+ Mon, 16 Oct 2023 03:17:19 -0700 (PDT)
+Received: from [192.168.1.23] (ip-046-223-203-173.um13.pools.vodafone-ip.de. [46.223.203.173])
+ by smtp.gmail.com with ESMTPSA id e10-20020a5d65ca000000b0032da6f17ffdsm4983379wrw.38.2023.10.16.03.17.18
+ (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);
+ Mon, 16 Oct 2023 03:17:19 -0700 (PDT)
+Message-ID: <0867077f-12ac-4a89-8745-440cc782fe5b@gmail.com>
+Date: Mon, 16 Oct 2023 12:17:07 +0200
+MIME-Version: 1.0
+User-Agent: Mozilla Thunderbird
+Cc: rdapp.gcc@gmail.com, jeffreyalaw <jeffreyalaw@gmail.com>,
+ "rjiejie@linux.alibaba.com" <rjiejie@linux.alibaba.com>
+Subject: Re: [PATCH] genemit: Split insn-emit.cc into ten files.
+Content-Language: en-US
+To: Tamar Christina <Tamar.Christina@arm.com>,
+ gcc-patches <gcc-patches@gcc.gnu.org>
+References: <de0f7bdc-d236-4f5b-9504-d5bfb215d023@gmail.com>
+ <be6174c7-820c-45b2-abb6-177c0701e3f5@gmail.com>
+ <VI1PR08MB53258DF11D842AD7BBDA7434FFD2A@VI1PR08MB5325.eurprd08.prod.outlook.com>
+ <37f1c7f7-411e-46de-8d68-a1e21ff440ae@gmail.com>
+From: Robin Dapp <rdapp.gcc@gmail.com>
+In-Reply-To: <37f1c7f7-411e-46de-8d68-a1e21ff440ae@gmail.com>
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 7bit
+X-Spam-Status: No, score=-9.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6
+X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org
+List-Id: <gcc-patches.gcc.gnu.org>
+
+Hi,
+
+the attached v2 includes Tamar's suggestion of keeping the current
+stdout behavior. When no output files are passed (via -O) the output
+is written to stdout as before.
+
+Tamar also mentioned off-list that, similar to match.pd, it might make
+sense to balance the partitions in a better way than a fixed number
+of patterns threshold. That's a good idea but I'd rather do that
+separately as the current approach already helps considerably.
+
+Attached v2 was bootstrapped and regtested on power10, aarch64 and
+x86 are still running.
+Stefan also tested v1 on s390 where the partitioning does not help
+but also doesn't slow anything down. insn-emit.cc isn't very large
+to begin with on s390.
+
+Regards
+ Robin
+
+>From 34d05113a4e3c7e83a4731020307e26c1144af69 Mon Sep 17 00:00:00 2001
+From: Robin Dapp <rdapp@ventanamicro.com>
+Date: Thu, 12 Oct 2023 11:23:26 +0200
+Subject: [PATCH v2] 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). In order to do so it first counts
+the number of available patterns, calculates the number of patterns per
+file and starts a new file whenever that number is reached.
+
+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 | 38 +++-
+ gcc/configure | 24 ++-
+ gcc/configure.ac | 13 ++
+ gcc/genemit.cc | 536 +++++++++++++++++++++++++---------------------
+ gcc/gensupport.cc | 36 ++++
+ gcc/gensupport.h | 1 +
+ gcc/read-md.cc | 4 +-
+ gcc/read-md.h | 2 +-
+ 8 files changed, 399 insertions(+), 255 deletions(-)
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 9cc16268abf..ca0a616f768 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -236,6 +236,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
+@@ -1354,7 +1361,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 \
+@@ -1852,7 +1859,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) \
+@@ -2481,11 +2489,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
+@@ -2508,7 +2516,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
+
+@@ -2537,8 +2545,22 @@ $(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)
++s-tmp-emit: build/genemit$(build_exeext) insn-conditions.md
++ $(RUN_GEN) build/genemit$(build_exeext) $(md_file) insn-conditions.md \
++ $(addprefix -O,${INSNEMIT_SEQ_TMP})
++ $(STAMP) s-tmp-emit
++
++$(INSNEMIT_SEQ_SRC): insn-emit-%.cc: s-insn-emit-%; @true
++$(INSNEMIT_SEQ_SRC:insn-emit-%.cc=s-insn-emit-%): s-insn-emit-%: s-tmp-emit
++ $(SHELL) $(srcdir)/../move-if-change tmp-emit-$*.cc insn-emit-$*.cc
++ $(STAMP) s-insn-emit-$*
++
+ # gencheck doesn't read the machine description, and the file produced
+ # doesn't use the insn-* convention.
++
++# --> s-check has prerequisite tree-check.h (though nothing to do)
+ 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 c43bde8174b..00672b18f72 100755
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -842,6 +842,7 @@ enable_gcov
+ enable_shared
+ enable_fixed_point
+ enable_decimal_float
++DEFAULT_INSNEMIT_PARTITIONS
+ DEFAULT_MATCHPD_PARTITIONS
+ with_float
+ with_cpu
+@@ -971,6 +972,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
+@@ -1839,6 +1841,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 :
+@@ -19923,7 +19943,7 @@ else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+-#line 19926 "configure"
++#line 19946 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -20029,7 +20049,7 @@ else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+-#line 20032 "configure"
++#line 20052 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+diff --git a/gcc/configure.ac b/gcc/configure.ac
+index fb8e32f8ee5..bc0ef734e6c 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 1ce0564076d..8d8a3c4aa80 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,17 +685,17 @@ 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;
+ bool used;
+
+- printf ("\n\nbool\nadded_clobbers_hard_reg_p (int insn_code_number)\n");
+- printf ("{\n");
+- printf (" switch (insn_code_number)\n");
+- printf (" {\n");
++ fprintf (file, "\n\nbool\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++)
+ {
+@@ -703,25 +704,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 = true;
+ }
+
+ if (used)
+- printf (" return %s;\n\n", clobber_p ? "true" : "false");
++ fprintf (file, " return %s;\n\n", clobber_p ? "true" : "false");
+ }
+
+- 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;
+@@ -746,12 +747,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,
+@@ -767,50 +768,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. */
+@@ -827,25 +828,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"
+@@ -853,12 +854,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) \
+@@ -868,86 +925,81 @@ 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;
+
+- 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");
++ int npatterns_per_file = npatterns;
++ if (!output_files.is_empty ())
++ npatterns_per_file = npatterns / output_files.length () + 1;
+
+- /* Read the machine description. */
++ gcc_assert (npatterns_per_file > 1);
+
+- md_rtx_info info;
++ /* Reverse so we can pop the first-added element. */
++ output_files.reverse ();
++
++ 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)
++ {
++ if (file)
++ 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
++ file = stdout;
+
+- 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 dd920d673b4..367ba1a30a4 100644
+--- a/gcc/gensupport.cc
++++ b/gcc/gensupport.cc
+@@ -3131,6 +3131,42 @@ 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;
++ class queue_elem *cur = define_attr_queue;
++ while (cur != NULL)
++ {
++ count++;
++ cur = cur->next;
++ }
++
++ cur = define_pred_queue;
++ while (cur != NULL)
++ {
++ count++;
++ cur = cur->next;
++ }
++
++ cur = define_insn_queue;
++ while (cur != NULL)
++ {
++ count++;
++ cur = cur->next;
++ }
++
++ cur = other_queue;
++ while (cur != NULL)
++ {
++ 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 7925e22ed41..7396118714b 100644
+--- a/gcc/gensupport.h
++++ b/gcc/gensupport.h
+@@ -130,6 +130,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 fd38818e3a3..46ab9065e3e 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 b309c9c3deb..2adcb58478f 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.41.0
+
+
+
diff --git a/14.0.0/gentoo/README.history b/14.0.0/gentoo/README.history
index 0e5fac9..fe5b568 100644
--- a/14.0.0/gentoo/README.history
+++ b/14.0.0/gentoo/README.history
@@ -1,7 +1,13 @@
+4 18 Oct 2023
+
+ + 75_all_PR54179_genemit-Split-insn-emit.cc-into-ten-files.patch
+
3 02 Oct 2023
+
U 26_all_enable-cet.patch
2 18 June 2023
+
- 09_all_nopie-all-flags.patch
1 23 April 2023