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
This commit is contained in:
Ulrich Drepper 1998-11-23 16:41:12 +00:00 committed by Richard Henderson
parent a05e22b814
commit 735a0e3356
6 changed files with 833 additions and 97 deletions

View File

@ -1,3 +1,19 @@
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>
* configure.in: Look for <sys/stat.h>.

View File

@ -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-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 \
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
# 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 \
c-iterate.o: c-iterate.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-tree.h \
flags.h toplev.h $(EXPR_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 \
version.o choose-temp.o mkstemp.o $(LIBDEPS)

View File

@ -502,3 +502,14 @@ extern int current_function_is_thunk;
/* Value of the -G xx switch, and whether it was passed or not. */
extern int g_switch_value;
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;

486
gcc/graph.c Normal file
View File

@ -0,0 +1,486 @@
/* 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);
}
}

View File

@ -1,5 +1,5 @@
/* 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.
@ -60,13 +60,17 @@ extern char **insn_name_ptr;
This must be defined here so that programs like gencodes can be linked. */
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. */
static void
print_rtx (in_rtx)
register rtx in_rtx;
{
register int i, j;
register int i = 0;
register int j;
register char *format_ptr;
register int is_insn;
@ -79,39 +83,54 @@ print_rtx (in_rtx)
if (in_rtx == 0)
{
fprintf (outfile, "(nil)");
fputs ("(nil)", outfile);
sawclose = 1;
return;
}
/* print name of expression code */
fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
is_insn = (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i');
if (in_rtx->in_struct)
fprintf (outfile, "/s");
if (in_rtx->volatil)
fprintf (outfile, "/v");
if (in_rtx->unchanging)
fprintf (outfile, "/u");
if (in_rtx->integrated)
fprintf (outfile, "/i");
if (GET_MODE (in_rtx) != VOIDmode)
/* 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))
{
/* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST)
fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
else
fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
i = 3;
indent = 0;
}
else
{
/* print name of expression code */
fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
if (in_rtx->in_struct)
fputs ("/s", outfile);
if (in_rtx->volatil)
fputs ("/v", outfile);
if (in_rtx->unchanging)
fputs ("/u", outfile);
if (in_rtx->integrated)
fputs ("/i", outfile);
if (GET_MODE (in_rtx) != VOIDmode)
{
/* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST)
fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
else
fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
}
}
is_insn = (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i');
format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
/* Get the format string and skip the first elements if we have handled
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++)
{
case 'S':
@ -141,9 +160,10 @@ print_rtx (in_rtx)
}
if (XSTR (in_rtx, i) == 0)
fprintf (outfile, " \"\"");
fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
else
fprintf (outfile, " (\"%s\")", XSTR (in_rtx, i));
fprintf (outfile, dump_for_graph ? " (\\\"%s\\\")" : " (\"%s\")",
XSTR (in_rtx, i));
sawclose = 1;
break;
@ -168,7 +188,7 @@ print_rtx (in_rtx)
(spaces + (sizeof spaces - 1 - indent * 2)));
sawclose = 0;
}
fprintf (outfile, "[ ");
fputs ("[ ", outfile);
if (NULL != XVEC (in_rtx, i))
{
indent += 2;
@ -184,7 +204,7 @@ print_rtx (in_rtx)
fprintf (outfile, "\n%s",
(spaces + (sizeof spaces - 1 - indent * 2)));
fprintf (outfile, "] ");
fputs ("] ", outfile);
sawclose = 1;
indent -= 2;
break;
@ -205,7 +225,7 @@ print_rtx (in_rtx)
}
else if (flag_dump_unnumbered
&& (is_insn || GET_CODE (in_rtx) == NOTE))
fprintf (outfile, "#");
fputc ('#', outfile);
else
fprintf (outfile, " %d", value);
}
@ -230,18 +250,18 @@ print_rtx (in_rtx)
if (XEXP (in_rtx, i) != NULL)
{
if (flag_dump_unnumbered)
fprintf (outfile, "#");
fputc ('#', outfile);
else
fprintf (outfile, " %d", INSN_UID (XEXP (in_rtx, i)));
}
else
fprintf (outfile, " 0");
fputs (" 0", outfile);
sawclose = 0;
break;
case 'b':
if (XBITMAP (in_rtx, i) == NULL)
fprintf (outfile, " {null}");
fputs (" {null}", outfile);
else
bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}");
sawclose = 0;
@ -253,7 +273,7 @@ print_rtx (in_rtx)
break;
case '*':
fprintf (outfile, " Unknown");
fputs (" Unknown", outfile);
sawclose = 0;
break;
@ -276,8 +296,15 @@ print_rtx (in_rtx)
}
#endif
fprintf (outfile, ")");
sawclose = 1;
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;
}
}
/* Print an rtx on the current line of FILE. Initially indent IND
@ -386,7 +413,7 @@ print_rtl (outf, rtx_first)
sawclose = 0;
if (rtx_first == 0)
fprintf (outf, "(nil)\n");
fputs ("(nil)\n", outf);
else
switch (GET_CODE (rtx_first))
{

View File

@ -212,6 +212,10 @@ static int print_single_switch PROTO((FILE *, int, int, char *, char *, char *,
char *, char *));
static void print_switch_values PROTO((FILE *, int, int, 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. */
#define MAX_LINE 75
@ -288,6 +292,7 @@ int stack_reg_dump = 0;
#ifdef MACHINE_DEPENDENT_REORG
int mach_dep_reorg_dump = 0;
#endif
enum graph_dump_types graph_dump_format;
/* Name for output file of assembly code, specified with -o. */
@ -2606,50 +2611,122 @@ compile_file (name)
pfatal_with_name (aux_info_file_name);
}
/* Clear the dump files file. */
/* Clear the dump files. */
if (rtl_dump)
clean_dump_file (".rtl");
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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
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
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
#ifdef MACHINE_DEPENDENT_REORG
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
/* Open assembler code output file. */
@ -3119,6 +3196,53 @@ compile_file (name)
&& (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0))
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_reg_info ();
@ -3544,28 +3668,40 @@ rest_of_compilation (decl)
!JUMP_AFTER_REGSCAN));
/* Dump rtl code after cse, if we are doing that. */
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);
reg_scan (insns, max_reg_num (), 1);
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. */
if (optimize > 0 && flag_gcse)
{
if (gcse_dump)
open_dump_file (".gcse", IDENTIFIER_POINTER (DECL_NAME (decl)));
TIMEVAR (gcse_time, gcse_main (insns, rtl_dump_file));
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. */
@ -3596,18 +3732,22 @@ rest_of_compilation (decl)
}
loop_optimize (insns, rtl_dump_file, flag_unroll_loops, 1);
});
/* Dump rtl code after loop opt, if we are doing that. */
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 (cse2_dump)
open_dump_file (".cse2", decl_printable_name (decl, 2));
if (flag_rerun_cse_after_loop)
{
/* Running another jump optimization pass before the second
@ -3636,28 +3776,36 @@ rest_of_compilation (decl)
TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 0));
}
/* Dump rtl code after cse, if we are doing that. */
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 (branch_prob_dump)
open_dump_file (".bp", decl_printable_name (decl, 2));
TIMEVAR
(branch_prob_time,
{
branch_prob (insns, rtl_dump_file);
});
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. */
cse_not_expected = 1;
@ -3708,18 +3856,26 @@ rest_of_compilation (decl)
/* Dump rtl after flow analysis. */
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 (optimize > 0)
{
TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ()));
/* Dump rtl code after insn combination. */
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
@ -3728,12 +3884,16 @@ rest_of_compilation (decl)
{
if (regmove_dump)
open_dump_file (".regmove", decl_printable_name (decl, 2));
TIMEVAR (regmove_time, regmove_optimize (insns, max_reg_num (),
rtl_dump_file));
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
@ -3743,16 +3903,20 @@ rest_of_compilation (decl)
{
if (sched_dump)
open_dump_file (".sched", decl_printable_name (decl, 2));
/* Do control and data sched analysis,
and write some of the results to dump file. */
TIMEVAR (sched_time, schedule_insns (rtl_dump_file));
/* Dump rtl after instruction scheduling. */
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,
@ -3771,11 +3935,13 @@ rest_of_compilation (decl)
if (local_reg_dump)
{
open_dump_file (".lreg", decl_printable_name (decl, 2));
TIMEVAR (dump_time, dump_flow_info (rtl_dump_file));
TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file));
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)
@ -3823,6 +3989,8 @@ rest_of_compilation (decl)
{
TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
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)
{
@ -3837,7 +4005,11 @@ rest_of_compilation (decl)
/* Dump rtl after post-reorder instruction scheduling. */
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
@ -3856,11 +4028,15 @@ rest_of_compilation (decl)
TIMEVAR (jump_time, jump_optimize (insns, JUMP_CROSS_JUMP,
JUMP_NOOP_MOVES,
!JUMP_AFTER_REGSCAN));
/* Dump rtl code after jump, if we are doing that. */
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. */
@ -3868,7 +4044,11 @@ rest_of_compilation (decl)
MACHINE_DEPENDENT_REORG (insns);
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
/* If a scheduling pass for delayed branches is to be done,
@ -3878,9 +4058,13 @@ rest_of_compilation (decl)
if (optimize > 0 && flag_delayed_branch)
{
TIMEVAR (dbr_sched_time, dbr_schedule (insns, rtl_dump_file));
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
@ -3897,7 +4081,11 @@ rest_of_compilation (decl)
TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file));
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
/* Now turn the rtl into assembler code. */
@ -4015,6 +4203,9 @@ rest_of_compilation (decl)
*except* what is spent in this function. */
parse_time -= get_run_time () - start_time;
/* Reset global variables. */
free_basic_block_vars (0);
}
static void
@ -4548,6 +4739,9 @@ main (argc, argv)
case 'N':
regmove_dump = 1;
break;
case 'v':
graph_dump_format = vcg;
break;
case 'y':
set_yydebug (1);
break;