This patch adds a new function, print_rtx_function, intended for use for generating function dumps suitable for parsing by the RTL frontend, but also intended to be human-readable, and human-authorable.
I put the function in its own file (rather than print-rtl.c) to avoid having to recompile all the gen* files etc every time the format is tweaked. For the RTL frontend, it's not enough for a dump to simply record the insn chain: we need to also capture the CFG and various other state. It's possible to reconstruct the CFG based on jump instructions when we're in "cfgrtl" mode (https://gcc.gnu.org/wiki/cfglayout_mode) but not when in "cfglayout" mode - in the latter, unconditional jumps are represented purely by edges in the CFG, not via jump instructions. So it seems best to directly capture the CFG. I plan to keep the CFG-reconstruction code, so that the CFG information can be optional, to make it easier to write interesting test cases by hand (for cfgrtl passes). Some other state needs to be captured. I know that we need to at least capture crtl->return_rtx. The reason for this is that in the normal case of expanding gimple, this is set inside assign_parms via non-trivial target-specific logic. We don't want to rerun assign_parms when loading a dump as it could insert new insns. In theory we could rerun parts of this logic, but it seems simplest to have the dump record the decisions that were made by assign_parms. (if crtl->return_rtx is not set, then df subtly changes behavior, e.g on x86_64 "ax" is not recognized as used at the exit block). Nothing in the tree actually uses the new dump function; you (currently) have to call it manually from the debugger. We could start using this function in various pass dumps - though that would obviously run the risk of affecting dump-scanning in the DejaGnu test suite, so I'm leaving that as followup work. The new dump format looks a lot like the existing insn chain dumps: Here's an example dump (from x86_64). I put the insn chain at the top, with the other data coming after it, since GCC developers are used to seeing the insn chain. The dump uses indentation and comments to make it easier for humans to grok. (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" I anticipate the format gaining extra fields, but I want to nail down the basic ideas and structure a little before I rewrite the RTL frontend to use it, hence this patch. Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. OK for trunk? gcc/ChangeLog: * Makefile.in (OBJS): Add print-rtl-function.o. * print-rtl-function.c: New file. * print-rtl.h (print_rtx_function): New decl. --- gcc/Makefile.in | 1 + gcc/print-rtl-function.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ gcc/print-rtl.h | 2 + 3 files changed, 134 insertions(+) create mode 100644 gcc/print-rtl-function.c diff --git a/gcc/Makefile.in b/gcc/Makefile.in index ff12908..15c48bc 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1405,6 +1405,7 @@ OBJS = \ postreload.o \ predict.o \ print-rtl.o \ + print-rtl-function.o \ print-tree.o \ profile.o \ real.o \ diff --git a/gcc/print-rtl-function.c b/gcc/print-rtl-function.c new file mode 100644 index 0000000..c4b99c0 --- /dev/null +++ b/gcc/print-rtl-function.c @@ -0,0 +1,131 @@ +/* Print RTL functions for GCC. + 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 "tm.h" +#include "rtl.h" +#include "alias.h" +#include "tree.h" +#include "cfg.h" +#include "flags.h" +#include "predict.h" +#include "function.h" +#include "basic-block.h" +#include "print-rtl.h" +#include "langhooks.h" +#include "emit-rtl.h" + +/* Write FN to OUTFILE in a form suitable for parsing, with indentation + and comments to make the structure easy for a human to grok. + + Example output: + + (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" +*/ + +DEBUG_FUNCTION void +print_rtx_function (FILE *outfile, function *fn) +{ + tree fdecl = fn->decl; + + const char *dname = lang_hooks.decl_printable_name (fdecl, 2); + + fprintf (outfile, "(function \"%s\"\n", dname); + + /* The instruction chain. */ + fprintf (outfile, " (insn-chain\n"); + for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn)) + print_rtl_single_with_indent (outfile, insn, 4); + fprintf (outfile, " ) ;; insn-chain\n"); + + /* The CFG. */ + fprintf (outfile, " (cfg\n"); + { + basic_block bb; + FOR_ALL_BB_FN (bb, fn) + { + fprintf (outfile, " (bb %i\n", bb->index); + edge e; + edge_iterator ei; + FOR_EACH_EDGE (e, ei, bb->succs) + fprintf (outfile, " (edge %i %i (flags 0x%x))\n", + e->src->index, e->dest->index, e->flags); + fprintf (outfile, " ) ;; bb\n"); + } + } + fprintf (outfile, " ) ;; cfg\n"); + + /* Additional RTL state. */ + fprintf (outfile, " (crtl\n"); + fprintf (outfile, " (return_rtx \n"); + print_rtl_single_with_indent (outfile, crtl->return_rtx, 6); + fprintf (outfile, " ) ;; return_rtx\n"); + fprintf (outfile, " ) ;; crtl\n"); + + fprintf (outfile, ") ;; function \"%s\"\n", dname); +} diff --git a/gcc/print-rtl.h b/gcc/print-rtl.h index e585a63..9cad683 100644 --- a/gcc/print-rtl.h +++ b/gcc/print-rtl.h @@ -36,4 +36,6 @@ extern void print_insn (pretty_printer *pp, const rtx_insn *x, int verbose); extern void rtl_dump_bb_for_graph (pretty_printer *, basic_block); extern const char *str_pattern_slim (const_rtx); +extern void print_rtx_function (FILE *file, function *fn); + #endif // GCC_PRINT_RTL_H -- 1.8.5.3