From: David Malcolm Date: Wed, 12 Oct 2016 14:59:56 +0000 (+0000) Subject: print_rtx_function: integrate dumping of the CFG into the insn chain X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4b77ac40f0fe35d541914de0227b5c37d88c619c;p=gcc.git print_rtx_function: integrate dumping of the CFG into the insn chain gcc/ChangeLog: * function-tests.c: Include "print-rtl.h". (selftest::test_expansion_to_rtl): Call print_rtx_function on the function, and verify what is dumped. * print-rtl-function.c (print_edge): New function. (begin_any_block): New function. (end_any_block): New function. (can_have_basic_block_p): New function. (print_rtx_function): Track the basic blocks of insns in the chain, wrapping those that are within blocks within "(block)" directives. Remove the "(cfg)" directive. From-SVN: r241057 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff670802ce5..35f38fff13a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2016-10-12 David Malcolm + + * function-tests.c: Include "print-rtl.h". + (selftest::test_expansion_to_rtl): Call print_rtx_function on the + function, and verify what is dumped. + * print-rtl-function.c (print_edge): New function. + (begin_any_block): New function. + (end_any_block): New function. + (can_have_basic_block_p): New function. + (print_rtx_function): Track the basic blocks of insns in the + chain, wrapping those that are within blocks within "(block)" + directives. Remove the "(cfg)" directive. + 2016-10-12 David Malcolm * selftest.c (selftest::read_file): New function. diff --git a/gcc/function-tests.c b/gcc/function-tests.c index 4152cd386d5..049a07f9a86 100644 --- a/gcc/function-tests.c +++ b/gcc/function-tests.c @@ -78,6 +78,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-ref.h" #include "cgraph.h" #include "selftest.h" +#include "print-rtl.h" #if CHECKING_P @@ -643,6 +644,27 @@ test_expansion_to_rtl () /* ...etc; any further checks are likely to over-specify things and run us into target dependencies. */ + + /* Verify that print_rtl_function is sane. */ + named_temp_file tmp_out (".rtl"); + FILE *outfile = fopen (tmp_out.get_filename (), "w"); + print_rtx_function (outfile, fun); + fclose (outfile); + + char *dump = read_file (SELFTEST_LOCATION, tmp_out.get_filename ()); + ASSERT_STR_CONTAINS (dump, "(function \"test_fn\"\n"); + ASSERT_STR_CONTAINS (dump, " (insn-chain\n"); + ASSERT_STR_CONTAINS (dump, " (block 2\n"); + ASSERT_STR_CONTAINS (dump, " (edge-from entry (flags \"FALLTHRU\"))\n"); + ASSERT_STR_CONTAINS (dump, " (insn "); /* ...etc. */ + ASSERT_STR_CONTAINS (dump, " (edge-to exit (flags \"FALLTHRU\"))\n"); + ASSERT_STR_CONTAINS (dump, " ) ;; block 2\n"); + ASSERT_STR_CONTAINS (dump, " ) ;; insn-chain\n"); + ASSERT_STR_CONTAINS (dump, " (crtl\n"); + ASSERT_STR_CONTAINS (dump, " ) ;; crtl\n"); + ASSERT_STR_CONTAINS (dump, ") ;; function \"test_fn\"\n"); + + free (dump); } /* Run all of the selftests within this file. */ diff --git a/gcc/print-rtl-function.c b/gcc/print-rtl-function.c index c4b99c03a37..4f9b4efdb2e 100644 --- a/gcc/print-rtl-function.c +++ b/gcc/print-rtl-function.c @@ -33,14 +33,106 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "emit-rtl.h" +/* Print an "(edge-from)" or "(edge-to)" directive describing E + to OUTFILE. */ + +static void +print_edge (FILE *outfile, edge e, bool from) +{ + fprintf (outfile, " (%s ", from ? "edge-from" : "edge-to"); + basic_block bb = from ? e->src : e->dest; + gcc_assert (bb); + switch (bb->index) + { + case ENTRY_BLOCK: + fprintf (outfile, "entry"); + break; + case EXIT_BLOCK: + fprintf (outfile, "exit"); + break; + default: + fprintf (outfile, "%i", bb->index); + break; + } + + /* Express edge flags as a string with " | " separator. + e.g. (flags "FALLTHRU | DFS_BACK"). */ + fprintf (outfile, " (flags \""); + bool seen_flag = false; +#define DEF_EDGE_FLAG(NAME,IDX) \ + do { \ + if (e->flags & EDGE_##NAME) \ + { \ + if (seen_flag) \ + fprintf (outfile, " | "); \ + fprintf (outfile, "%s", (#NAME)); \ + seen_flag = true; \ + } \ + } while (0); +#include "cfg-flags.def" +#undef DEF_EDGE_FLAG + + fprintf (outfile, "\"))\n"); +} + +/* If BB is non-NULL, print the start of a "(block)" directive for it + to OUTFILE, otherwise do nothing. */ + +static void +begin_any_block (FILE *outfile, basic_block bb) +{ + if (!bb) + return; + + edge e; + edge_iterator ei; + + fprintf (outfile, " (block %i\n", bb->index); + FOR_EACH_EDGE (e, ei, bb->preds) + print_edge (outfile, e, true); +} + +/* If BB is non-NULL, print the end of a "(block)" directive for it + to OUTFILE, otherwise do nothing. */ + +static void +end_any_block (FILE *outfile, basic_block bb) +{ + if (!bb) + return; + + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->succs) + print_edge (outfile, e, false); + fprintf (outfile, " ) ;; block %i\n", bb->index); +} + +/* Determine if INSN is of a kind that can have a basic block. */ + +static bool +can_have_basic_block_p (const rtx_insn *insn) +{ + rtx_code code = GET_CODE (insn); + if (code == BARRIER) + return false; + gcc_assert (GET_RTX_FORMAT (code)[2] == 'B'); + return true; +} + /* Write FN to OUTFILE in a form suitable for parsing, with indentation - and comments to make the structure easy for a human to grok. + and comments to make the structure easy for a human to grok. Track + the basic blocks of insns in the chain, wrapping those that are within + blocks within "(block)" directives. Example output: - (function "times_two" - (insn-chain - (note 1 0 4 (nil) NOTE_INSN_DELETED) + (function "times_two" + (insn-chain + (note 1 0 4 (nil) NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) (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]) @@ -69,23 +161,15 @@ along with GCC; see the file COPYING3. If not see (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" + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI 0 ax) + ) ;; return_rtx + ) ;; crtl + ) ;; function "times_two" */ DEBUG_FUNCTION void @@ -99,27 +183,25 @@ print_rtx_function (FILE *outfile, function *fn) /* The instruction chain. */ fprintf (outfile, " (insn-chain\n"); + basic_block curr_bb = NULL; for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn)) - print_rtl_single_with_indent (outfile, insn, 4); + { + basic_block insn_bb; + if (can_have_basic_block_p (insn)) + insn_bb = BLOCK_FOR_INSN (insn); + else + insn_bb = NULL; + if (curr_bb != insn_bb) + { + end_any_block (outfile, curr_bb); + curr_bb = insn_bb; + begin_any_block (outfile, curr_bb); + } + print_rtl_single_with_indent (outfile, insn, curr_bb ? 6 : 4); + } + end_any_block (outfile, curr_bb); 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");