+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>.
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
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)
/* 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;
--- /dev/null
+/* 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;
+ }
+}
+\f
+/* 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.
- 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 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;
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');
+
+ /* 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 */
+ fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
- if (in_rtx->in_struct)
- fprintf (outfile, "/s");
+ if (in_rtx->in_struct)
+ fputs ("/s", outfile);
- if (in_rtx->volatil)
- fprintf (outfile, "/v");
+ if (in_rtx->volatil)
+ fputs ("/v", outfile);
- if (in_rtx->unchanging)
- fprintf (outfile, "/u");
+ if (in_rtx->unchanging)
+ fputs ("/u", outfile);
- if (in_rtx->integrated)
- fprintf (outfile, "/i");
+ 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)));
+ 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':
}
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;
(spaces + (sizeof spaces - 1 - indent * 2)));
sawclose = 0;
}
- fprintf (outfile, "[ ");
+ fputs ("[ ", outfile);
if (NULL != XVEC (in_rtx, i))
{
indent += 2;
fprintf (outfile, "\n%s",
(spaces + (sizeof spaces - 1 - indent * 2)));
- fprintf (outfile, "] ");
+ fputs ("] ", outfile);
sawclose = 1;
indent -= 2;
break;
}
else if (flag_dump_unnumbered
&& (is_insn || GET_CODE (in_rtx) == NOTE))
- fprintf (outfile, "#");
+ fputc ('#', outfile);
else
fprintf (outfile, " %d", value);
}
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;
break;
case '*':
- fprintf (outfile, " Unknown");
+ fputs (" Unknown", outfile);
sawclose = 0;
break;
}
#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
sawclose = 0;
if (rtx_first == 0)
- fprintf (outf, "(nil)\n");
+ fputs ("(nil)\n", outf);
else
switch (GET_CODE (rtx_first))
{
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
#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. */
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. */
&& (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 ();
!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. */
}
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
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;
/* 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
{
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
{
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,
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)
{
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)
{
/* 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
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. */
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,
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
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. */
*except* what is spent in this function. */
parse_time -= get_run_time () - start_time;
+
+ /* Reset global variables. */
+ free_basic_block_vars (0);
}
\f
static void
case 'N':
regmove_dump = 1;
break;
+ case 'v':
+ graph_dump_format = vcg;
+ break;
case 'y':
set_yydebug (1);
break;