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
This commit is contained in:
David Malcolm 2016-10-12 14:59:56 +00:00 committed by David Malcolm
parent 2934018d27
commit 4b77ac40f0
3 changed files with 156 additions and 39 deletions

View File

@ -1,3 +1,16 @@
2016-10-12 David Malcolm <dmalcolm@redhat.com>
* 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 <dmalcolm@redhat.com>
* selftest.c (selftest::read_file): New function.

View File

@ -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. */

View File

@ -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");