Commit 735a0e33 by Ulrich Drepper Committed by Richard Henderson

Ulrich Drepper <drepper@cygnus.com>

Ulrich Drepper  <drepper@cygnus.com>
        * Makefile.in (OBJS): Add graph.o
        (graph.o): New dependency list.
        * flags.h: Declare dump_for_graph and define graph_dump_types type.
        * print-rtl.c (dump_for_graph): Define new variable.
        (print_rtx): Rewrite to allow use in graph dumping functions.
        * toplev.c: Declare print_rtl_graph_with_bb, clean_graph_dump_file,
        finish_graph_dump_file.
        Define graph_dump_format.
        (compile_file): If graph dumping is enabled also clear these files.
        Finish graph dump files.
        (rest_of_compilation): Also dump graph information if enabled.
        (main): Recognize -dv to enabled VCG based graph dumping.
        * graph.c: New file.  Graph dumping functions.

From-SVN: r23813
parent a05e22b8
Mon Nov 23 16:40:00 1998 Ulrich Drepper <drepper@cygnus.com>
* Makefile.in (OBJS): Add graph.o
(graph.o): New dependency list.
* flags.h: Declare dump_for_graph and define graph_dump_types type.
* print-rtl.c (dump_for_graph): Define new variable.
(print_rtx): Rewrite to allow use in graph dumping functions.
* toplev.c: Declare print_rtl_graph_with_bb, clean_graph_dump_file,
finish_graph_dump_file.
Define graph_dump_format.
(compile_file): If graph dumping is enabled also clear these files.
Finish graph dump files.
(rest_of_compilation): Also dump graph information if enabled.
(main): Recognize -dv to enabled VCG based graph dumping.
* graph.c: New file. Graph dumping functions.
Mon Nov 23 16:39:04 1998 Richard Henderson <rth@cygnus.com> Mon Nov 23 16:39:04 1998 Richard Henderson <rth@cygnus.com>
* configure.in: Look for <sys/stat.h>. * configure.in: Look for <sys/stat.h>.
......
...@@ -647,7 +647,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \ ...@@ -647,7 +647,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \
insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \ insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o \ insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o \
profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \ profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \
mbchar.o dyn-string.o splay-tree.o mbchar.o dyn-string.o splay-tree.o graph.o
# GEN files are listed separately, so they can be built before doing parallel # GEN files are listed separately, so they can be built before doing parallel
# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load # makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
...@@ -1289,6 +1289,8 @@ c-pragma.o: c-pragma.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) except.h \ ...@@ -1289,6 +1289,8 @@ c-pragma.o: c-pragma.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) except.h \
c-iterate.o: c-iterate.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-tree.h \ c-iterate.o: c-iterate.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-tree.h \
flags.h toplev.h $(EXPR_H) flags.h toplev.h $(EXPR_H)
mbchar.o: mbchar.c $(CONFIG_H) system.h mbchar.h mbchar.o: mbchar.c $(CONFIG_H) system.h mbchar.h
graph.o: graph.c $(CONFIG_H) system.h toplev.h flags.h output.h rtl.h \
hard-reg-set.h basic-block.h
collect2$(exeext): collect2.o tlink.o hash.o cplus-dem.o underscore.o \ collect2$(exeext): collect2.o tlink.o hash.o cplus-dem.o underscore.o \
version.o choose-temp.o mkstemp.o $(LIBDEPS) version.o choose-temp.o mkstemp.o $(LIBDEPS)
......
...@@ -502,3 +502,14 @@ extern int current_function_is_thunk; ...@@ -502,3 +502,14 @@ extern int current_function_is_thunk;
/* Value of the -G xx switch, and whether it was passed or not. */ /* Value of the -G xx switch, and whether it was passed or not. */
extern int g_switch_value; extern int g_switch_value;
extern int g_switch_set; extern int g_switch_set;
/* Nonzero if we dump in VCG format, not plain text. */
extern int dump_for_graph;
/* Selection of the graph form. */
enum graph_dump_types
{
no_graph = 0,
vcg
};
extern enum graph_dump_types graph_dump_format;
/* Output routines for graphical representation.
Copyright (C) 1998 Free Software Foundation, Inc.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
This file is part of GNU CC.
GNU CC 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 2, or (at your option)
any later version.
GNU CC 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 GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <config.h>
#include "system.h"
#include "rtl.h"
#include "flags.h"
#include "output.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "toplev.h"
static const char *graph_ext[] =
{
/* no_graph */ "",
/* vcg */ ".vcg",
};
/* Output text for new basic block. */
static void
start_fct (fp)
FILE *fp;
{
switch (graph_dump_format)
{
case vcg:
fprintf (fp, "\
graph: { title: \"%s\"\nfolding: 1\nhidden: 2\nnode: { title: \"%s.0\" }\n",
current_function_name, current_function_name);
break;
case no_graph:
break;
}
}
static void
start_bb (fp, bb)
FILE *fp;
int bb;
{
switch (graph_dump_format)
{
case vcg:
fprintf (fp, "\
graph: {\ntitle: \"%s.BB%d\"\nfolding: 1\ncolor: lightblue\n\
label: \"basic block %d",
current_function_name, bb, bb);
break;
case no_graph:
break;
}
#if 0
/* FIXME Should this be printed? It makes the graph significantly larger. */
/* Print the live-at-start register list. */
fputc ('\n', fp);
EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[bb], 0, i,
{
fprintf (fp, " %d", i);
if (i < FIRST_PSEUDO_REGISTER)
fprintf (fp, " [%s]",
reg_names[i]);
});
#endif
switch (graph_dump_format)
{
case vcg:
fputs ("\"\n\n", fp);
break;
case no_graph:
break;
}
}
static int
node_data (fp, tmp_rtx)
FILE *fp;
rtx tmp_rtx;
{
int result;
if (PREV_INSN (tmp_rtx) == 0)
{
/* This is the first instruction. Add an edge from the starting
block. */
switch (graph_dump_format)
{
case vcg:
fprintf (fp, "\
edge: { sourcename: \"%s.0\" targetname: \"%s.%d\" }\n",
current_function_name,
current_function_name, XINT (tmp_rtx, 0));
break;
case no_graph:
break;
}
}
switch (graph_dump_format)
{
case vcg:
fprintf (fp, "node: {\n title: \"%s.%d\"\n color: %s\n \
label: \"%s %d\n",
current_function_name, XINT (tmp_rtx, 0),
GET_CODE (tmp_rtx) == NOTE ? "lightgrey"
: GET_CODE (tmp_rtx) == INSN ? "green"
: GET_CODE (tmp_rtx) == JUMP_INSN ? "darkgreen"
: GET_CODE (tmp_rtx) == CALL_INSN ? "darkgreen"
: GET_CODE (tmp_rtx) == CODE_LABEL ? "\
darkgrey\n shape: ellipse" : "white",
GET_RTX_NAME (GET_CODE (tmp_rtx)), XINT (tmp_rtx, 0));
break;
case no_graph:
break;
}
/* Print the RTL. */
if (GET_CODE (tmp_rtx) == NOTE)
{
static const char *note_names[] =
{
NULL,
"deleted",
"block_beg",
"block_end",
"loop_beg",
"loop_end",
"function_end",
"setjmp",
"loop_cont",
"loop_vtop",
"prologue_end",
"epilogue_beg",
"deleted_label",
"function_beg",
"eh_region_beg",
"eh_region_end",
"repeated_line_number",
"range_start",
"range_end",
"live"
};
fprintf (fp, " %s",
XINT (tmp_rtx, 4) < 0 ? note_names[-XINT (tmp_rtx, 4)] : "");
}
else if (GET_RTX_CLASS (GET_CODE (tmp_rtx)) == 'i')
result = print_rtl_single (fp, PATTERN (tmp_rtx));
else
result = print_rtl_single (fp, tmp_rtx);
switch (graph_dump_format)
{
case vcg:
fputs ("\"\n}\n", fp);
break;
case no_graph:
break;
}
return result;
}
static void
draw_edge (fp, from, to, bb_edge, class)
FILE *fp;
int from;
int to;
int bb_edge;
int class;
{
switch (graph_dump_format)
{
case vcg:
fprintf (fp,
"edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s",
current_function_name, from,
current_function_name, to,
bb_edge ? "color: blue " : class ? "color: red " : "");
if (class)
fprintf (fp, "class: %d ", class);
fputs ("}\n", fp);
break;
case no_graph:
break;
}
}
static void
end_bb (fp, bb)
FILE *fp;
int bb ATTRIBUTE_UNUSED;
{
switch (graph_dump_format)
{
case vcg:
fputs ("}\n", fp);
break;
case no_graph:
break;
}
}
static void
end_fct (fp)
FILE *fp;
{
switch (graph_dump_format)
{
case vcg:
fprintf (fp, "node: { title: \"%s.999999\" label: \"END\" }\n}\n",
current_function_name);
break;
case no_graph:
break;
}
}
/* Like print_rtl, but also print out live information for the start of each
basic block. */
void
print_rtl_graph_with_bb (base, suffix, rtx_first)
const char *base;
const char *suffix;
rtx rtx_first;
{
register rtx tmp_rtx;
size_t namelen = strlen (base);
size_t suffixlen = strlen (suffix);
size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
char *buf = (char *) alloca (namelen + suffixlen + extlen);
FILE *fp;
/* Regenerate the basic block information. */
find_basic_blocks (rtx_first, max_reg_num (), NULL);
memcpy (buf, base, namelen);
memcpy (buf + namelen, suffix, suffixlen);
memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
fp = fopen (buf, "a");
if (fp == NULL)
return;
if (rtx_first == 0)
fprintf (fp, "(nil)\n");
else
{
int i, bb;
enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
int max_uid = get_max_uid ();
int *start = (int *) alloca (max_uid * sizeof (int));
int *end = (int *) alloca (max_uid * sizeof (int));
enum bb_state *in_bb_p = (enum bb_state *)
alloca (max_uid * sizeof (enum bb_state));
/* Element I is a list of I's predecessors/successors. */
int_list_ptr *s_preds;
int_list_ptr *s_succs;
/* Element I is the number of predecessors/successors of basic
block I. */
int *num_preds;
int *num_succs;
for (i = 0; i < max_uid; ++i)
{
start[i] = end[i] = -1;
in_bb_p[i] = NOT_IN_BB;
}
for (i = n_basic_blocks - 1; i >= 0; --i)
{
rtx x;
start[INSN_UID (basic_block_head[i])] = i;
end[INSN_UID (basic_block_end[i])] = i;
for (x = basic_block_head[i]; x != NULL_RTX; x = NEXT_INSN (x))
{
in_bb_p[INSN_UID (x)]
= (in_bb_p[INSN_UID (x)] == NOT_IN_BB)
? IN_ONE_BB : IN_MULTIPLE_BB;
if (x == basic_block_end[i])
break;
}
}
/* Get the information about the basic blocks predecessors and
successors. */
s_preds = (int_list_ptr *) alloca (n_basic_blocks
* sizeof (int_list_ptr));
s_succs = (int_list_ptr *) alloca (n_basic_blocks
* sizeof (int_list_ptr));
num_preds = (int *) alloca (n_basic_blocks * sizeof (int));
num_succs = (int *) alloca (n_basic_blocks * sizeof (int));
compute_preds_succs (s_preds, s_succs, num_preds, num_succs);
/* Tell print-rtl that we want graph output. */
dump_for_graph = 1;
/* Start new function. */
start_fct (fp);
for (tmp_rtx = NEXT_INSN (rtx_first); NULL != tmp_rtx;
tmp_rtx = NEXT_INSN (tmp_rtx))
{
int did_output;
int edge_printed = 0;
rtx next_insn;
if (start[INSN_UID (tmp_rtx)] < 0 && end[INSN_UID (tmp_rtx)] < 0)
{
if (GET_CODE (tmp_rtx) == BARRIER)
continue;
if (GET_CODE (tmp_rtx) == NOTE
&& (1 || in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB))
continue;
}
if ((bb = start[INSN_UID (tmp_rtx)]) >= 0)
{
/* We start a subgraph for each basic block. */
start_bb (fp, bb);
if (bb == 0)
draw_edge (fp, 0, INSN_UID (tmp_rtx), 1, 0);
}
/* Print the data for this node. */
did_output = node_data (fp, tmp_rtx);
next_insn = next_nonnote_insn (tmp_rtx);
if ((bb = end[INSN_UID (tmp_rtx)]) >= 0)
{
int_list_ptr p;
/* End of the basic block. */
end_bb (fp, bb);
/* Now specify the edges to all the successors of this
basic block. */
for (p = s_succs[bb]; p != NULL; p = p->next)
{
int bb_succ = INT_LIST_VAL (p);
if (bb_succ >= 0)
{
rtx block_head = BLOCK_HEAD (bb_succ);
draw_edge (fp, INSN_UID (tmp_rtx),
INSN_UID (block_head),
next_insn != block_head, 0);
if (BLOCK_HEAD (bb_succ) == next_insn)
edge_printed = 1;
}
else if (bb_succ == EXIT_BLOCK)
{
draw_edge (fp, INSN_UID (tmp_rtx), 999999,
next_insn != 0, 0);
if (next_insn == 0)
edge_printed = 1;
}
else
abort ();
}
}
if (!edge_printed)
{
/* Don't print edges to barriers. */
if (next_insn == 0
|| GET_CODE (next_insn) != BARRIER)
draw_edge (fp, XINT (tmp_rtx, 0),
next_insn ? INSN_UID (next_insn) : 999999, 0, 0);
else
{
/* We draw the remaining edges in class 2. We have
to skip oevr the barrier since these nodes are
not printed at all. */
do
next_insn = NEXT_INSN (next_insn);
while (next_insn
&& (GET_CODE (next_insn) == NOTE
|| GET_CODE (next_insn) == BARRIER));
draw_edge (fp, XINT (tmp_rtx, 0),
next_insn ? INSN_UID (next_insn) : 999999, 0, 2);
}
}
}
dump_for_graph = 0;
end_fct (fp);
}
fclose (fp);
}
/* Similar as clean_dump_file, but this time for graph output files. */
void
clean_graph_dump_file (base, suffix)
const char *base;
const char *suffix;
{
size_t namelen = strlen (base);
size_t suffixlen = strlen (suffix);
size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
char *buf = (char *) alloca (namelen + extlen + suffixlen);
FILE *fp;
memcpy (buf, base, namelen);
memcpy (buf + namelen, suffix, suffixlen);
memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
fp = fopen (buf, "w");
if (fp == NULL)
pfatal_with_name (buf);
switch (graph_dump_format)
{
case vcg:
fputs ("graph: {\nport_sharing: no\n", fp);
break;
case no_graph:
abort ();
}
fclose (fp);
}
/* Do final work on the graph output file. */
void
finish_graph_dump_file (base, suffix)
const char *base;
const char *suffix;
{
size_t namelen = strlen (base);
size_t suffixlen = strlen (suffix);
size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
char *buf = (char *) alloca (namelen + suffixlen + extlen);
FILE *fp;
memcpy (buf, base, namelen);
memcpy (buf + namelen, suffix, suffixlen);
memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
fp = fopen (buf, "a");
if (fp != NULL)
{
switch (graph_dump_format)
{
case vcg:
fputs ("}\n", fp);
break;
case no_graph:
abort ();
}
fclose (fp);
}
}
/* Print RTL for GNU C Compiler. /* Print RTL for GNU C Compiler.
Copyright (C) 1987, 1988, 1992, 1997 Free Software Foundation, Inc. Copyright (C) 1987, 1988, 1992, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -60,13 +60,17 @@ extern char **insn_name_ptr; ...@@ -60,13 +60,17 @@ extern char **insn_name_ptr;
This must be defined here so that programs like gencodes can be linked. */ This must be defined here so that programs like gencodes can be linked. */
int flag_dump_unnumbered = 0; int flag_dump_unnumbered = 0;
/* Nonzero if we are dumping graphical description. */
int dump_for_graph;
/* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */ /* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */
static void static void
print_rtx (in_rtx) print_rtx (in_rtx)
register rtx in_rtx; register rtx in_rtx;
{ {
register int i, j; register int i = 0;
register int j;
register char *format_ptr; register char *format_ptr;
register int is_insn; register int is_insn;
...@@ -79,25 +83,38 @@ print_rtx (in_rtx) ...@@ -79,25 +83,38 @@ print_rtx (in_rtx)
if (in_rtx == 0) if (in_rtx == 0)
{ {
fprintf (outfile, "(nil)"); fputs ("(nil)", outfile);
sawclose = 1; sawclose = 1;
return; return;
} }
is_insn = (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i');
/* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER
in separate nodes and therefore have to handle them special here. */
if (dump_for_graph &&
(is_insn || GET_CODE (in_rtx) == NOTE || GET_CODE (in_rtx) == CODE_LABEL
|| GET_CODE (in_rtx) == BARRIER))
{
i = 3;
indent = 0;
}
else
{
/* print name of expression code */ /* print name of expression code */
fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx))); fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
if (in_rtx->in_struct) if (in_rtx->in_struct)
fprintf (outfile, "/s"); fputs ("/s", outfile);
if (in_rtx->volatil) if (in_rtx->volatil)
fprintf (outfile, "/v"); fputs ("/v", outfile);
if (in_rtx->unchanging) if (in_rtx->unchanging)
fprintf (outfile, "/u"); fputs ("/u", outfile);
if (in_rtx->integrated) if (in_rtx->integrated)
fprintf (outfile, "/i"); fputs ("/i", outfile);
if (GET_MODE (in_rtx) != VOIDmode) if (GET_MODE (in_rtx) != VOIDmode)
{ {
...@@ -107,11 +124,13 @@ print_rtx (in_rtx) ...@@ -107,11 +124,13 @@ print_rtx (in_rtx)
else else
fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
} }
}
is_insn = (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i'); /* Get the format string and skip the first elements if we have handled
format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); them already. */
format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
switch (*format_ptr++) switch (*format_ptr++)
{ {
case 'S': case 'S':
...@@ -141,9 +160,10 @@ print_rtx (in_rtx) ...@@ -141,9 +160,10 @@ print_rtx (in_rtx)
} }
if (XSTR (in_rtx, i) == 0) if (XSTR (in_rtx, i) == 0)
fprintf (outfile, " \"\""); fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
else else
fprintf (outfile, " (\"%s\")", XSTR (in_rtx, i)); fprintf (outfile, dump_for_graph ? " (\\\"%s\\\")" : " (\"%s\")",
XSTR (in_rtx, i));
sawclose = 1; sawclose = 1;
break; break;
...@@ -168,7 +188,7 @@ print_rtx (in_rtx) ...@@ -168,7 +188,7 @@ print_rtx (in_rtx)
(spaces + (sizeof spaces - 1 - indent * 2))); (spaces + (sizeof spaces - 1 - indent * 2)));
sawclose = 0; sawclose = 0;
} }
fprintf (outfile, "[ "); fputs ("[ ", outfile);
if (NULL != XVEC (in_rtx, i)) if (NULL != XVEC (in_rtx, i))
{ {
indent += 2; indent += 2;
...@@ -184,7 +204,7 @@ print_rtx (in_rtx) ...@@ -184,7 +204,7 @@ print_rtx (in_rtx)
fprintf (outfile, "\n%s", fprintf (outfile, "\n%s",
(spaces + (sizeof spaces - 1 - indent * 2))); (spaces + (sizeof spaces - 1 - indent * 2)));
fprintf (outfile, "] "); fputs ("] ", outfile);
sawclose = 1; sawclose = 1;
indent -= 2; indent -= 2;
break; break;
...@@ -205,7 +225,7 @@ print_rtx (in_rtx) ...@@ -205,7 +225,7 @@ print_rtx (in_rtx)
} }
else if (flag_dump_unnumbered else if (flag_dump_unnumbered
&& (is_insn || GET_CODE (in_rtx) == NOTE)) && (is_insn || GET_CODE (in_rtx) == NOTE))
fprintf (outfile, "#"); fputc ('#', outfile);
else else
fprintf (outfile, " %d", value); fprintf (outfile, " %d", value);
} }
...@@ -230,18 +250,18 @@ print_rtx (in_rtx) ...@@ -230,18 +250,18 @@ print_rtx (in_rtx)
if (XEXP (in_rtx, i) != NULL) if (XEXP (in_rtx, i) != NULL)
{ {
if (flag_dump_unnumbered) if (flag_dump_unnumbered)
fprintf (outfile, "#"); fputc ('#', outfile);
else else
fprintf (outfile, " %d", INSN_UID (XEXP (in_rtx, i))); fprintf (outfile, " %d", INSN_UID (XEXP (in_rtx, i)));
} }
else else
fprintf (outfile, " 0"); fputs (" 0", outfile);
sawclose = 0; sawclose = 0;
break; break;
case 'b': case 'b':
if (XBITMAP (in_rtx, i) == NULL) if (XBITMAP (in_rtx, i) == NULL)
fprintf (outfile, " {null}"); fputs (" {null}", outfile);
else else
bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}"); bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}");
sawclose = 0; sawclose = 0;
...@@ -253,7 +273,7 @@ print_rtx (in_rtx) ...@@ -253,7 +273,7 @@ print_rtx (in_rtx)
break; break;
case '*': case '*':
fprintf (outfile, " Unknown"); fputs (" Unknown", outfile);
sawclose = 0; sawclose = 0;
break; break;
...@@ -276,8 +296,15 @@ print_rtx (in_rtx) ...@@ -276,8 +296,15 @@ print_rtx (in_rtx)
} }
#endif #endif
fprintf (outfile, ")"); if (dump_for_graph
&& (is_insn || GET_CODE (in_rtx) == NOTE
|| GET_CODE (in_rtx) == CODE_LABEL || GET_CODE (in_rtx) == BARRIER))
sawclose = 0;
else
{
fputc (')', outfile);
sawclose = 1; sawclose = 1;
}
} }
/* Print an rtx on the current line of FILE. Initially indent IND /* Print an rtx on the current line of FILE. Initially indent IND
...@@ -386,7 +413,7 @@ print_rtl (outf, rtx_first) ...@@ -386,7 +413,7 @@ print_rtl (outf, rtx_first)
sawclose = 0; sawclose = 0;
if (rtx_first == 0) if (rtx_first == 0)
fprintf (outf, "(nil)\n"); fputs ("(nil)\n", outf);
else else
switch (GET_CODE (rtx_first)) switch (GET_CODE (rtx_first))
{ {
......
...@@ -212,6 +212,10 @@ static int print_single_switch PROTO((FILE *, int, int, char *, char *, char *, ...@@ -212,6 +212,10 @@ static int print_single_switch PROTO((FILE *, int, int, char *, char *, char *,
char *, char *)); char *, char *));
static void print_switch_values PROTO((FILE *, int, int, char *, char *, static void print_switch_values PROTO((FILE *, int, int, char *, char *,
char *)); char *));
void print_rtl_graph_with_bb PROTO ((const char *, const char *, rtx));
void clean_graph_dump_file PROTO ((const char *, const char *));
void finish_graph_dump_file PROTO ((const char *, const char *));
/* Length of line when printing switch values. */ /* Length of line when printing switch values. */
#define MAX_LINE 75 #define MAX_LINE 75
...@@ -288,6 +292,7 @@ int stack_reg_dump = 0; ...@@ -288,6 +292,7 @@ int stack_reg_dump = 0;
#ifdef MACHINE_DEPENDENT_REORG #ifdef MACHINE_DEPENDENT_REORG
int mach_dep_reorg_dump = 0; int mach_dep_reorg_dump = 0;
#endif #endif
enum graph_dump_types graph_dump_format;
/* Name for output file of assembly code, specified with -o. */ /* Name for output file of assembly code, specified with -o. */
...@@ -2606,50 +2611,122 @@ compile_file (name) ...@@ -2606,50 +2611,122 @@ compile_file (name)
pfatal_with_name (aux_info_file_name); pfatal_with_name (aux_info_file_name);
} }
/* Clear the dump files file. */ /* Clear the dump files. */
if (rtl_dump) if (rtl_dump)
clean_dump_file (".rtl"); clean_dump_file (".rtl");
if (jump_opt_dump) if (jump_opt_dump)
{
clean_dump_file (".jump"); clean_dump_file (".jump");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".jump");
}
if (addressof_dump) if (addressof_dump)
{
clean_dump_file (".addressof"); clean_dump_file (".addressof");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".addressof");
}
if (cse_dump) if (cse_dump)
{
clean_dump_file (".cse"); clean_dump_file (".cse");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".cse");
}
if (loop_dump) if (loop_dump)
{
clean_dump_file (".loop"); clean_dump_file (".loop");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".loop");
}
if (cse2_dump) if (cse2_dump)
{
clean_dump_file (".cse2"); clean_dump_file (".cse2");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".cse2");
}
if (branch_prob_dump) if (branch_prob_dump)
{
clean_dump_file (".bp"); clean_dump_file (".bp");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".bp");
}
if (flow_dump) if (flow_dump)
{
clean_dump_file (".flow"); clean_dump_file (".flow");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".flow");
}
if (combine_dump) if (combine_dump)
{
clean_dump_file (".combine"); clean_dump_file (".combine");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".combine");
}
if (regmove_dump) if (regmove_dump)
{
clean_dump_file (".regmove"); clean_dump_file (".regmove");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".regmove");
}
if (sched_dump) if (sched_dump)
{
clean_dump_file (".sched"); clean_dump_file (".sched");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".sched");
}
if (local_reg_dump) if (local_reg_dump)
{
clean_dump_file (".lreg"); clean_dump_file (".lreg");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".lreg");
}
if (global_reg_dump) if (global_reg_dump)
{
clean_dump_file (".greg"); clean_dump_file (".greg");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".greg");
}
if (sched2_dump) if (sched2_dump)
{
clean_dump_file (".sched2"); clean_dump_file (".sched2");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".sched2");
}
if (jump2_opt_dump) if (jump2_opt_dump)
{
clean_dump_file (".jump2"); clean_dump_file (".jump2");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".jump2");
}
#ifdef DELAY_SLOTS #ifdef DELAY_SLOTS
if (dbr_sched_dump) if (dbr_sched_dump)
{
clean_dump_file (".dbr"); clean_dump_file (".dbr");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".dbr");
}
#endif #endif
if (gcse_dump) if (gcse_dump)
{
clean_dump_file (".gcse"); clean_dump_file (".gcse");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".gcse");
}
#ifdef STACK_REGS #ifdef STACK_REGS
if (stack_reg_dump) if (stack_reg_dump)
{
clean_dump_file (".stack"); clean_dump_file (".stack");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".stack");
}
#endif #endif
#ifdef MACHINE_DEPENDENT_REORG #ifdef MACHINE_DEPENDENT_REORG
if (mach_dep_reorg_dump) if (mach_dep_reorg_dump)
{
clean_dump_file (".mach"); clean_dump_file (".mach");
if (graph_dump_format != no_graph)
clean_graph_dump_file (dump_base_name, ".mach");
}
#endif #endif
/* Open assembler code output file. */ /* Open assembler code output file. */
...@@ -3119,6 +3196,53 @@ compile_file (name) ...@@ -3119,6 +3196,53 @@ compile_file (name)
&& (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0)) && (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0))
fatal_io_error (asm_file_name); fatal_io_error (asm_file_name);
/* Do whatever is necessary to finish printing the graphs. */
if (graph_dump_format != no_graph)
{
if (jump_opt_dump)
finish_graph_dump_file (dump_base_name, ".jump");
if (addressof_dump)
finish_graph_dump_file (dump_base_name, ".addressof");
if (cse_dump)
finish_graph_dump_file (dump_base_name, ".cse");
if (loop_dump)
finish_graph_dump_file (dump_base_name, ".loop");
if (cse2_dump)
finish_graph_dump_file (dump_base_name, ".cse2");
if (branch_prob_dump)
finish_graph_dump_file (dump_base_name, ".bp");
if (flow_dump)
finish_graph_dump_file (dump_base_name, ".flow");
if (combine_dump)
finish_graph_dump_file (dump_base_name, ".combine");
if (regmove_dump)
finish_graph_dump_file (dump_base_name, ".regmove");
if (sched_dump)
finish_graph_dump_file (dump_base_name, ".sched");
if (local_reg_dump)
finish_graph_dump_file (dump_base_name, ".lreg");
if (global_reg_dump)
finish_graph_dump_file (dump_base_name, ".greg");
if (sched2_dump)
finish_graph_dump_file (dump_base_name, ".sched2");
if (jump2_opt_dump)
finish_graph_dump_file (dump_base_name, ".jump2");
#ifdef DELAY_SLOTS
if (dbr_sched_dump)
finish_graph_dump_file (dump_base_name, ".dbr");
#endif
if (gcse_dump)
finish_graph_dump_file (dump_base_name, ".gcse");
#ifdef STACK_REGS
if (stack_reg_dump)
finish_graph_dump_file (dump_base_name, ".stack");
#endif
#ifdef MACHINE_DEPENDENT_REORG
if (mach_dep_reorg_dump)
finish_graph_dump_file (dump_base_name, ".mach");
#endif
}
/* Free up memory for the benefit of leak detectors. */ /* Free up memory for the benefit of leak detectors. */
free_reg_info (); free_reg_info ();
...@@ -3546,14 +3670,22 @@ rest_of_compilation (decl) ...@@ -3546,14 +3670,22 @@ rest_of_compilation (decl)
/* Dump rtl code after cse, if we are doing that. */ /* Dump rtl code after cse, if we are doing that. */
if (cse_dump) if (cse_dump)
{
close_dump_file (print_rtl, insns); close_dump_file (print_rtl, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".cse", insns);
}
} }
purge_addressof (insns); purge_addressof (insns);
reg_scan (insns, max_reg_num (), 1); reg_scan (insns, max_reg_num (), 1);
if (addressof_dump) if (addressof_dump)
{
dump_rtl (".addressof", decl, print_rtl, insns); dump_rtl (".addressof", decl, print_rtl, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".addressof", insns);
}
/* Perform global cse. */ /* Perform global cse. */
...@@ -3565,7 +3697,11 @@ rest_of_compilation (decl) ...@@ -3565,7 +3697,11 @@ rest_of_compilation (decl)
TIMEVAR (gcse_time, gcse_main (insns, rtl_dump_file)); TIMEVAR (gcse_time, gcse_main (insns, rtl_dump_file));
if (gcse_dump) if (gcse_dump)
{
close_dump_file (print_rtl, insns); close_dump_file (print_rtl, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".gcse", insns);
}
} }
/* Move constant computations out of loops. */ /* Move constant computations out of loops. */
...@@ -3600,7 +3736,11 @@ rest_of_compilation (decl) ...@@ -3600,7 +3736,11 @@ rest_of_compilation (decl)
/* Dump rtl code after loop opt, if we are doing that. */ /* Dump rtl code after loop opt, if we are doing that. */
if (loop_dump) if (loop_dump)
{
close_dump_file (print_rtl, insns); close_dump_file (print_rtl, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".loop", insns);
}
} }
if (optimize > 0) if (optimize > 0)
...@@ -3640,7 +3780,11 @@ rest_of_compilation (decl) ...@@ -3640,7 +3780,11 @@ rest_of_compilation (decl)
/* Dump rtl code after cse, if we are doing that. */ /* Dump rtl code after cse, if we are doing that. */
if (cse2_dump) if (cse2_dump)
{
close_dump_file (print_rtl, insns); close_dump_file (print_rtl, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".cse2", insns);
}
} }
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
...@@ -3655,7 +3799,11 @@ rest_of_compilation (decl) ...@@ -3655,7 +3799,11 @@ rest_of_compilation (decl)
}); });
if (branch_prob_dump) if (branch_prob_dump)
{
close_dump_file (print_rtl, insns); close_dump_file (print_rtl, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".bp", insns);
}
} }
/* We are no longer anticipating cse in this function, at least. */ /* We are no longer anticipating cse in this function, at least. */
...@@ -3708,7 +3856,11 @@ rest_of_compilation (decl) ...@@ -3708,7 +3856,11 @@ rest_of_compilation (decl)
/* Dump rtl after flow analysis. */ /* Dump rtl after flow analysis. */
if (flow_dump) if (flow_dump)
{
close_dump_file (print_rtl_with_bb, insns); close_dump_file (print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".flow", insns);
}
/* If -opt, try combining insns through substitution. */ /* If -opt, try combining insns through substitution. */
...@@ -3719,7 +3871,11 @@ rest_of_compilation (decl) ...@@ -3719,7 +3871,11 @@ rest_of_compilation (decl)
/* Dump rtl code after insn combination. */ /* Dump rtl code after insn combination. */
if (combine_dump) if (combine_dump)
{
dump_rtl (".combine", decl, print_rtl_with_bb, insns); dump_rtl (".combine", decl, print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".combine", insns);
}
} }
/* Register allocation pre-pass, to reduce number of moves /* Register allocation pre-pass, to reduce number of moves
...@@ -3733,7 +3889,11 @@ rest_of_compilation (decl) ...@@ -3733,7 +3889,11 @@ rest_of_compilation (decl)
rtl_dump_file)); rtl_dump_file));
if (regmove_dump) if (regmove_dump)
{
close_dump_file (print_rtl_with_bb, insns); close_dump_file (print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".regmove", insns);
}
} }
/* Print function header into sched dump now /* Print function header into sched dump now
...@@ -3752,7 +3912,11 @@ rest_of_compilation (decl) ...@@ -3752,7 +3912,11 @@ rest_of_compilation (decl)
/* Dump rtl after instruction scheduling. */ /* Dump rtl after instruction scheduling. */
if (sched_dump) if (sched_dump)
{
close_dump_file (print_rtl_with_bb, insns); close_dump_file (print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".sched", insns);
}
} }
/* Unless we did stupid register allocation, /* Unless we did stupid register allocation,
...@@ -3776,6 +3940,8 @@ rest_of_compilation (decl) ...@@ -3776,6 +3940,8 @@ rest_of_compilation (decl)
TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file)); TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file));
close_dump_file (print_rtl_with_bb, insns); close_dump_file (print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".lreg", insns);
} }
if (global_reg_dump) if (global_reg_dump)
...@@ -3823,6 +3989,8 @@ rest_of_compilation (decl) ...@@ -3823,6 +3989,8 @@ rest_of_compilation (decl)
{ {
TIMEVAR (dump_time, dump_global_regs (rtl_dump_file)); TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
close_dump_file (print_rtl_with_bb, insns); close_dump_file (print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".greg", insns);
} }
if (optimize > 0 && flag_schedule_insns_after_reload) if (optimize > 0 && flag_schedule_insns_after_reload)
{ {
...@@ -3837,7 +4005,11 @@ rest_of_compilation (decl) ...@@ -3837,7 +4005,11 @@ rest_of_compilation (decl)
/* Dump rtl after post-reorder instruction scheduling. */ /* Dump rtl after post-reorder instruction scheduling. */
if (sched2_dump) if (sched2_dump)
{
close_dump_file (print_rtl_with_bb, insns); close_dump_file (print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".sched2", insns);
}
} }
#ifdef LEAF_REGISTERS #ifdef LEAF_REGISTERS
...@@ -3860,7 +4032,11 @@ rest_of_compilation (decl) ...@@ -3860,7 +4032,11 @@ rest_of_compilation (decl)
/* Dump rtl code after jump, if we are doing that. */ /* Dump rtl code after jump, if we are doing that. */
if (jump2_opt_dump) if (jump2_opt_dump)
{
dump_rtl (".jump2", decl, print_rtl_with_bb, insns); dump_rtl (".jump2", decl, print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".jump2", insns);
}
} }
/* If a machine dependent reorganization is needed, call it. */ /* If a machine dependent reorganization is needed, call it. */
...@@ -3868,7 +4044,11 @@ rest_of_compilation (decl) ...@@ -3868,7 +4044,11 @@ rest_of_compilation (decl)
MACHINE_DEPENDENT_REORG (insns); MACHINE_DEPENDENT_REORG (insns);
if (mach_dep_reorg_dump) if (mach_dep_reorg_dump)
{
dump_rtl (".mach", decl, print_rtl_with_bb, insns); dump_rtl (".mach", decl, print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".mach", insns);
}
#endif #endif
/* If a scheduling pass for delayed branches is to be done, /* If a scheduling pass for delayed branches is to be done,
...@@ -3880,7 +4060,11 @@ rest_of_compilation (decl) ...@@ -3880,7 +4060,11 @@ rest_of_compilation (decl)
TIMEVAR (dbr_sched_time, dbr_schedule (insns, rtl_dump_file)); TIMEVAR (dbr_sched_time, dbr_schedule (insns, rtl_dump_file));
if (dbr_sched_dump) if (dbr_sched_dump)
{
dump_rtl (".dbr", decl, print_rtl_with_bb, insns); dump_rtl (".dbr", decl, print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".dbr", insns);
}
} }
#endif #endif
...@@ -3897,7 +4081,11 @@ rest_of_compilation (decl) ...@@ -3897,7 +4081,11 @@ rest_of_compilation (decl)
TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file)); TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file));
if (stack_reg_dump) if (stack_reg_dump)
{
dump_rtl (".stack", decl, print_rtl_with_bb, insns); dump_rtl (".stack", decl, print_rtl_with_bb, insns);
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".stack", insns);
}
#endif #endif
/* Now turn the rtl into assembler code. */ /* Now turn the rtl into assembler code. */
...@@ -4015,6 +4203,9 @@ rest_of_compilation (decl) ...@@ -4015,6 +4203,9 @@ rest_of_compilation (decl)
*except* what is spent in this function. */ *except* what is spent in this function. */
parse_time -= get_run_time () - start_time; parse_time -= get_run_time () - start_time;
/* Reset global variables. */
free_basic_block_vars (0);
} }
static void static void
...@@ -4548,6 +4739,9 @@ main (argc, argv) ...@@ -4548,6 +4739,9 @@ main (argc, argv)
case 'N': case 'N':
regmove_dump = 1; regmove_dump = 1;
break; break;
case 'v':
graph_dump_format = vcg;
break;
case 'y': case 'y':
set_yydebug (1); set_yydebug (1);
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment