On Thu, 2016-10-06 at 17:23 +0200, Bernd Schmidt wrote: > Let me just make a first pass over this for minor/obvious issues. > > > +we have little control of the input to that specific pass. We > > "control over" maybe?
Fixed. > > +The testsuite is below @file{gcc/testsuite/rtl.dg}. > > Not sure this needs to be in the manual (I have similar doubts about > the > entire motivation section, but I guess we can keep it). This is within the "internals" part of the manual; presumably the audience for that manual is gcc developers. > Also, "below"? Changed to "within". > > +/* rtl-error.c - Replacement for errors.c for use by RTL frontend > > + Copyright (C) 2016 Free Software Foundation, Inc. > > Why have this and not use the normal machinery? (see https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00489.html for discussion of that). > > + > > +static bool > > +rtl_langhook_handle_option ( > > + size_t scode, > > + const char *arg, > > + int value ATTRIBUTE_UNUSED, > > + int kind ATTRIBUTE_UNUSED, > > + location_t loc ATTRIBUTE_UNUSED, > > + const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED) > > Please line up the arguments, including the first, with the open > paren. Fixed. > For hooks I think we're converging towards just not naming unused > args. I removed the names (and ATTRIBUTE_UNUSED). > > + > > + /* If -fsingle-pass=PASS_NAME was provided, locate and run > > PASS_NAME > > + on cfun, as created above. */ > > Comment text indented too much. Fixed. > > +/* Implementation of LANG_HOOKS_TYPE_FOR_MODE, taken from Go > > frontend. */ > > + > > +static tree > > +rtl_langhook_type_for_mode (machine_mode mode, int unsignedp) > > +{ > > + tree type; > > + /* Go has no vector types. Build them here. FIXME: It does not > > + make sense for the middle-end to ask the frontend for a type > > + which the frontend does not support. However, at least for > > now > > + it is required. See PR 46805. */ > > Hmm, not sure it makes much sense to have comments referencing Go. Heh. Can you spot which frontend I used as a model? :) > > + if (VECTOR_MODE_P (mode)) > > + { > > + tree inner; > > + > > + inner = rtl_langhook_type_for_mode (GET_MODE_INNER (mode), > > unsignedp); > > + if (inner != NULL_TREE) > > + return build_vector_type_for_mode (inner, mode); > > + return NULL_TREE; > > + } > > + > > + // FIXME: This static_cast should be in machmode.h. > > + enum mode_class mc = static_cast<enum > > mode_class>(GET_MODE_CLASS(mode)); > > + if (mc == MODE_INT) > > + return rtl_langhook_type_for_size(GET_MODE_BITSIZE(mode), > > unsignedp); > > Also not really following our coding standards. Presumably this is > all > copied? Yes, from Go. I've fixed things up in the next version of the patch, and I'll work on a patch for Go to fix them up there. > > +#include <mpfr.h> > > The include list probably wants checking whether everything is really > necessary; this one stood out as a bit odd (several files). This was for the: /* The default precision for floating point numbers. This is used for floating point constants with abstract type. This may eventually be controllable by a command line option. */ mpfr_set_default_prec (256); call in rtl_langhook_init, again copied from Go. I can drop it. I went through the list of includes; doing so revealed that this code within rtl_langhook_parse_file: in_rtl_frontend_p = true; initialize_rtl (); init_emit (); init_varasm_status (); was redundant (we were also doing it in read_rtl_function_body; this code has gone through a *lot* of refactoring). So I've trimmed things quite a bit in rtl-frontend.c. When trimming the headers, I was able to eliminate rtl.h from the deps, so I was able to remove: /* Front ends normally should never have to include RTL headers. This is enforced in system.h by poisoning various header double-include protection defines. However, for obvious reasons, the RTL frontend needs RTL headers. Override this protection for this special case. */ #undef IN_GCC_FRONTEND > > + > > +#ifndef GCC_RUN_ONE_RTL_PASS_H > > +#define GCC_RUN_ONE_RTL_PASS_H > > + > > +extern void run_one_rtl_pass_by_name (const char *pass_name); > > + > > +#endif /* GCC_RUN_ONE_RTL_PASS_H */ > > Do we really need an entire header file for a single declaration? The problem I kept running into was that system.h has this: /* Front ends should never have to include middle-end headers. Enforce this by poisoning the header double-include protection defines. */ run_one_rtl_pass_by_name gets used by both the RTL frontend in this patch, and by cc1 in the followup __RTL patch (from c-parser.c), so whatever header it's in, it needs to be one that can be included by these frontend files with no rtl.h poisoning. This seems like a special-case, so it seemed to make sense to give it its own header. Is there a better place for it? Maybe pass_manager.h? Updated patch follows... gcc/ChangeLog: * Makefile.in (OBJS): Add run-one-rtl-pass.o. * doc/rtl-frontend.texi: New file. * doc/rtl.texi (RTL Representation): Add "RTL Frontend" to menu. Include rtl-frontend.texi. * gcc.c (default_compilers): Add a ".rtl" entry. * read-rtl-function.c (read_rtl_function_body): Set in_rtl_frontend_p. * rtl.c (in_rtl_frontend_p): New global. * rtl.h (in_rtl_frontend_p): New global decl. * run-one-rtl-pass.c: New file. * run-one-rtl-pass.h: New file. * toplev.c (compile_file): Bail out after the parse_file langhook if within the RTL frontend. gcc/rtl/ChangeLog: * ChangeLog: New file. * Make-lang.in: New file. * config-lang.in: New file. * lang-specs.h: New file. * lang.opt: New file. * rtl-errors.c: New file. * rtl-frontend.c: New file. gcc/testsuite/ChangeLog: * lib/rtl-dg.exp: New file. * rtl.dg/aarch64/asr_div1.rtl: New file. * rtl.dg/aarch64/pr71779.rtl: New file. * rtl.dg/cfg-extra-bb.rtl: New file. * rtl.dg/cfg-missing-bb.rtl: New file. * rtl.dg/good-include.rtl: New file. * rtl.dg/good-includee.md: New file. * rtl.dg/missing-include.rtl: New file. * rtl.dg/more-than-one-cfg.rtl: New file. * rtl.dg/rtl.exp: New file. * rtl.dg/test.c: New file. * rtl.dg/unknown-insn-uid.rtl: New file. * rtl.dg/unknown-rtx-code.rtl: New file. * rtl.dg/x86_64/dfinit.rtl: New file. * rtl.dg/x86_64/final.rtl: New file. * rtl.dg/x86_64/into-cfglayout.rtl: New file. * rtl.dg/x86_64/ira.rtl: New file. * rtl.dg/x86_64/pro_and_epilogue.rtl: New file. * rtl.dg/x86_64/vregs.rtl: New file. --- gcc/Makefile.in | 1 + gcc/doc/rtl-frontend.texi | 262 ++++++++++++++++++ gcc/doc/rtl.texi | 3 + gcc/gcc.c | 1 + gcc/read-rtl-function.c | 2 + gcc/rtl.c | 2 + gcc/rtl.h | 1 + gcc/rtl/Make-lang.in | 88 ++++++ gcc/rtl/config-lang.in | 36 +++ gcc/rtl/lang-specs.h | 25 ++ gcc/rtl/lang.opt | 33 +++ gcc/rtl/rtl-errors.c | 34 +++ gcc/rtl/rtl-frontend.c | 336 +++++++++++++++++++++++ gcc/run-one-rtl-pass.c | 119 ++++++++ gcc/run-one-rtl-pass.h | 25 ++ gcc/testsuite/lib/rtl-dg.exp | 64 +++++ gcc/testsuite/rtl.dg/aarch64/asr_div1.rtl | 32 +++ gcc/testsuite/rtl.dg/aarch64/pr71779.rtl | 44 +++ gcc/testsuite/rtl.dg/cfg-extra-bb.rtl | 12 + gcc/testsuite/rtl.dg/cfg-missing-bb.rtl | 16 ++ gcc/testsuite/rtl.dg/good-include.rtl | 6 + gcc/testsuite/rtl.dg/good-includee.md | 5 + gcc/testsuite/rtl.dg/missing-include.rtl | 1 + gcc/testsuite/rtl.dg/more-than-one-cfg.rtl | 7 + gcc/testsuite/rtl.dg/rtl.exp | 41 +++ gcc/testsuite/rtl.dg/test.c | 31 +++ gcc/testsuite/rtl.dg/unknown-insn-uid.rtl | 6 + gcc/testsuite/rtl.dg/unknown-rtx-code.rtl | 5 + gcc/testsuite/rtl.dg/x86_64/dfinit.rtl | 102 +++++++ gcc/testsuite/rtl.dg/x86_64/final.rtl | 58 ++++ gcc/testsuite/rtl.dg/x86_64/into-cfglayout.rtl | 91 ++++++ gcc/testsuite/rtl.dg/x86_64/ira.rtl | 91 ++++++ gcc/testsuite/rtl.dg/x86_64/pro_and_epilogue.rtl | 44 +++ gcc/testsuite/rtl.dg/x86_64/vregs.rtl | 88 ++++++ gcc/toplev.c | 7 + 35 files changed, 1719 insertions(+) create mode 100644 gcc/doc/rtl-frontend.texi create mode 100644 gcc/rtl/Make-lang.in create mode 100644 gcc/rtl/config-lang.in create mode 100644 gcc/rtl/lang-specs.h create mode 100644 gcc/rtl/lang.opt create mode 100644 gcc/rtl/rtl-errors.c create mode 100644 gcc/rtl/rtl-frontend.c create mode 100644 gcc/run-one-rtl-pass.c create mode 100644 gcc/run-one-rtl-pass.h create mode 100644 gcc/testsuite/lib/rtl-dg.exp create mode 100644 gcc/testsuite/rtl.dg/aarch64/asr_div1.rtl create mode 100644 gcc/testsuite/rtl.dg/aarch64/pr71779.rtl create mode 100644 gcc/testsuite/rtl.dg/cfg-extra-bb.rtl create mode 100644 gcc/testsuite/rtl.dg/cfg-missing-bb.rtl create mode 100644 gcc/testsuite/rtl.dg/good-include.rtl create mode 100644 gcc/testsuite/rtl.dg/good-includee.md create mode 100644 gcc/testsuite/rtl.dg/missing-include.rtl create mode 100644 gcc/testsuite/rtl.dg/more-than-one-cfg.rtl create mode 100644 gcc/testsuite/rtl.dg/rtl.exp create mode 100644 gcc/testsuite/rtl.dg/test.c create mode 100644 gcc/testsuite/rtl.dg/unknown-insn-uid.rtl create mode 100644 gcc/testsuite/rtl.dg/unknown-rtx-code.rtl create mode 100644 gcc/testsuite/rtl.dg/x86_64/dfinit.rtl create mode 100644 gcc/testsuite/rtl.dg/x86_64/final.rtl create mode 100644 gcc/testsuite/rtl.dg/x86_64/into-cfglayout.rtl create mode 100644 gcc/testsuite/rtl.dg/x86_64/ira.rtl create mode 100644 gcc/testsuite/rtl.dg/x86_64/pro_and_epilogue.rtl create mode 100644 gcc/testsuite/rtl.dg/x86_64/vregs.rtl diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 2147aee..c6f86db 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1432,6 +1432,7 @@ OBJS = \ rtlhash.o \ rtlanal.o \ rtlhooks.o \ + run-one-rtl-pass.o \ sbitmap.o \ sched-deps.o \ sched-ebb.o \ diff --git a/gcc/doc/rtl-frontend.texi b/gcc/doc/rtl-frontend.texi new file mode 100644 index 0000000..393630d --- /dev/null +++ b/gcc/doc/rtl-frontend.texi @@ -0,0 +1,262 @@ +@node RTL Frontend +@section RTL Frontend + +@subsection Purpose + +Historically GCC testing has been done by providing source files +to be built with various command-line options (via DejaGnu +directives), dumping state at pertinent places, and verifying +properties of the state via these dumps. + +A strength of this approach is that we have excellent integration +testing, as every test case exercises the toolchain as a whole, but +it has the drawback that when testing a specific pass, +we have little control over the input to that specific pass. We +provide input, and the various passes transform the state +of the internal representation: + +@smallexample + INPUT -> PASS-1 -> STATE-1 -> PASS-2 -> STATE-2 -> ... + -> etc -> + -> ... -> PASS-n-1 -> STATE-n-1 -> PASS-n -> STATE-n + ^ ^ ^ + | | Output from the pass + | The pass we care about + The actual input to the pass +@end smallexample + +so the intervening passes before "PASS-n" could make changes to the +IR that affect the input seen by our pass ("STATE-n-1" above). This +can break our test cases, sometimes in a form that's visible, +sometimes invisibly (e.g. where a test case silently stops providing +coverage). + +The aim of the RTL frontend is to provide a convenient way to test +individual passes in the backend, by loading dumps of specific RTL +state (possibly edited by hand), and then running just one specific +pass on them, so that we effectively have this: + +@smallexample + INPUT -> PASS-n -> OUTPUT +@end smallexample + +thus fixing the problem above. + +The goal is to make it easy to write more fine-grained and +robust test coverage for the RTL phase of GCC. However this should be +seen as @emph{complementary} to the existing "integrated testing" approach: +patches should include both RTL frontend tests @emph{and} integrated tests, +to avoid regressing the great integration testing we currently have. + +The idea is to use the existing dump format as a input format, since +presumably existing GCC developers are very familiar with the dump +format. + +One other potential benefit of this approach is to allow unit-testing +of machine descriptions - we could provide specific RTL fragments, +and have the @file{rtl.dg} testsuite directly verify that we recognize all +instructions and addressing modes that a given target ought to support. + +@subsection Structure + +The RTL frontend is similar to a regular frontend: a @file{gcc/rtl} +subdirectory within the source tree contains frontend-specific hooks. +These provide a new @code{rtl} frontend, which can be optionally +enabled at configuration time within @option{--enable-languages}. + +If enabled, it builds an @command{rtl1} binary, which is invoked by the +@command{gcc} driver on files with a @file{.rtl} extension. + +The testsuite is within @file{gcc/testsuite/rtl.dg}. + +@subsection Input format + +Input files should have a @file{.rtl} extension. + +The parser accepts the format emitted by @code{print_rtx_function}: + +@smallexample +(function "times_two" + (insn-chain + (note 1 0 4 (nil) NOTE_INSN_DELETED) + (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) + (insn 2 4 3 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32]) + (reg:SI 5 di [ i ])) t.c:2 -1 + (nil)) + (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG) + (insn 6 3 7 2 (set (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -4 [0xfffffffffffffffc])) + [1 i+0 S4 A32])) t.c:3 -1 + (nil)) + (insn 7 6 10 2 (parallel [ + (set (reg:SI 87 [ _2 ]) + (ashift:SI (reg:SI 89) + (const_int 1 [0x1]))) + (clobber (reg:CC 17 flags)) + ]) t.c:3 -1 + (expr_list:REG_EQUAL + (ashift:SI (mem/c:SI + (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -4 [0xfffffffffffffffc])) + [1 i+0 S4 A32]) + (const_int 1 [0x1])) + (nil))) + (insn 10 7 14 2 (set (reg:SI 88 [ <retval> ]) + (reg:SI 87 [ _2 ])) t.c:3 -1 + (nil)) + (insn 14 10 15 2 (set (reg/i:SI 0 ax) + (reg:SI 88 [ <retval> ])) t.c:4 -1 + (nil)) + (insn 15 14 0 2 (use (reg/i:SI 0 ax)) t.c:4 -1 + (nil)) + ) ;; insn-chain + (cfg + (bb 0 + (edge 0 2 (flags 0x1)) + ) ;; bb + (bb 2 + (edge 2 1 (flags 0x1)) + ) ;; bb + (bb 1 + ) ;; bb + ) ;; cfg + (crtl + (return_rtx + (reg/i:SI 0 ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "times_two" +@end smallexample + +To make it easier to hand-edit file, the @code{(cfg)} and @code{(crtl)} +directives can be omitted. If the @code{(cfg)} directive is omitted, +then the parser frontend reconstructs the edges implied by jump +instructions. This ought to work OK for ``cfgrtl'' mode, but isn't +going to work for ``cfglayout'' mode - in the latter, unconditional jumps +are represented purely by edges in the CFG, and so this information must +be provided by a @code{(cfg)} directive. See +@uref{https://gcc.gnu.org/wiki/cfglayout_mode} for more information +on ``cfgrtl'' mode vs ``cfglayout mode''. + +@subsection Register numbers + +print_rtx will print a name for hard and virtual registers +after the register number, and no name for pseudos. + +The parser looks for a name after the number. If there is, such as: + +@smallexample + (reg/f:DI 82 virtual-stack-vars) +@end smallexample + +it assumes a hard or virtual reg, and tries to parse the name: + +@itemize @bullet + +@item +if the name is recognized, it uses the target's current number for that +name (future-proofing virtuals against @file{.md} changes) + +@item +if the name is not recognized, issue a fatal error (it's probably a +typo, or maybe a backport from a future version of gcc, or a target +incompatibility) + +@item +if there's no name, it assumes it's a pseudo. If any such the registers +appear in the dump with a register number <= @code{LAST_VIRTUAL_REGISTER}, +then all such pseudos have their register number adjusted by an offset so +that all are > @code{LAST_VIRTUAL_REGISTER}, to future-proof against +@file{.md} changes, and to allow some measure of target-independence. +Otherwise, the numbering is left untouched (the common case). + +@end itemize + + +@subsection Limitations + +@itemize @bullet + +@item +It's a work-in-progress. There will be bugs. + + +@item +The existing RTL code is structured around a single function being +optimized, so, as a simplification, the RTL frontend can only handle +one function per input file. + +@item +The RTL frontend doesn't have any knowledge of parameters, types, +locals, globals, etc. It creates a single function. +The function is currently hardcoded to have this signature: + + int NAME (int, int, int); + +since there's no syntax for specify otherwise, and we need to provide +a @code{FUNCTION_DECL} tree when building a function object (by calling +@code{allocate_struct_function}). + +@item +Similarly, there are no types beyond the built-in ones; all expressions +are treated as being of type @code{int}. I suspect that this approach +will be too simplistic when it comes to e.g. aliasing. + +@item +There's no support for running more than one pass; fixing this would +require being able to run passes from a certain point onwards. + +@item +Roundtripping of recognized instructions may be an issue (i.e. those +with @code{INSN_CODE} != -1), such as the ``667 @{jump@}'' in the +following: + +@smallexample + (jump_insn 50 49 51 10 + (set (pc) + (label_ref:DI 59)) ../../src/test-switch.c:18 667 @{jump@} + (nil) -> 59) +@end smallexample + +since the integer ID can change when the @file{.md} files are changed +(and the associated pattern name is very much target-specific). +Currently the loaded ignores them, resetting the @code{INSN_CODE} to -1. +An alternative strategy would be to lookup the insn by name, and +use the correct @code{INSN_CODE} (future-proofing against @file{.md} +changes, but making dumps more target-specific). + +@end itemize + +@subsection TODO items + +@itemize @bullet + +@item +test with other architectures + +@item +example with "-g" + +@item +implement a fuzzer (or use AFL on the existing test cases) + +@end itemize + +@subsection Cross-arch issues + +Test cases are likely to be target-specific. Examples include: + +@itemize @bullet + +@item +unknown modes e.g. this from x86_64: + +@smallexample + (reg:CCGC 17 flags) +@end smallexample + +fails on aarch64 due to the lack of a "CCGC" mode. + +@end itemize diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 692d9b5..9e86df9 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -41,6 +41,7 @@ form uses nested parentheses to indicate the pointers in the internal form. * Calls:: RTL representation of function call insns. * Sharing:: Some expressions are unique; others *must* be copied. * Reading RTL:: Reading textual RTL from a file. +* RTL Frontend:: Testing GCC using RTL dumps. @end menu @node RTL Objects @@ -4236,3 +4237,5 @@ The proper way to interface GCC to a new language front end is with the ``tree'' data structure, described in the files @file{tree.h} and @file{tree.def}. The documentation for this structure (@pxref{GENERIC}) is incomplete. + +@include rtl-frontend.texi diff --git a/gcc/gcc.c b/gcc/gcc.c index fd2b182..7a21a74 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -1296,6 +1296,7 @@ static const struct compiler default_compilers[] = {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0}, {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0}, {".go", "#Go", 0, 1, 0}, + {".rtl", "#RTL", 0, 1, 0}, /* Next come the entries for C. */ {".c", "@c", 0, 0, 1}, {"@c", diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c index 0cd34d4..0723585 100644 --- a/gcc/read-rtl-function.c +++ b/gcc/read-rtl-function.c @@ -1801,6 +1801,8 @@ read_rtl_function_body (int argc, const char **argv, function_reader_policy *policy, int *out_pseudo_offset) { + in_rtl_frontend_p = true; + initialize_rtl (); init_emit (); init_varasm_status (); diff --git a/gcc/rtl.c b/gcc/rtl.c index a445cdc..9729c82 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -878,3 +878,5 @@ rtl_check_failed_flag (const char *name, const_rtx r, const char *file, name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line); } #endif /* ENABLE_RTL_FLAG_CHECKING */ + +bool in_rtl_frontend_p = false; diff --git a/gcc/rtl.h b/gcc/rtl.h index 0741fc6..813d7a9 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -3748,5 +3748,6 @@ struct GTY(()) cgraph_rtl_info { unsigned function_used_regs_valid: 1; }; +extern bool in_rtl_frontend_p; #endif /* ! GCC_RTL_H */ diff --git a/gcc/rtl/Make-lang.in b/gcc/rtl/Make-lang.in new file mode 100644 index 0000000..74d0a3e --- /dev/null +++ b/gcc/rtl/Make-lang.in @@ -0,0 +1,88 @@ +# Make-lang.in -- Top level -*- makefile -*- fragment for RTL frontend. + +# Copyright (C) 2016 Free Software Foundation, Inc. + +# This file is part of GCC. + +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. + +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# This file provides the language dependent support in the main Makefile. + +# The name for selecting the RTL frontend in LANGUAGES. +rtl: rtl1$(exeext) + +.PHONY: rtl + +# Use strict warnings. +rtl-warn = $(STRICT_WARN) + +rtl_OBJS = \ + rtl/rtl-errors.o \ + rtl/rtl-frontend.o + +rtl1$(exeext): $(rtl_OBJS) attribs.o $(BACKEND) $(LIBDEPS) + +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ + $(rtl_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS) + +# Build hooks: + +rtl.all.cross: +rtl.start.encap: +rtl.rest.encap: +rtl.info: +rtl.dvi: +rtl.html: +rtl.pdf: +rtl.man: + +lang_checks += check-rtl +lang_checks_parallelized += check-rtl +check_rtl_parallelize = 10 + +# Install hooks. + +rtl.install-common: +rtl.install-man: +rtl.install-plugin: +rtl.install-info: +rtl.install-pdf: +rtl.install-html: +rtl.uninstall: + +# Clean hooks. + +rtl.mostlyclean: + -rm -f rtl1$(exeext) + -rm -f rtl/*$(objext) + -rm -f rtl/*$(coverageexts) +rtl.clean: +rtl.distclean: + -rm -f rtl/config.status rtl/Makefile +rtl.maintainer-clean: + +# Stage hooks. + +rtl.stage1: stage1-start + -mv rtl/*$(objext) stage1/rtl +rtl.stage2: stage2-start + -mv rtl/*$(objext) stage2/rtl +rtl.stage3: stage3-start + -mv rtl/*$(objext) stage3/rtl +rtl.stage4: stage4-start + -mv rtl/*$(objext) stage4/rtl +rtl.stageprofile: stageprofile-start + -mv rtl/*$(objext) stageprofile/rtl +rtl.stagefeedback: stagefeedback-start + -mv rtl/*$(objext) stagefeedback/rtl diff --git a/gcc/rtl/config-lang.in b/gcc/rtl/config-lang.in new file mode 100644 index 0000000..3b101ce --- /dev/null +++ b/gcc/rtl/config-lang.in @@ -0,0 +1,36 @@ +# config-lang.in -- Top level configure fragment for RTL frontend. + +# Copyright (C) 2016 Free Software Foundation, Inc. + +# This file is part of GCC. + +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. + +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# Configure looks for the existence of this file to auto-config each language. +# We define several parameters used by configure: +# +# language - name of language as it would appear in $(LANGUAGES) +# compilers - value to add to $(COMPILERS) + +language="rtl" + +compilers="rtl1\$(exeext)" + +target_libs="" + +gtfiles="\$(srcdir)/rtl/rtl-frontend.c" + +# Do not build by default. +build_by_default="no" diff --git a/gcc/rtl/lang-specs.h b/gcc/rtl/lang-specs.h new file mode 100644 index 0000000..2af33ab --- /dev/null +++ b/gcc/rtl/lang-specs.h @@ -0,0 +1,25 @@ +/* lang-specs.h -- gcc driver specs for RTL frontend. + Copyright (C) 2016 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* This is the contribution to the `default_compilers' array in gcc.c + for the RTL frontend. */ + +{".rtl", "@RTL", 0, 1, 0}, +{"@RTL", "rtl1 %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}", + 0, 1, 0}, diff --git a/gcc/rtl/lang.opt b/gcc/rtl/lang.opt new file mode 100644 index 0000000..2515ff3 --- /dev/null +++ b/gcc/rtl/lang.opt @@ -0,0 +1,33 @@ +; lang.opt -- Options for the gcc RTL front end. + +; Copyright (C) 2016 Free Software Foundation, Inc. +; +; This file is part of GCC. +; +; GCC is free software; you can redistribute it and/or modify it under +; the terms of the GNU General Public License as published by the Free +; Software Foundation; either version 3, or (at your option) any later +; version. +; +; GCC is distributed in the hope that it will be useful, but WITHOUT ANY +; WARRANTY; without even the implied warranty of MERCHANTABILITY or +; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +; for more details. +; +; You should have received a copy of the GNU General Public License +; along with GCC; see the file COPYING3. If not see +; <http://www.gnu.org/licenses/>. + +; See the GCC internals manual for a description of this file's format. + +; Please try to keep this file in ASCII collating order. + +Language +RTL + +fsingle-pass= +RTL Joined RejectNegative +After loading the RTL input file, run the specified pass on it. + + +; This comment is to ensure we retain the blank line above. diff --git a/gcc/rtl/rtl-errors.c b/gcc/rtl/rtl-errors.c new file mode 100644 index 0000000..1859cb6 --- /dev/null +++ b/gcc/rtl/rtl-errors.c @@ -0,0 +1,34 @@ +/* rtl-error.c - Replacement for errors.c for use by RTL frontend + Copyright (C) 2016 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "errors.h" + +/* Stub implementation of RTL error-handling for use by RTL frontend. */ + +void +fatal (const char *, ...) +{ + abort (); +} + +int have_error; + diff --git a/gcc/rtl/rtl-frontend.c b/gcc/rtl/rtl-frontend.c new file mode 100644 index 0000000..9df8c0e --- /dev/null +++ b/gcc/rtl/rtl-frontend.c @@ -0,0 +1,336 @@ +/* rtl-frontend.c - Top-level of RTL frontend + Copyright (C) 2016 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tree.h" +#include "diagnostic.h" +#include "opts.h" +#include "fold-const.h" +#include "stor-layout.h" +#include "debug.h" +#include "convert.h" +#include "langhooks.h" +#include "langhooks-def.h" +#include "read-rtl-function.h" +#include "run-one-rtl-pass.h" + +/* Language-dependent contents of a type. */ + +struct GTY(()) lang_type +{ + char dummy; +}; + +/* Language-dependent contents of a decl. */ + +struct GTY(()) lang_decl +{ + char dummy; +}; + +/* Language-dependent contents of an identifier. This must include a + tree_identifier. */ + +struct GTY(()) lang_identifier +{ + struct tree_identifier common; +}; + +/* The resulting tree type. */ + +union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), + chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) +lang_tree_node +{ + union tree_node GTY((tag ("0"), + desc ("tree_node_structure (&%h)"))) generic; + struct lang_identifier GTY((tag ("1"))) identifier; +}; + +/* We don't use language_function. */ + +struct GTY(()) language_function +{ + int dummy; +}; + +/* Language hooks. */ + +/* Implementation of LANG_HOOKS_INIT for the RTL frontend. */ + +static bool +rtl_langhook_init (void) +{ + build_common_tree_nodes (false); + + /* I don't know why this has to be done explicitly. */ + void_list_node = build_tree_list (NULL_TREE, void_type_node); + + build_common_builtin_nodes (); + + return true; +} + +/* Implementation of LANG_HOOKS_OPTION_LANG_MASK for the RTL frontend. */ + +static unsigned int +rtl_langhook_option_lang_mask (void) +{ + return CL_RTL; +} + +/* The value of "-fsingle-pass=", if any. */ + +static const char *single_pass_name = NULL; + +/* Implementation of LANG_HOOKS_HANDLE_OPTION for the RTL frontend. */ + +static bool +rtl_langhook_handle_option (size_t scode, const char *arg, int, int, + location_t, const struct cl_option_handlers *) +{ + enum opt_code code = (enum opt_code) scode; + + switch (code) + { + case OPT_fsingle_pass_: + single_pass_name = xstrdup (arg); + break; + + default: + break; + } + return true; +} + +/* Implementation of LANG_HOOKS_PARSE_FILE for the RTL frontend. */ + +static void +rtl_langhook_parse_file (void) +{ + auto_vec<const char *> argv (num_in_fnames + 1); + argv.safe_push (progname); + for (unsigned i = 0; i < num_in_fnames; i++) + argv.safe_push (in_fnames[i]); + if (!read_rtl_function_body (argv.length (), argv.address (), NULL, NULL, + NULL)) + return; + + /* If -fsingle-pass=PASS_NAME was provided, locate and run PASS_NAME + on cfun, as created above. */ + if (single_pass_name) + run_one_rtl_pass_by_name (single_pass_name); +} + +/* Implementation of LANG_HOOKS_TYPE_FOR_SIZE, taken from Go frontend. */ + +static tree +rtl_langhook_type_for_size (unsigned int bits, int unsignedp) +{ + tree type; + if (unsignedp) + { + if (bits == INT_TYPE_SIZE) + type = unsigned_type_node; + else if (bits == CHAR_TYPE_SIZE) + type = unsigned_char_type_node; + else if (bits == SHORT_TYPE_SIZE) + type = short_unsigned_type_node; + else if (bits == LONG_TYPE_SIZE) + type = long_unsigned_type_node; + else if (bits == LONG_LONG_TYPE_SIZE) + type = long_long_unsigned_type_node; + else + type = make_unsigned_type(bits); + } + else + { + if (bits == INT_TYPE_SIZE) + type = integer_type_node; + else if (bits == CHAR_TYPE_SIZE) + type = signed_char_type_node; + else if (bits == SHORT_TYPE_SIZE) + type = short_integer_type_node; + else if (bits == LONG_TYPE_SIZE) + type = long_integer_type_node; + else if (bits == LONG_LONG_TYPE_SIZE) + type = long_long_integer_type_node; + else + type = make_signed_type(bits); + } + return type; +} + +/* Implementation of LANG_HOOKS_TYPE_FOR_MODE, taken from Go frontend. */ + +static tree +rtl_langhook_type_for_mode (machine_mode mode, int unsignedp) +{ + tree type; + + enum mode_class mc = GET_MODE_CLASS (mode); + if (mc == MODE_INT) + return rtl_langhook_type_for_size (GET_MODE_BITSIZE (mode), unsignedp); + else if (mc == MODE_FLOAT) + { + switch (GET_MODE_BITSIZE (mode)) + { + case 32: + return float_type_node; + case 64: + return double_type_node; + default: + // We have to check for long double in order to support + // i386 excess precision. + if (mode == TYPE_MODE (long_double_type_node)) + return long_double_type_node; + } + } + else if (mc == MODE_COMPLEX_FLOAT) + { + switch (GET_MODE_BITSIZE (mode)) + { + case 64: + return complex_float_type_node; + case 128: + return complex_double_type_node; + default: + // We have to check for long double in order to support + // i386 excess precision. + if (mode == TYPE_MODE(complex_long_double_type_node)) + return complex_long_double_type_node; + } + } + +#if HOST_BITS_PER_WIDE_INT >= 64 + /* The middle-end and some backends rely on TImode being supported + for 64-bit HWI. */ + if (mode == TImode) + { + type = build_nonstandard_integer_type (GET_MODE_BITSIZE (TImode), + unsignedp); + if (type && TYPE_MODE (type) == TImode) + return type; + } +#endif + return NULL_TREE; +} + +/* Implementation of LANG_HOOKS_BUILTIN_FUNCTION. */ + +static tree +rtl_langhook_builtin_function (tree decl) +{ + return decl; +} + +/* Implementation of LANG_HOOKS_GLOBAL_BINDINGS_P. + Return true if we are in the global binding level. */ + +static bool +rtl_langhook_global_bindings_p (void) +{ + return current_function_decl == NULL_TREE; +} + +/* Implementation of LANG_HOOKS_PUSHDECL. */ + +static tree +rtl_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED) +{ + gcc_unreachable (); +} + +/* Implementation of LANG_HOOKS_GETDECLS. */ + +static tree +rtl_langhook_getdecls (void) +{ + return NULL; +} + +/* Functions called directly by the generic backend. */ + +/* Implementation of "convert" taken from the Go frontend. */ + +tree +convert (tree type, tree expr) +{ + if (type == error_mark_node + || expr == error_mark_node + || TREE_TYPE (expr) == error_mark_node) + return error_mark_node; + + if (type == TREE_TYPE (expr)) + return expr; + + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) + return fold_convert (type, expr); + + switch (TREE_CODE (type)) + { + case VOID_TYPE: + case BOOLEAN_TYPE: + return fold_convert (type, expr); + case INTEGER_TYPE: + return fold (convert_to_integer (type, expr)); + case POINTER_TYPE: + return fold (convert_to_pointer (type, expr)); + case REAL_TYPE: + return fold (convert_to_real (type, expr)); + case COMPLEX_TYPE: + return fold (convert_to_complex (type, expr)); + default: + break; + } + + gcc_unreachable (); +} + +#undef LANG_HOOKS_NAME +#undef LANG_HOOKS_INIT +#undef LANG_HOOKS_OPTION_LANG_MASK +#undef LANG_HOOKS_HANDLE_OPTION +#undef LANG_HOOKS_PARSE_FILE +#undef LANG_HOOKS_TYPE_FOR_MODE +#undef LANG_HOOKS_TYPE_FOR_SIZE +#undef LANG_HOOKS_BUILTIN_FUNCTION +#undef LANG_HOOKS_GLOBAL_BINDINGS_P +#undef LANG_HOOKS_PUSHDECL +#undef LANG_HOOKS_GETDECLS + +#define LANG_HOOKS_NAME "GCC RTL frontend" +#define LANG_HOOKS_INIT rtl_langhook_init +#define LANG_HOOKS_OPTION_LANG_MASK rtl_langhook_option_lang_mask +#define LANG_HOOKS_HANDLE_OPTION rtl_langhook_handle_option +#define LANG_HOOKS_PARSE_FILE rtl_langhook_parse_file +#define LANG_HOOKS_TYPE_FOR_MODE rtl_langhook_type_for_mode +#define LANG_HOOKS_TYPE_FOR_SIZE rtl_langhook_type_for_size +#define LANG_HOOKS_BUILTIN_FUNCTION rtl_langhook_builtin_function +#define LANG_HOOKS_GLOBAL_BINDINGS_P rtl_langhook_global_bindings_p +#define LANG_HOOKS_PUSHDECL rtl_langhook_pushdecl +#define LANG_HOOKS_GETDECLS rtl_langhook_getdecls + +struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; + +#include "gt-rtl-rtl-frontend.h" +#include "gtype-rtl.h" diff --git a/gcc/run-one-rtl-pass.c b/gcc/run-one-rtl-pass.c new file mode 100644 index 0000000..ced81a2 --- /dev/null +++ b/gcc/run-one-rtl-pass.c @@ -0,0 +1,119 @@ +/* run-one-rtl-pass.c - Run just one RTL pass + Copyright (C) 2016 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tree.h" +#include "gimple-expr.h" +#include "diagnostic.h" +#include "opts.h" +#include "fold-const.h" +#include "gimplify.h" +#include "stor-layout.h" +#include "debug.h" +#include "convert.h" +#include "langhooks.h" +#include "langhooks-def.h" +#include "common/common-target.h" +#include "read-md.h" +#include <mpfr.h> +#include "rtl.h" +#include "cfghooks.h" +#include "stringpool.h" +#include "function.h" +#include "tree-cfg.h" +#include "cfg.h" +#include "basic-block.h" +#include "cfgrtl.h" +#include "emit-rtl.h" +#include "cgraph.h" +#include "tree-pass.h" +#include "context.h" +#include "pass_manager.h" +#include "toplev.h" +#include "bitmap.h" +#include "df.h" +#include "regs.h" +#include "varasm.h" +#include "insn-addr.h" + +/* Locate and run PASS_NAME on cfun. */ + +void +run_one_rtl_pass_by_name (const char *pass_name) +{ + opt_pass *pass = g->get_passes ()->get_pass_by_name (pass_name); + if (!pass) + { + error_at (UNKNOWN_LOCATION, "unrecognized pass: %qs", pass_name); + return; + } + + /* Forcibly create the dataflow instance. We'll need to do this on passes + that normally occur after pass_df_initialize/pass_df_initialize_no_opt. */ + /* FIXME: better conditional logic here. */ + if (0 == strcmp (pass_name, "rtl-cse1") + || 0 == strcmp (pass_name, "rtl-fwprop1") + || 0 == strcmp (pass_name, "rtl-combine") + || 0 == strcmp (pass_name, "rtl-ira") + || 0 == strcmp (pass_name, "rtl-reload") + || 0 == strcmp (pass_name, "rtl-pro_and_epilogue")) + { + opt_pass *df_pass = g->get_passes ()->get_pass_by_name ("rtl-dfinit"); + gcc_assert (df_pass); + current_function_decl = cfun->decl; + df_pass->execute (cfun); + + /* The dataflow instance should now exist. */ + gcc_assert (df); + + df_analyze (); + } + + /* Ensure reg_renumber is set up. */ + resize_reg_info (); + + max_regno = max_reg_num (); + + /* Pass "reload" sets the global "reload_completed", and many things + depend on this (e.g. instructions in .md files). */ + /* FIXME: better conditional logic here. */ + if (0 == strcmp (pass_name, "rtl-final")) + reload_completed = 1; + + /* The INSN_ADDRESSES vec is normally set up by shorten_branches; we must + manually set it up for passes that run after this. */ + /* FIXME: better conditional logic here. */ + if (0 == strcmp (pass_name, "rtl-final")) + INSN_ADDRESSES_ALLOC (get_max_uid ()); + + /* Run the user-specified pass. */ + bitmap_obstack_initialize (NULL); + bitmap_obstack_initialize (®_obstack); + pass_init_dump_file (pass); + current_function_decl = cfun->decl; + pass->execute (cfun); + current_function_decl = NULL; + if (dump_file) + print_rtl_with_bb (dump_file, get_insns (), dump_flags); + pass_fini_dump_file (pass); + bitmap_obstack_release (®_obstack); +} diff --git a/gcc/run-one-rtl-pass.h b/gcc/run-one-rtl-pass.h new file mode 100644 index 0000000..40d60ba --- /dev/null +++ b/gcc/run-one-rtl-pass.h @@ -0,0 +1,25 @@ +/* run-one-rtl-pass.h - Run just one RTL pass + Copyright (C) 2016 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_RUN_ONE_RTL_PASS_H +#define GCC_RUN_ONE_RTL_PASS_H + +extern void run_one_rtl_pass_by_name (const char *pass_name); + +#endif /* GCC_RUN_ONE_RTL_PASS_H */ diff --git a/gcc/testsuite/lib/rtl-dg.exp b/gcc/testsuite/lib/rtl-dg.exp new file mode 100644 index 0000000..8aa5943 --- /dev/null +++ b/gcc/testsuite/lib/rtl-dg.exp @@ -0,0 +1,64 @@ +# Copyright (C) 1997, 1999, 2000, 2003, 2007 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# Define rtl callbacks for dg.exp. + +# Load support procs. +load_lib gcc-defs.exp + +proc rtl_target_compile { source dest type options } { + set result [target_compile $source $dest $type $options] + return $result +} + +load_lib gcc-dg.exp + +proc rtl-dg-test { prog do_what extra_tool_flags } { + verbose "rtl-dg-test (rtl-dg.exp):" 3 + verbose " prog: $prog" 3 + verbose " do_what: $do_what" 3 + verbose " extra_tool_flags: $extra_tool_flags" 3 + + return [gcc-dg-test-1 rtl_target_compile $prog $do_what $extra_tool_flags] +} + + +proc rtl-dg-prune { system text } { + return [gcc-dg-prune $system $text] +} + +# Modified dg-runtest that runs tests in both C++98 and C++11 modes +# unless they specifically specify one or the other. +proc rtl-dg-runtest { testcases default-extra-flags } { + global runtests + + foreach test $testcases { + # look if this is dg-do-run test, in which case + # we cycle through the option list, otherwise we don't + if [expr [search_for $test "dg-do run"]] { + set option_list $TORTURE_OPTIONS + } else { + set option_list [list { -O } ] + } + + set nshort [file tail [file dirname $test]]/[file tail $test] + + foreach flags $option_list { + verbose "Testing $nshort, $flags" 1 + dg-test $test $flags ${default-extra-flags} + } + } +} diff --git a/gcc/testsuite/rtl.dg/aarch64/asr_div1.rtl b/gcc/testsuite/rtl.dg/aarch64/asr_div1.rtl new file mode 100644 index 0000000..0eafab3 --- /dev/null +++ b/gcc/testsuite/rtl.dg/aarch64/asr_div1.rtl @@ -0,0 +1,32 @@ +;; { dg-do compile { target aarch64-*-* } } +;; { dg-options "-mtune=cortex-a53 -fsingle-pass=rtl-combine -fdump-rtl-combine" } + +;; Taken from +;; gcc/testsuite/gcc.dg/asr_div1.c -O2 -fdump-rtl-all -mtune=cortex-a53 +;; for aarch64, hand editing the prev/next insns to 0 as needed, and +;; editing whitespace to avoid over-long lines. */ + +(function "f1" + (insn-chain + +(insn 8 0 9 2 (set (reg:DI 78) + (lshiftrt:DI (reg:DI 76) + (const_int 32 [0x20]))) + ../../src/gcc/testsuite/gcc.dg/asr_div1.c:14 + 641 {*aarch64_lshr_sisd_or_int_di3} + (expr_list:REG_DEAD (reg:DI 76) + (nil))) +(insn 9 8 0 2 (set (reg:SI 79) + (ashiftrt:SI (subreg:SI (reg:DI 78) 0) + (const_int 3 [0x3]))) + ../../src/gcc/testsuite/gcc.dg/asr_div1.c:14 + 642 {*aarch64_ashr_sisd_or_int_si3} + (expr_list:REG_DEAD (reg:DI 78) + (nil))) + + ) ;; insn-chain +) ;; function + +;; Verify that insns 8 and 9 get combined into a shift of 35 (0x23) +;; { dg-final { scan-rtl-dump "allowing combination of insns 8 and 9" "combine" } } +;; { dg-final { scan-rtl-dump "modifying insn i3 9: r79:SI#0=r76:DI>>0x23" "combine" } } diff --git a/gcc/testsuite/rtl.dg/aarch64/pr71779.rtl b/gcc/testsuite/rtl.dg/aarch64/pr71779.rtl new file mode 100644 index 0000000..96f6e3d --- /dev/null +++ b/gcc/testsuite/rtl.dg/aarch64/pr71779.rtl @@ -0,0 +1,44 @@ +;; { dg-do compile { target aarch64-*-* } } +;; { dg-options "-fsingle-pass=rtl-cse1 -fdump-rtl-cse1" } + +;; Dump taken from comment 2 of PR 71779, of +;; "...the relevant memory access coming out of expand" +;; with basic block IDs added, and prev/next insns set to +;; 0 at ends, and 'p' added to pseudo regnos. + +(function "fragment" + (insn-chain + +;; MEM[(struct isl_obj *)&obj1] = &isl_obj_map_vtable; +(insn 1045 0 1046 2 (set (reg:SI 480) + (high:SI (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + <var_decl 0x7fa0363ea240 isl_obj_map_vtable>))) + y.c:12702 -1 + (nil)) +(insn 1046 1045 1047 2 (set (reg/f:SI 479) + (lo_sum:SI (reg:SI 480) + (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + <var_decl 0x7fa0363ea240 isl_obj_map_vtable>))) + y.c:12702 -1 + (expr_list:REG_EQUAL (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + <var_decl 0x7fa0363ea240 isl_obj_map_vtable>) + (nil))) +(insn 1047 1046 1048 2 (set (reg:DI 481) + (subreg:DI (reg/f:SI 479) 0)) y.c:12702 -1 + (nil)) +(insn 1048 1047 1049 2 (set (zero_extract:DI (reg/v:DI 191 [ obj1D.17368 ]) + (const_int 32 [0x20]) + (const_int 0 [0])) + (reg:DI 481)) y.c:12702 -1 + (nil)) +;; Extra insn, to avoid all of the above from being deleted by DCE +(insn 1049 1048 0 2 (set (mem:DI (reg:DI 191) [1 i+0 S4 A32]) + (const_int 1 [0x1])) -1 (nil)) + + ) ;; insn-chain +) ;; function + +;; TODO: scan the dump diff --git a/gcc/testsuite/rtl.dg/cfg-extra-bb.rtl b/gcc/testsuite/rtl.dg/cfg-extra-bb.rtl new file mode 100644 index 0000000..7da8870 --- /dev/null +++ b/gcc/testsuite/rtl.dg/cfg-extra-bb.rtl @@ -0,0 +1,12 @@ +(function "extra_bb" + (insn-chain) ;; empty + (cfg + (bb 0 ;; entry + (edge 0 2 (flags 0x1)) ;; { dg-error "bb index 2 not referenced by insns" } + ) ;; bb + (bb 2 + (edge 2 1 (flags 0x1)) + ) ;; bb + (bb 1) ;; exit + ) ;; cfg +) diff --git a/gcc/testsuite/rtl.dg/cfg-missing-bb.rtl b/gcc/testsuite/rtl.dg/cfg-missing-bb.rtl new file mode 100644 index 0000000..cd82d04 --- /dev/null +++ b/gcc/testsuite/rtl.dg/cfg-missing-bb.rtl @@ -0,0 +1,16 @@ +(function "missing_bb" + (insn-chain + (note 2 0 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK) + (note 3 2 0 3 [bb 3] NOTE_INSN_BASIC_BLOCK) + ) ;; empty + (cfg ;; { dg-error "bb index 3 used in .insn-chain. but not listed in .cfg." } + ;; { dg-error "1 missing bb.s." "" { target *-*-*} 6 } + (bb 0 ;; entry + (edge 0 2 (flags 0x1)) + ) ;; bb + (bb 2 + (edge 2 1 (flags 0x1)) + ) ;; bb + (bb 1) ;; exit + ) ;; cfg +) diff --git a/gcc/testsuite/rtl.dg/good-include.rtl b/gcc/testsuite/rtl.dg/good-include.rtl new file mode 100644 index 0000000..24be829 --- /dev/null +++ b/gcc/testsuite/rtl.dg/good-include.rtl @@ -0,0 +1,6 @@ +/* Verify that we can include fragments from another dump. + We give the included file a .md suffix to avoid it being + run by rtl.exp. */ + +(include "good-includee.md") +/* TODO: verify that we have the instruction from the above file. */ diff --git a/gcc/testsuite/rtl.dg/good-includee.md b/gcc/testsuite/rtl.dg/good-includee.md new file mode 100644 index 0000000..3314c40 --- /dev/null +++ b/gcc/testsuite/rtl.dg/good-includee.md @@ -0,0 +1,5 @@ +(function "test" + (insn-chain + (note 1 0 0 (nil) NOTE_INSN_DELETED) + ) ;; insn-chain +) ;; function diff --git a/gcc/testsuite/rtl.dg/missing-include.rtl b/gcc/testsuite/rtl.dg/missing-include.rtl new file mode 100644 index 0000000..f99f3ef --- /dev/null +++ b/gcc/testsuite/rtl.dg/missing-include.rtl @@ -0,0 +1 @@ +(include "does-not-exist.rtl") /* { dg-error "include file .does-not-exist.rtl. not found" } */ diff --git a/gcc/testsuite/rtl.dg/more-than-one-cfg.rtl b/gcc/testsuite/rtl.dg/more-than-one-cfg.rtl new file mode 100644 index 0000000..7153e0f --- /dev/null +++ b/gcc/testsuite/rtl.dg/more-than-one-cfg.rtl @@ -0,0 +1,7 @@ +(function "more_than_one_cfg" + (insn-chain) ;; insn-chain + + (cfg) + (cfg) ;; { dg-error "more than one 'cfg' directive" } + +) ;; function diff --git a/gcc/testsuite/rtl.dg/rtl.exp b/gcc/testsuite/rtl.dg/rtl.exp new file mode 100644 index 0000000..71bebb9 --- /dev/null +++ b/gcc/testsuite/rtl.dg/rtl.exp @@ -0,0 +1,41 @@ +# Copyright (C) 2016 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib rtl-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_RTLFLAGS +if ![info exists DEFAULT_RTLFLAGS] then { + set DEFAULT_RTLFLAGS "" + # -fdump-tree-rtl-raw +} + +# Initialize `dg'. +dg-init + +# Gather a list of all tests. +set tests [lsort [find $srcdir/$subdir *.rtl]] + +verbose "rtl.exp tests: $tests" 1 + +# Main loop. +dg-runtest $tests "" $DEFAULT_RTLFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/rtl.dg/test.c b/gcc/testsuite/rtl.dg/test.c new file mode 100644 index 0000000..ebb8aef --- /dev/null +++ b/gcc/testsuite/rtl.dg/test.c @@ -0,0 +1,31 @@ +int test_1 (int i, int j, int k) +{ + if (i < j) + return k + 4; + else + return -k; +} + +/* Example showing: + - data structure + - loop + - call to "abort". */ + +struct foo +{ + int count; + float *data; +}; + +float test_2 (struct foo *lhs, struct foo *rhs) +{ + float result = 0.0f; + + if (lhs->count != rhs->count) + __builtin_abort (); + + for (int i = 0; i < lhs->count; i++) + result += lhs->data[i] * rhs->data[i]; + + return result; +} diff --git a/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl b/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl new file mode 100644 index 0000000..8e63ace --- /dev/null +++ b/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl @@ -0,0 +1,6 @@ +(function "test" + (insn-chain + (note 6 1 0 2 [bb 2] NOTE_INSN_BASIC_BLOCK) ;; { dg-error "insn with UID 1 not found for operand 0 ..PREV_INSN.. of insn 6" } + (note 7 0 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK) ;; { dg-error "insn with UID 3 not found for operand 1 ..NEXT_INSN.. of insn 7" } + ) ;; insn-chain +) ;; function diff --git a/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl b/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl new file mode 100644 index 0000000..9930677 --- /dev/null +++ b/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl @@ -0,0 +1,5 @@ +(function "test" + (insn-chain + (not-a-valid-kind-of-insn 1 0 0) ;; { dg-error "unknown rtx code" } + ) ;; insn-chain +) ;; function diff --git a/gcc/testsuite/rtl.dg/x86_64/dfinit.rtl b/gcc/testsuite/rtl.dg/x86_64/dfinit.rtl new file mode 100644 index 0000000..54370a6 --- /dev/null +++ b/gcc/testsuite/rtl.dg/x86_64/dfinit.rtl @@ -0,0 +1,102 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fsingle-pass=rtl-dfinit -fdump-rtl-dfinit" } */ + +/* Lightly-modified dump of test.c.247r.split1 for x86_64, with + "function" directives added by hand. */ + +;; Function test_1 (test_1, funcdef_no=0, decl_uid=1758, cgraph_uid=0, symbol_order=0) + +(function "test_1" + (insn-chain +(note 1 0 6 (nil) NOTE_INSN_DELETED) +(note 6 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) +(insn 2 6 3 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32]) + (reg:SI 5 di [ i ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(insn 3 2 4 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]) + (reg:SI 4 si [ j ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(insn 4 3 5 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]) + (reg:SI 1 dx [ k ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(note 5 4 8 2 NOTE_INSN_FUNCTION_BEG) +(insn 8 5 9 2 (set (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil)) +(insn 9 8 10 2 (set (reg:CCGC 17 flags) + (compare:CCGC (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil)) +(jump_insn 10 9 11 2 (set (pc) + (if_then_else (ge (reg:CCGC 17 flags) + (const_int 0 [0])) + (label_ref 16) + (pc))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil) + -> 16) +(note 11 10 12 3 [bb 3] NOTE_INSN_BASIC_BLOCK) +(insn 12 11 13 3 (set (reg:SI 90) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 13 12 29 3 (parallel [ + (set (reg:SI 87 [ _1 ]) + (plus:SI (reg:SI 90) + (const_int 4 [0x4]))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]) + (const_int 4 [0x4])) + (nil))) +(jump_insn 29 13 30 3 (set (pc) + (label_ref 20)) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil) + -> 20) +(barrier 30 29 16) +(code_label 16 30 17 4 2 (nil) [1 uses]) +(note 17 16 18 4 [bb 4] NOTE_INSN_BASIC_BLOCK) +(insn 18 17 19 4 (set (reg:SI 91) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1 + (nil)) +(insn 19 18 20 4 (parallel [ + (set (reg:SI 87 [ _1 ]) + (neg:SI (reg:SI 91))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) + (nil))) +(code_label 20 19 21 5 3 (nil) [1 uses]) +(note 21 20 22 5 [bb 5] NOTE_INSN_BASIC_BLOCK) +(insn 22 21 26 5 (set (reg:SI 88 [ <retval> ]) + (reg:SI 87 [ _1 ])) -1 + (nil)) +(insn 26 22 27 5 (set (reg/i:SI 0 ax) + (reg:SI 88 [ <retval> ])) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) +(insn 27 26 0 5 (use (reg/i:SI 0 ax)) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) +) ;; insn-chain + + (crtl + (return_rtx + (reg/i:SI 0 ax) + ) ;; return_rtx + ) ;; crtl + +) ;; function + +/* Verify that the dataflow information matches what cc1 would have + generated. In particular, in earlier versions of the RTL + frontend, the exit block use of reg 0 (ax) wasn't picked up + on, due to not setting up crtl->return_rtx based on + DECL_RESULT (fndecl). */ +/* { dg-final { scan-rtl-dump ";; exit block uses.*0 .ax. 6 .bp. 7 .sp. 20 .frame." "dfinit" } } */ +/* { dg-final { scan-rtl-dump ";; regs ever live.*0 .ax. 1 .dx. 4 .si. 5 .di. 17 .flags." "dfinit" } } */ diff --git a/gcc/testsuite/rtl.dg/x86_64/final.rtl b/gcc/testsuite/rtl.dg/x86_64/final.rtl new file mode 100644 index 0000000..dbcdd0b --- /dev/null +++ b/gcc/testsuite/rtl.dg/x86_64/final.rtl @@ -0,0 +1,58 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fsingle-pass=rtl-final -fdump-rtl-final" } */ + +/* Lightly-modified dump of test.c.289r.dwarf2 for x86_64 target. */ + +;; Function test_1 (test_1, funcdef_no=0, decl_uid=1758, cgraph_uid=0, symbol_order=0) + +(function "test_1" + (insn-chain + +(note 1 0 6 (nil) NOTE_INSN_DELETED) +(note 6 1 32 2 [bb 2] NOTE_INSN_BASIC_BLOCK) +(note 32 6 5 2 NOTE_INSN_PROLOGUE_END) +(note 5 32 31 2 NOTE_INSN_FUNCTION_BEG) +(insn:TI 31 5 27 2 (set (reg:SI 0 ax [93]) + (plus:SI (reg/v:SI 1 dx [orig:90 k ] [90]) + (const_int 4 [0x4]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 27 31 28 2 (parallel [ + (set (reg:SI 1 dx [92]) + (neg:SI (reg/v:SI 1 dx [orig:90 k ] [90]))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (expr_list:REG_UNUSED (reg:CC 17 flags) + (nil))) +(insn 28 27 29 2 (set (reg:CCGC 17 flags) + (compare:CCGC (reg/v:SI 5 di [orig:88 i ] [88]) + (reg/v:SI 4 si [orig:89 j ] [89]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (expr_list:REG_DEAD (reg/v:SI 5 di [orig:88 i ] [88]) + (expr_list:REG_DEAD (reg/v:SI 4 si [orig:89 j ] [89]) + (nil)))) +(insn:TI 29 28 23 2 (set (reg:SI 0 ax [orig:87 <retval> ] [87]) + (if_then_else:SI (ge (reg:CCGC 17 flags) + (const_int 0 [0])) + (reg:SI 1 dx [92]) + (reg:SI 0 ax [93]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (expr_list:REG_DEAD (reg:CCGC 17 flags) + (expr_list:REG_DEAD (reg:SI 1 dx [92]) + (nil)))) +(insn 23 29 34 2 (use (reg/i:SI 0 ax)) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) +(jump_insn:TI 34 23 33 2 (simple_return) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil) + -> simple_return) +(barrier 33 34 30) +(note 30 33 0 (nil) NOTE_INSN_DELETED) + + ) ;; insn-chain +) ;; function + +/* Verify that asm was emitted. */ +/* { dg-final { scan-assembler "test_1:" } } */ +/* { dg-final { scan-assembler ".cfi_startproc" } } */ +/* { dg-final { scan-assembler ".cfi_endproc" } } */ + +/* Verify that the "simple_return" was recognized. + FIXME: this assumes i386.md. */ +/* { dg-final { scan-assembler "ret" } } */ diff --git a/gcc/testsuite/rtl.dg/x86_64/into-cfglayout.rtl b/gcc/testsuite/rtl.dg/x86_64/into-cfglayout.rtl new file mode 100644 index 0000000..f7798aa --- /dev/null +++ b/gcc/testsuite/rtl.dg/x86_64/into-cfglayout.rtl @@ -0,0 +1,91 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fsingle-pass=rtl-into_cfglayout -fdump-rtl-into_cfglayout" } */ + +(function "test" + (insn-chain +(note 1 0 6 (nil) NOTE_INSN_DELETED) +(note 6 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) +(insn 2 6 3 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32]) + (reg:SI 5 di [ i ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(insn 3 2 4 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]) + (reg:SI 4 si [ j ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(insn 4 3 5 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]) + (reg:SI 1 dx [ k ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(note 5 4 8 2 NOTE_INSN_FUNCTION_BEG) +(insn 8 5 9 2 (set (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil)) +(insn 9 8 10 2 (set (reg:CCGC 17 flags) + (compare:CCGC (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil)) +(jump_insn 10 9 11 2 (set (pc) + (if_then_else (ge (reg:CCGC 17 flags) + (const_int 0 [0])) + (label_ref 16) + (pc))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil) + -> 16) +(note 11 10 12 4 [bb 4] NOTE_INSN_BASIC_BLOCK) +(insn 12 11 13 4 (set (reg:SI 90) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 13 12 14 4 (parallel [ + (set (reg:SI 87 [ _1 ]) + (plus:SI (reg:SI 90) + (const_int 4 [0x4]))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]) + (const_int 4 [0x4])) + (nil))) +(jump_insn 14 13 15 4 (set (pc) + (label_ref 20)) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil) + -> 20) +(barrier 15 14 16) +(code_label 16 15 17 5 2 (nil) [1 uses]) +(note 17 16 18 5 [bb 5] NOTE_INSN_BASIC_BLOCK) +(insn 18 17 19 5 (set (reg:SI 91) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1 + (nil)) +(insn 19 18 20 5 (parallel [ + (set (reg:SI 87 [ _1 ]) + (neg:SI (reg:SI 91))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) + (nil))) +(code_label 20 19 21 6 3 (nil) [1 uses]) +(note 21 20 22 6 [bb 6] NOTE_INSN_BASIC_BLOCK) +(insn 22 21 26 6 (set (reg:SI 88 [ <retval> ]) + (reg:SI 87 [ _1 ])) -1 + (nil)) +(insn 26 22 27 6 (set (reg/i:SI 0 ax) + (reg:SI 88 [ <retval> ])) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) +(insn 27 26 0 6 (use (reg/i:SI 0 ax)) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) +) ;; insn-chain +) ;; function + +/* The conversion to cfglayout should eliminate unconditional jump + instructions... */ +/* { dg-final { scan-rtl-dump "Removing jump 14." "into_cfglayout" } } */ +/* { dg-final { scan-rtl-dump-not "jump_insn 14" "into_cfglayout" } } */ +/* { dg-final { scan-rtl-dump-not "barrier 15" "into_cfglayout" } } */ + +/* ...but conditional jumps should be preserved. */ +/* { dg-final { scan-rtl-dump "jump_insn 10" "into_cfglayout" } } */ diff --git a/gcc/testsuite/rtl.dg/x86_64/ira.rtl b/gcc/testsuite/rtl.dg/x86_64/ira.rtl new file mode 100644 index 0000000..707895d --- /dev/null +++ b/gcc/testsuite/rtl.dg/x86_64/ira.rtl @@ -0,0 +1,91 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fsingle-pass=rtl-ira -fdump-rtl-ira" } */ + +/* Lightly-modified dump of test.c.251r.asmcons for x86_64. */ + +;; Function test_1 (test_1, funcdef_no=0, decl_uid=1758, cgraph_uid=0, symbol_order=0) + +(function "test" +(insn-chain + +(note 1 0 6 (nil) NOTE_INSN_DELETED) +(note 6 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) +(insn 2 6 3 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32]) + (reg:SI 5 di [ i ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(insn 3 2 4 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]) + (reg:SI 4 si [ j ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(insn 4 3 5 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]) + (reg:SI 1 dx [ k ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(note 5 4 8 2 NOTE_INSN_FUNCTION_BEG) +(insn 8 5 9 2 (set (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil)) +(insn 9 8 10 2 (set (reg:CCGC 17 flags) + (compare:CCGC (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil)) +(jump_insn 10 9 11 2 (set (pc) + (if_then_else (ge (reg:CCGC 17 flags) + (const_int 0 [0])) + (label_ref 16) + (pc))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil) + -> 16) +(note 11 10 12 3 [bb 3] NOTE_INSN_BASIC_BLOCK) +(insn 12 11 13 3 (set (reg:SI 90) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 13 12 29 3 (parallel [ + (set (reg:SI 87 [ _1 ]) + (plus:SI (reg:SI 90) + (const_int 4 [0x4]))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]) + (const_int 4 [0x4])) + (nil))) +(jump_insn 29 13 30 3 (set (pc) + (label_ref 20)) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil) + -> 20) +(barrier 30 29 16) +(code_label 16 30 17 4 2 (nil) [1 uses]) +(note 17 16 18 4 [bb 4] NOTE_INSN_BASIC_BLOCK) +(insn 18 17 19 4 (set (reg:SI 91) + (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1 + (nil)) +(insn 19 18 20 4 (parallel [ + (set (reg:SI 87 [ _1 ]) + (neg:SI (reg:SI 91))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI 20 frame) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) + (nil))) +(code_label 20 19 21 5 3 (nil) [1 uses]) +(note 21 20 22 5 [bb 5] NOTE_INSN_BASIC_BLOCK) +(insn 22 21 26 5 (set (reg:SI 88 [ <retval> ]) + (reg:SI 87 [ _1 ])) -1 + (nil)) +(insn 26 22 27 5 (set (reg/i:SI 0 ax) + (reg:SI 88 [ <retval> ])) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) +(insn 27 26 0 5 (use (reg/i:SI 0 ax)) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) + +) ;; insn-chain +) ;; function + +/* Verify that IRA was run. */ +/* { dg-final { scan-rtl-dump "Building IRA IR" "ira" } } */ diff --git a/gcc/testsuite/rtl.dg/x86_64/pro_and_epilogue.rtl b/gcc/testsuite/rtl.dg/x86_64/pro_and_epilogue.rtl new file mode 100644 index 0000000..bfbe302 --- /dev/null +++ b/gcc/testsuite/rtl.dg/x86_64/pro_and_epilogue.rtl @@ -0,0 +1,44 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fsingle-pass=rtl-pro_and_epilogue -fdump-rtl-pro_and_epilogue" } */ + +/* Lightly-modified dump of test.c.259r.split2 for x86_64. */ + +(function "test_1" +(insn-chain + +(note 1 0 6 (nil) NOTE_INSN_DELETED) +(note 6 1 5 2 [bb 2] NOTE_INSN_BASIC_BLOCK) +(note 5 6 31 2 NOTE_INSN_FUNCTION_BEG) +(insn 31 5 27 2 (set (reg:SI 0 ax [93]) + (plus:SI (reg/v:SI 1 dx [orig:90 k ] [90]) + (const_int 4 [0x4]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 27 31 28 2 (parallel [ + (set (reg:SI 1 dx [92]) + (neg:SI (reg/v:SI 1 dx [orig:90 k ] [90]))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 28 27 29 2 (set (reg:CCGC 17 flags) + (compare:CCGC (reg/v:SI 5 di [orig:88 i ] [88]) + (reg/v:SI 4 si [orig:89 j ] [89]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 29 28 23 2 (set (reg:SI 0 ax [orig:87 <retval> ] [87]) + (if_then_else:SI (ge (reg:CCGC 17 flags) + (const_int 0 [0])) + (reg:SI 1 dx [92]) + (reg:SI 0 ax [93]))) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 23 29 30 2 (use (reg/i:SI 0 ax)) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) +(note 30 23 0 (nil) NOTE_INSN_DELETED) + +) ;; insn-chain +) ;; function + +/* Verify that the prologue and epilogue were added. */ +/* { dg-final { scan-rtl-dump-times "NOTE_INSN_PROLOGUE_END" 1 "pro_and_epilogue" } } */ + +/* We expect a jump_insn to "simple_return". */ +/* { dg-final { scan-rtl-dump-times "simple_return" 2 "pro_and_epilogue" } } */ + diff --git a/gcc/testsuite/rtl.dg/x86_64/vregs.rtl b/gcc/testsuite/rtl.dg/x86_64/vregs.rtl new file mode 100644 index 0000000..95f5310 --- /dev/null +++ b/gcc/testsuite/rtl.dg/x86_64/vregs.rtl @@ -0,0 +1,88 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fsingle-pass=rtl-vregs -fdump-rtl-vregs" } */ + +(function "test" +(insn-chain + +(note 1 0 6 (nil) NOTE_INSN_DELETED) +(note 6 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) +(insn 2 6 3 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32]) + (reg:SI 5 di [ i ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(insn 3 2 4 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]) + (reg:SI 4 si [ j ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(insn 4 3 5 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]) + (reg:SI 1 dx [ k ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1 + (nil)) +(note 5 4 8 2 NOTE_INSN_FUNCTION_BEG) +(insn 8 5 9 2 (set (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil)) +(insn 9 8 10 2 (set (reg:CCGC 17 flags) + (compare:CCGC (reg:SI 89) + (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil)) +(jump_insn 10 9 11 2 (set (pc) + (if_then_else (ge (reg:CCGC 17 flags) + (const_int 0 [0])) + (label_ref 16) + (pc))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1 + (nil) + -> 16) +(note 11 10 12 4 [bb 4] NOTE_INSN_BASIC_BLOCK) +(insn 12 11 13 4 (set (reg:SI 90) + (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil)) +(insn 13 12 14 4 (parallel [ + (set (reg:SI 87 [ _1 ]) + (plus:SI (reg:SI 90) + (const_int 4 [0x4]))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]) + (const_int 4 [0x4])) + (nil))) +(jump_insn 14 13 15 4 (set (pc) + (label_ref 20)) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1 + (nil) + -> 20) +(barrier 15 14 16) +(code_label 16 15 17 5 2 (nil) [1 uses]) +(note 17 16 18 5 [bb 5] NOTE_INSN_BASIC_BLOCK) +(insn 18 17 19 5 (set (reg:SI 91) + (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1 + (nil)) +(insn 19 18 20 5 (parallel [ + (set (reg:SI 87 [ _1 ]) + (neg:SI (reg:SI 91))) + (clobber (reg:CC 17 flags)) + ]) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) + (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) + (nil))) +(code_label 20 19 21 6 3 (nil) [1 uses]) +(note 21 20 22 6 [bb 6] NOTE_INSN_BASIC_BLOCK) +(insn 22 21 26 6 (set (reg:SI 88 [ <retval> ]) + (reg:SI 87 [ _1 ])) -1 + (nil)) +(insn 26 22 27 6 (set (reg/i:SI 0 ax) + (reg:SI 88 [ <retval> ])) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) +(insn 27 26 0 6 (use (reg/i:SI 0 ax)) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1 + (nil)) + +) ;; insn-chain +) ;; function + +/* The 9 instances of "virtual-stack-vars" should now all be "frame". */ +/* { dg-final { scan-rtl-dump-times "frame" 9 "vregs" } } */ +/* { dg-final { scan-rtl-dump-not "virtual-stack-vars" "vregs" } } */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 5f80763..2bb42a1 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -477,6 +477,13 @@ compile_file (void) if (flag_syntax_only || flag_wpa) return; + + /* The RTL frontend is currently only capable of running one pass; this + is done from within the parse_file langhook. + Hence we must return early here. Fixing this would require + being able to run passes from a certain point onwards. */ + if (in_rtl_frontend_p) + return; /* Reset maximum_field_alignment, it can be adjusted by #pragma pack and this shouldn't influence any types built by the middle-end -- 1.8.5.3