diff mbox

RTL frontend (rtl1), on top of dump reader (v4)

Message ID 1475859171-5446-1-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm Oct. 7, 2016, 4:52 p.m. UTC
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 mbox

Patch

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 (&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