[PATCH 15/16] RTL frontend (rtl1), on top of dump reader

David Malcolm dmalcolm@redhat.com
Wed Oct 5 15:45:00 GMT 2016


This patch implements the RTL frontend, using the function_reader
class from earlier in the patch kit.

Compared to this patch in v1 of the kit, most of the work has been
split into earlier patches.  Other changes relative to v1 include:
* fix autodeps (by renaming RTL_OBJS to rtl_OBJS in rtl/Make-lang.in)
* cleanup of rtl/Make-lang.in
* overrride IN_GCC_FRONTEND in rtl/rtl-frontend.c
* split out run-one-rtl-pass.h/c
* added .texi docs to gccint (instead of notes.rst)
* remove roundtrip.exp for now (we don't currently preserve source
location information)
* convert existing test cases to "print_rtx_function" format, and add
new test cases.  Move some to target-specific subdirectories of rtl.dg
(manually adding target filters).

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                           | 399 +++++++++++++++++++++++
 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, 1782 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 3582bde..1c7c548 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..b87794a
--- /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 of 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 below @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..638b104
--- /dev/null
+++ b/gcc/rtl/rtl-frontend.c
@@ -0,0 +1,399 @@
+/* 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/>.  */
+
+/* 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
+
+#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"
+#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)
+{
+  in_rtl_frontend_p = true;
+
+  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 ();
+
+  /* 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);
+
+  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 value ATTRIBUTE_UNUSED,
+    int kind ATTRIBUTE_UNUSED,
+    location_t loc ATTRIBUTE_UNUSED,
+    const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
+{
+  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)
+{
+  in_rtl_frontend_p = true;
+
+  initialize_rtl ();
+  init_emit ();
+  init_varasm_status ();
+
+  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;
+  /* 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.  */
+  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);
+  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 (&reg_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 (&reg_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



More information about the Gcc-patches mailing list