diff options
author | Sam James <sam@gentoo.org> | 2023-10-16 13:33:30 +0100 |
---|---|---|
committer | Sam James <sam@gentoo.org> | 2023-10-16 13:40:58 +0100 |
commit | cfe1a42149964e54a250698e9d8dc50f4745caf9 (patch) | |
tree | 107d08a4c6fbeae99c4f1b655ea9e2592d9961e7 /14.0.0 | |
parent | 13.2.0: backport insn-emit split patches (diff) | |
download | gcc-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.patch | 1453 | ||||
-rw-r--r-- | 14.0.0/gentoo/README.history | 6 |
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 |