public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Rework RTL CFG graph dumping to dump DOT format
@ 2012-11-23  9:47 Steven Bosscher
  2012-11-26 15:46 ` Richard Biener
  0 siblings, 1 reply; 7+ messages in thread
From: Steven Bosscher @ 2012-11-23  9:47 UTC (permalink / raw)
  To: GCC Patches; +Cc: rsandifo

[-- Attachment #1: Type: text/plain, Size: 892 bytes --]

Hello,

The graph.[ch] code to dump the CFG for viewing with VCG is quite
broken and hasn't been updated to follow the advances in the CFG
infrastructure.

The attached patch is the first in a series of patches I have planned
to update the CFG-as-graph dumping code to dump GraphViz DOT input
instead. The attached archive is an example input/output.

There's still quite a lot of work to be done:
- use pretty-print in the slim RTL dumping
- move the escaped-string printing into pretty-print
- make the basic block content dumping a cfghook
- make these dumps work for GIMPLE also

For the moment, this is a good starting point.

Obviously there are no changes in code generation due to this patch,
so IMHO this patch (and the rest of the series) should be safe for
stage3. Hopefully everyone else agrees :-)

Bootstrapped&tested on powerpc64-unknown-linux-gnu. OK for trunk?

Ciao!
Steven

[-- Attachment #2: t.tar.gz --]
[-- Type: application/x-gzip, Size: 75309 bytes --]

[-- Attachment #3: cfg_graph_dot.diff --]
[-- Type: application/octet-stream, Size: 35250 bytes --]

gcc/
	* doc/invoke.texi: Remove -dv documentation.  Fix up graph dump related
	documentation.  Document the '-graph' dump option.  Complete the '-slim'
	dump option documentation.

	* common.opt (Variable graph_dump_format): Remove.
	* flag-types.h (enum graph_dump_types): Remove.
	* flags.h (dump_for_graph): Remove.
	* opts.c (decode_d_option): Remove -dv handling.
	* sched-int.h (print_insn, print_pattern, print_value): Move prototypes
	from here ...
	* rtl.h: ...to here.  Add note that these functions ought to be in
	another file.
	* sched-vis.c (print_insn): Add detailed dump for insn notes.
	* print-rtl.c (dump_for_graph): Remove.
	(print_rtx): Remove dump_for_graph related code.
	* graph.c: Almost complete re-write to dump DOT (GraphViz) dumps
	instead of VCG dumps.
	* graph.h (print_rtl_graph_with_bb): Update prototype.
	* passes.c (finish_optimization_passes): Fix profile dump finishing.
	Unconditionally loop over graph dumps to finalize.
	(execute_function_dump): Split code to dump graphs to separate block.
	(execute_one_pass): Don't set TDF_GRAPH here, let the dump option
	decoders do their job.

	* ddg.c (vcg_print_ddg): Make it a DEBUG_FUNCTION.
	* toplev.c: Don't include graph.h.
	* tree-optimize.c: Don't include graph.h.

testsuite/
	* testsuite/gcc.dg/20050811-1.c: Change -dv option to -graph option
	to -fdump-rtl-all.
	* testsuite/gcc.dg/pr37858.c: Remove -dv option.

Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 193650)
+++ doc/invoke.texi	(working copy)
@@ -5369,7 +5369,7 @@ appended with a sequential number starting from 1.
 comma-separated list of function ranges or assembler names.  Each range is a number
 pair separated by a colon.  The range is inclusive in both ends.  If the range
 is trivial, the number pair can be simplified as a single number.  If the
-function's cgraph node's @var{uid} falls within one of the specified ranges,
+function's call graph node's @var{uid} falls within one of the specified ranges,
 the @var{pass} is disabled for that function.  The @var{uid} is shown in the
 function header of a dump file, and the pass names can be dumped by using
 option @option{-fdump-passes}.
@@ -5725,12 +5725,6 @@ also printed.
 Dump the RTL in the assembler output as a comment before each instruction.
 Also turns on @option{-dp} annotation.
 
-@item -dv
-@opindex dv
-For each of the other indicated dump files (@option{-fdump-rtl-@var{pass}}),
-dump a representation of the control flow graph suitable for viewing with VCG
-to @file{@var{file}.@var{pass}.vcg}.
-
 @item -dx
 @opindex dx
 Just generate RTL for a function instead of compiling it.  Usually used
@@ -5839,10 +5833,16 @@ If @code{DECL_ASSEMBLER_NAME} has been set for a g
 in the dump instead of @code{DECL_NAME}.  Its primary use is ease of
 use working backward from mangled names in the assembly file.
 @item slim
-Inhibit dumping of members of a scope or body of a function merely
-because that scope has been reached.  Only dump such items when they
-are directly reachable by some other path.  When dumping pretty-printed
-trees, this option inhibits dumping the bodies of control structures.
+When dumping front-end intermediate representations, inhibit dumping
+of members of a scope or body of a function merely because that scope
+has been reached.  Only dump such items when they are directly reachable
+by some other path.
+
+When dumping pretty-printed trees, this option inhibits dumping the
+bodies of control structures.
+
+When dumping RTL, print the RTL in slim (condensed) form instead of
+the default LISP-like representation.
 @item raw
 Print a raw representation of the tree.  By default, trees are
 pretty-printed into a C-like representation.
@@ -5854,6 +5854,16 @@ Enable dumping various statistics about the pass (
 option).
 @item blocks
 Enable showing basic block boundaries (disabled in raw dumps).
+@item graph
+For each of the other indicated dump files (@option{-fdump-rtl-@var{pass}}),
+dump a representation of the control flow graph suitable for viewing with
+GraphViz to @file{@var{file}.@var{passid}.@var{pass}.dot}.  Note that if
+the file contains more than one function, the generated file cannot be
+used directly by GraphViz@.  You must cut and paste each function's
+graph into its own separate file first.
+
+This option currently only works for RTL dumps, and the RTL is always
+dumped in slim form.
 @item vops
 Enable showing virtual operands for every statement.
 @item lineno
Index: common.opt
===================================================================
--- common.opt	(revision 193650)
+++ common.opt	(working copy)
@@ -174,9 +174,6 @@ int rtl_dump_and_exit
 Variable
 int flag_print_asm_name
 
-Variable
-enum graph_dump_types graph_dump_format = no_graph
-
 ; Name of top-level original source file (what was input to cpp).
 ; This comes from the #-command at the beginning of the actual input.
 ; If there isn't any there, then this is the cc1 input file name.
Index: flag-types.h
===================================================================
--- flag-types.h	(revision 193650)
+++ flag-types.h	(working copy)
@@ -141,13 +141,6 @@ enum excess_precision
   EXCESS_PRECISION_STANDARD
 };
 
-/* Selection of the graph form.  */
-enum graph_dump_types
-{
-  no_graph = 0,
-  vcg
-};
-
 /* Type of stack check.  */
 enum stack_check_type
 {
Index: flags.h
===================================================================
--- flags.h	(revision 193650)
+++ flags.h	(working copy)
@@ -89,9 +89,6 @@ extern struct target_flag_state *this_target_flag_
 #define flag_excess_precision \
   (this_target_flag_state->x_flag_excess_precision)
 
-/* Nonzero if we dump in VCG format, not plain text.  */
-extern int dump_for_graph;
-
 /* Returns TRUE if generated code should match ABI version N or
    greater is in use.  */
 
Index: opts.c
===================================================================
--- opts.c	(revision 193650)
+++ opts.c	(working copy)
@@ -1982,9 +1982,6 @@ decode_d_option (const char *arg, struct gcc_optio
 	opts->x_flag_dump_rtl_in_asm = 1;
 	opts->x_flag_print_asm_name = 1;
 	break;
-      case 'v':
-	opts->x_graph_dump_format = vcg;
-	break;
       case 'x':
 	opts->x_rtl_dump_and_exit = 1;
 	break;
Index: sched-int.h
===================================================================
--- sched-int.h	(revision 193650)
+++ sched-int.h	(working copy)
@@ -1578,11 +1578,5 @@ extern void sd_debug_lists (rtx, sd_list_types_def
 
 #endif /* INSN_SCHEDULING */
 
-/* Functions in sched-vis.c.  These must be outside INSN_SCHEDULING as
-   sched-vis.c is compiled always.  */
-extern void print_insn (char *, const_rtx, int);
-extern void print_pattern (char *, const_rtx, int);
-extern void print_value (char *, const_rtx, int);
-
 #endif /* GCC_SCHED_INT_H */
 
Index: rtl.h
===================================================================
--- rtl.h	(revision 193650)
+++ rtl.h	(working copy)
@@ -2605,6 +2605,14 @@ extern int print_rtl_single (FILE *, const_rtx);
 extern int print_rtl_single_with_indent (FILE *, const_rtx, int);
 extern void print_inline_rtx (FILE *, const_rtx, int);
 
+/* Functions in sched-vis.c.  These must be outside INSN_SCHEDULING as
+   sched-vis.c is compiled always.  FIXME: Ideally these functions would
+   not be in sched-vis.c but in rtl.c, because they are not only used
+   by the scheduler anymore but for all "slim" RTL dumping.  */
+extern void print_insn (char *, const_rtx, int);
+extern void print_pattern (char *, const_rtx, int);
+extern void print_value (char *, const_rtx, int);
+
 /* In function.c */
 extern void reposition_prologue_and_epilogue_notes (void);
 extern int prologue_epilogue_contains (const_rtx);
Index: sched-vis.c
===================================================================
--- sched-vis.c	(revision 193650)
+++ sched-vis.c	(working copy)
@@ -782,12 +782,53 @@ print_insn (char *buf, const_rtx x, int verbose)
       sprintf (buf, "i%4d: barrier", INSN_UID (x));
       break;
     case NOTE:
-      sprintf (buf, " %4d %s", INSN_UID (x),
-	       GET_NOTE_INSN_NAME (NOTE_KIND (x)));
-      break;
+      {
+        int uid = INSN_UID (x);
+        const char *note_name = GET_NOTE_INSN_NAME (NOTE_KIND (x));
+	switch (NOTE_KIND (x))
+	  {
+	  case NOTE_INSN_EH_REGION_BEG:
+	  case NOTE_INSN_EH_REGION_END:
+	    sprintf (buf, " %4d %s %d", uid, note_name,
+		     NOTE_EH_HANDLER (x));
+	    break;
+
+	  case NOTE_INSN_BLOCK_BEG:
+	  case NOTE_INSN_BLOCK_END:
+	    sprintf (buf, " %4d %s %d", uid, note_name,
+		     BLOCK_NUMBER (NOTE_BLOCK (x)));
+	    break;
+
+	  case NOTE_INSN_BASIC_BLOCK:
+	    sprintf (buf, " %4d %s %d", uid, note_name,
+		     NOTE_BASIC_BLOCK (x)->index);
+	    break;
+
+	  case NOTE_INSN_DELETED_LABEL:
+	  case NOTE_INSN_DELETED_DEBUG_LABEL:
+	    {
+	      const char *label = NOTE_DELETED_LABEL_NAME (x);
+	      if (label == NULL)
+		label = "";
+	      sprintf (buf, " %4d %s (\"%s\")", uid, note_name, label);
+	    }
+	    break;
+
+	  case NOTE_INSN_VAR_LOCATION:
+	    print_pattern (t, NOTE_VAR_LOCATION (x), verbose);
+	    sprintf (buf, " %4d %s {%s}", uid, note_name, t);
+	    break;
+
+	  default:
+	    sprintf (buf, " %4d %s", uid, note_name);
+	    break;
+	  }
+	break;
+      }
     default:
       sprintf (buf, "i%4d  <What %s?>", INSN_UID (x),
 	       GET_RTX_NAME (GET_CODE (x)));
+      break;
     }
 }				/* print_insn */
 
Index: print-rtl.c
===================================================================
--- print-rtl.c	(revision 193650)
+++ print-rtl.c	(working copy)
@@ -77,9 +77,6 @@ int flag_dump_unnumbered_links = 0;
 /* Nonzero means use simplified format without flags, modes, etc.  */
 int flag_simple = 0;
 
-/* Nonzero if we are dumping graphical description.  */
-int dump_for_graph;
-
 #ifndef GENERATOR_FILE
 void
 print_mem_expr (FILE *outfile, const_tree expr)
@@ -124,74 +121,62 @@ print_rtx (const_rtx in_rtx)
 
   is_insn = INSN_P (in_rtx);
 
-  /* 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 || NOTE_P (in_rtx)
-	  || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))
-    {
-      i = 3;
-      indent = 0;
-    }
+  /* Print name of expression code.  */
+  if (flag_simple && CONST_INT_P (in_rtx))
+    fputc ('(', outfile);
   else
+    fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
+
+  if (! flag_simple)
     {
-      /* Print name of expression code.  */
-      if (flag_simple && CONST_INT_P (in_rtx))
-	fputc ('(', outfile);
-      else
-	fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
+      if (RTX_FLAG (in_rtx, in_struct))
+	fputs ("/s", outfile);
 
-      if (! flag_simple)
-	{
-	  if (RTX_FLAG (in_rtx, in_struct))
-	    fputs ("/s", outfile);
+      if (RTX_FLAG (in_rtx, volatil))
+	fputs ("/v", outfile);
 
-	  if (RTX_FLAG (in_rtx, volatil))
-	    fputs ("/v", outfile);
+      if (RTX_FLAG (in_rtx, unchanging))
+	fputs ("/u", outfile);
 
-	  if (RTX_FLAG (in_rtx, unchanging))
-	    fputs ("/u", outfile);
+      if (RTX_FLAG (in_rtx, frame_related))
+	fputs ("/f", outfile);
 
-	  if (RTX_FLAG (in_rtx, frame_related))
-	    fputs ("/f", outfile);
+      if (RTX_FLAG (in_rtx, jump))
+	fputs ("/j", outfile);
 
-	  if (RTX_FLAG (in_rtx, jump))
-	    fputs ("/j", outfile);
+      if (RTX_FLAG (in_rtx, call))
+	fputs ("/c", outfile);
 
-	  if (RTX_FLAG (in_rtx, call))
-	    fputs ("/c", outfile);
+      if (RTX_FLAG (in_rtx, return_val))
+	fputs ("/i", outfile);
 
-	  if (RTX_FLAG (in_rtx, return_val))
-	    fputs ("/i", outfile);
+      /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */
+      if ((GET_CODE (in_rtx) == EXPR_LIST
+	   || GET_CODE (in_rtx) == INSN_LIST)
+	  && (int)GET_MODE (in_rtx) < REG_NOTE_MAX)
+	fprintf (outfile, ":%s",
+		 GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
 
-	  /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */
-	  if ((GET_CODE (in_rtx) == EXPR_LIST
-	       || GET_CODE (in_rtx) == INSN_LIST)
-	      && (int)GET_MODE (in_rtx) < REG_NOTE_MAX)
-	    fprintf (outfile, ":%s",
-		     GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
+      /* For other rtl, print the mode if it's not VOID.  */
+      else if (GET_MODE (in_rtx) != VOIDmode)
+	fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
 
-	  /* For other rtl, print the mode if it's not VOID.  */
-	  else if (GET_MODE (in_rtx) != VOIDmode)
-	    fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
-
 #ifndef GENERATOR_FILE
-	  if (GET_CODE (in_rtx) == VAR_LOCATION)
-	    {
-	      if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST)
-		fputs (" <debug string placeholder>", outfile);
-	      else
-		print_mem_expr (outfile, PAT_VAR_LOCATION_DECL (in_rtx));
-	      fputc (' ', outfile);
-	      print_rtx (PAT_VAR_LOCATION_LOC (in_rtx));
-	      if (PAT_VAR_LOCATION_STATUS (in_rtx)
-		  == VAR_INIT_STATUS_UNINITIALIZED)
-		fprintf (outfile, " [uninit]");
-	      sawclose = 1;
-	      i = GET_RTX_LENGTH (VAR_LOCATION);
-	    }
-#endif
+      if (GET_CODE (in_rtx) == VAR_LOCATION)
+	{
+	  if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST)
+	    fputs (" <debug string placeholder>", outfile);
+	  else
+	    print_mem_expr (outfile, PAT_VAR_LOCATION_DECL (in_rtx));
+	  fputc (' ', outfile);
+	  print_rtx (PAT_VAR_LOCATION_LOC (in_rtx));
+	  if (PAT_VAR_LOCATION_STATUS (in_rtx)
+	      == VAR_INIT_STATUS_UNINITIALIZED)
+	    fprintf (outfile, " [uninit]");
+	  sawclose = 1;
+	  i = GET_RTX_LENGTH (VAR_LOCATION);
 	}
+#endif
     }
 
 #ifndef GENERATOR_FILE
@@ -217,14 +202,9 @@ print_rtx (const_rtx in_rtx)
       string:
 
 	if (str == 0)
-	  fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
+	  fputs (" \"\"", outfile);
 	else
-	  {
-	    if (dump_for_graph)
-	      fprintf (outfile, " (\\\"%s\\\")", str);
-	    else
-	      fprintf (outfile, " (\"%s\")", str);
-	  }
+	  fprintf (outfile, " (\"%s\")", str);
 	sawclose = 1;
 	break;
 
@@ -652,15 +632,7 @@ print_rtx (const_rtx in_rtx)
       break;
     }
 
-  if (dump_for_graph
-      && (is_insn || NOTE_P (in_rtx)
-	  || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))
-    sawclose = 0;
-  else
-    {
-      fputc (')', outfile);
-      sawclose = 1;
-    }
+  fputc (')', outfile);
 }
 
 /* Print an rtx on the current line of FILE.  Initially indent IND
Index: graph.c
===================================================================
--- graph.c	(revision 193650)
+++ graph.c	(working copy)
@@ -1,7 +1,8 @@
 /* Output routines for graphical representation.
-   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2007, 2008, 2010
+   Copyright (C) 1998-2012
    Free Software Foundation, Inc.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+   Rewritten for DOT output by Steven Bosscher, 2012.
 
 This file is part of GCC.
 
@@ -22,396 +23,242 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "flags.h"
-#include "function.h"
-#include "hard-reg-set.h"
-#include "obstack.h"
+#include "diagnostic-core.h" /* for fatal_error */
+#include "sbitmap.h"
 #include "basic-block.h"
-#include "diagnostic-core.h"
+#include "rtl.h"
+#include "tree.h"
 #include "graph.h"
-#include "emit-rtl.h"
 
-static const char *const graph_ext[] =
+/* DOT files with the .dot extension are recognized as document templates
+   by a well-known piece of word processing software out of Redmond, WA.
+   Therefore some recommend using the .gv extension instead.  Obstinately
+   ignore that recommendatition...  */
+static const char *const graph_ext = ".dot";
+
+/* Open a file with MODE for dumping our graph to.
+   Return the file pointer.  */
+static FILE *
+open_graph_file (const char *base, const char *mode)
 {
-  /* no_graph */ "",
-  /* vcg */      ".vcg",
-};
+  size_t namelen = strlen (base);
+  size_t extlen = strlen (graph_ext) + 1;
+  char *buf = XALLOCAVEC (char, namelen + extlen);
+  FILE *fp;
 
-/* The flag to indicate if output is inside of a building block.  */
-static int inbb = 0;
+  memcpy (buf, base, namelen);
+  memcpy (buf + namelen, graph_ext, extlen);
 
-static void start_fct (FILE *);
-static void start_bb (FILE *, int);
-static void node_data (FILE *, rtx);
-static void draw_edge (FILE *, int, int, int, int);
-static void end_fct (FILE *);
-static void end_bb (FILE *);
+  fp = fopen (buf, mode);
+  if (fp == NULL)
+    fatal_error ("can%'t open %s: %m", buf);
 
-/* Output text for new basic block.  */
-static void
-start_fct (FILE *fp)
+  return fp;
+}
+
+/* Print the output from print_insn or print_pattern with GraphViz-special
+   characters escaped as necessary.  */
+void
+print_escaped_line (FILE *fp, const char *buf)
 {
-  switch (graph_dump_format)
+  const char *p = buf;
+
+  while (*p)
     {
-    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;
+      switch (*p)
+	{
+	case '\n':
+	  /* Print newlines as a left-aligned newline.  */
+	  fputs ("\\l\\\n", fp);
+	  break;
+
+	case '{':
+	case '}':
+	case '<':
+	case '>':
+	case '|':
+	case ' ':
+	  /* These characters have to be escaped to work with record-shape nodes.  */
+	  fputc ('\\', fp);
+	  /* fall through */
+	default:
+	  fputc (*p, fp);
+	  break;
+	}
+      p++;
     }
+  fputs ("\\l\\\n", fp);
 }
 
+/* Draw a basic block BB belonging to the function with FNDECL_UID
+   as its unique number.  */
 static void
-start_bb (FILE *fp, int bb)
+draw_cfg_node (FILE *fp, int fndecl_uid, basic_block bb)
 {
-#if 0
-  reg_set_iterator rsi;
-#endif
+  rtx insn;
+  bool first = true;
+  const char *shape;
+  const char *fillcolor;
 
-  switch (graph_dump_format)
+  if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK)
     {
-    case vcg:
-      fprintf (fp, "\
-graph: {\ntitle: \"%s.BB%d\"\nfolding: 1\ncolor: lightblue\n\
-label: \"basic block %d",
-	       current_function_name (), bb, bb);
-      inbb = 1; /* Now We are inside of a building block.  */
-      break;
-    case no_graph:
-      break;
+      shape = "Mdiamond";
+      fillcolor = "white";
     }
-
-#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, rsi)
+  else
     {
-      fprintf (fp, " %d", i);
-      if (i < FIRST_PSEUDO_REGISTER)
-	fprintf (fp, " [%s]", reg_names[i]);
+      shape = "record";
+      fillcolor =
+	BB_PARTITION (bb) == BB_HOT_PARTITION ? "lightpink"
+	: BB_PARTITION (bb) == BB_COLD_PARTITION ? "lightblue"
+	: "lightgrey";
     }
-#endif
 
-  switch (graph_dump_format)
-    {
-    case vcg:
-      fputs ("\"\n\n", fp);
-      break;
-    case no_graph:
-      break;
-    }
-}
+  fprintf (fp,
+	   "\tfn_%d_basic_block_%d [shape=%s,style=filled,fillcolor=%s,label=\"",
+	   fndecl_uid, bb->index, shape, fillcolor);
 
-static void
-node_data (FILE *fp, rtx tmp_rtx)
-{
-  if (PREV_INSN (tmp_rtx) == 0)
+  if (bb->index == ENTRY_BLOCK)
+    fputs ("ENTRY", fp);
+  else if (bb->index == EXIT_BLOCK)
+    fputs ("EXIT", fp);
+  else
     {
-      /* This is the first instruction.  Add an edge from the starting
-	 block.  */
-      switch (graph_dump_format)
+      fputc ('{', fp);
+      /* TODO: inter-bb stuff.  */
+      FOR_BB_INSNS (bb, insn)
 	{
-	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;
-	}
-    }
+	  char buf[2048];
 
-  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),
-	       NOTE_P (tmp_rtx) ? "lightgrey"
-	       : NONJUMP_INSN_P (tmp_rtx) ? "green"
-	       : JUMP_P (tmp_rtx) ? "darkgreen"
-	       : CALL_P (tmp_rtx) ? "darkgreen"
-	       : LABEL_P (tmp_rtx) ?  "\
-darkgrey\n  shape: ellipse" : "white",
-	       GET_RTX_NAME (GET_CODE (tmp_rtx)), XINT (tmp_rtx, 0));
-      break;
-    case no_graph:
-      break;
-    }
+	  if (! first)
+	    fputc ('|', fp);
 
-  /* Print the RTL.  */
-  if (NOTE_P (tmp_rtx))
-    {
-      const char *name;
-      name =  GET_NOTE_INSN_NAME (NOTE_KIND (tmp_rtx));
-      fprintf (fp, " %s", name);
-    }
-  else if (INSN_P (tmp_rtx))
-    print_rtl_single (fp, PATTERN (tmp_rtx));
-  else
-    print_rtl_single (fp, tmp_rtx);
+	  print_insn (buf, insn, 1);
+	  print_escaped_line (fp, buf);
+	  if (INSN_P (insn) && REG_NOTES (insn))
+	    for (rtx note = REG_NOTES (insn); note; note = XEXP (note, 1))
+	      {
+		fprintf (fp, "      %s: ",
+			 GET_REG_NOTE_NAME (REG_NOTE_KIND (note)));
+		print_pattern (buf, XEXP (note, 0), 1);
+		print_escaped_line (fp, buf);
+	      }
 
-  switch (graph_dump_format)
-    {
-    case vcg:
-      fputs ("\"\n}\n", fp);
-      break;
-    case no_graph:
-      break;
+	  first = false;
+	}
+      fputc ('}', fp);
     }
-}
 
-static void
-draw_edge (FILE *fp, int from, int to, int bb_edge, int color_class)
-{
-  const char * color;
-  switch (graph_dump_format)
-    {
-    case vcg:
-      color = "";
-      if (color_class == 2)
-	color = "color: red ";
-      else if (bb_edge)
-	color = "color: blue ";
-      else if (color_class == 3)
-	color = "color: green ";
-      fprintf (fp,
-	       "edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s",
-	       current_function_name (), from,
-	       current_function_name (), to, color);
-      if (color_class)
-	fprintf (fp, "class: %d ", color_class);
-      fputs ("}\n", fp);
-      break;
-    case no_graph:
-      break;
-    }
+  fputs ("\"];\n\n", fp);
 }
 
+/* Draw all successor edges of a basic block BB belonging to the function
+   with FNDECL_UID as its unique number.  */
 static void
-end_bb (FILE *fp)
+draw_cfg_node_succ_edges (FILE *fp, int fndecl_uid, basic_block bb)
 {
-  switch (graph_dump_format)
+  edge e;
+  edge_iterator ei;
+  FOR_EACH_EDGE (e, ei, bb->succs)
     {
-    case vcg:
-      /* Check if we are inside of a building block.  */
-      if (inbb != 0)
-        {
-          fputs ("}\n", fp);
-          inbb = 0; /* Now we are outside of a building block.  */
-        }
-      break;
-    case no_graph:
-      break;
-    }
-}
+      const char *style = "\"solid,bold\"";
+      const char *color = "black";
+      int weight = 10;
 
-static void
-end_fct (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 (const char *base, rtx rtx_first)
-{
-  rtx tmp_rtx;
-  size_t namelen = strlen (base);
-  size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
-  char *buf = XALLOCAVEC (char, namelen + extlen);
-  FILE *fp;
-
-  if (!basic_block_info)
-    return;
-
-  memcpy (buf, base, namelen);
-  memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
-
-  fp = fopen (buf, "a");
-  if (fp == NULL)
-    return;
-
-  if (rtx_first == 0)
-    fprintf (fp, "(nil)\n");
-  else
-    {
-      enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
-      int max_uid = get_max_uid ();
-      int *start = XNEWVEC (int, max_uid);
-      int *end = XNEWVEC (int, max_uid);
-      enum bb_state *in_bb_p = XNEWVEC (enum bb_state, max_uid);
-      basic_block bb;
-      int i;
-
-      for (i = 0; i < max_uid; ++i)
+      if (e->flags & EDGE_FAKE)
 	{
-	  start[i] = end[i] = -1;
-	  in_bb_p[i] = NOT_IN_BB;
+	  style = "dotted";
+	  color = "green";
+	  weight = 0;
 	}
-
-      FOR_EACH_BB_REVERSE (bb)
+      else if (e->flags & EDGE_DFS_BACK)
 	{
-	  rtx x;
-	  start[INSN_UID (BB_HEAD (bb))] = bb->index;
-	  end[INSN_UID (BB_END (bb))] = bb->index;
-	  for (x = BB_HEAD (bb); 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 == BB_END (bb))
-		break;
-	    }
+	  style = "\"dotted,bold\"";
+	  color = "blue";
+	  weight = 10;
 	}
-
-      /* 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))
+      else if (e->flags & EDGE_FALLTHRU)
 	{
-	  int edge_printed = 0;
-	  rtx next_insn;
+	  color = "blue";
+	  weight = 100;
+	}
 
-	  if (start[INSN_UID (tmp_rtx)] < 0 && end[INSN_UID (tmp_rtx)] < 0)
-	    {
-	      if (BARRIER_P (tmp_rtx))
-		continue;
-	      if (NOTE_P (tmp_rtx)
-		  && (1 || in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB))
-		continue;
-	    }
+      if (e->flags & EDGE_ABNORMAL)
+	color = "red";
 
-	  if ((i = start[INSN_UID (tmp_rtx)]) >= 0)
-	    {
-	      /* We start a subgraph for each basic block.  */
-	      start_bb (fp, i);
+      fprintf (fp,
+	       "\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
+	       "[style=%s,color=%s,weight=%d];\n",
+	       fndecl_uid, e->src->index,
+	       fndecl_uid, e->dest->index,
+	       style, color, weight);
+    }
+}
 
-	      if (i == 0)
-		draw_edge (fp, 0, INSN_UID (tmp_rtx), 1, 0);
-	    }
+/* Print a graphical representation of the CFG of function FUN.
+   Currently only supports RTL in cfgrtl or cfglayout mode, GIMPLE is TODO.  */
+void
+print_rtl_graph_with_bb (const char *base, tree fndecl)
+{
+  const char *funcname = fndecl_name (fndecl);
+  int fndecl_uid = DECL_UID (fndecl);
+  FILE *fp = open_graph_file (base, "a");
+  int *rpo = XNEWVEC (int, n_basic_blocks);
+  basic_block bb;
+  int i, n;
 
-	  /* Print the data for this node.  */
-	  node_data (fp, tmp_rtx);
-	  next_insn = next_nonnote_insn (tmp_rtx);
+  fprintf (fp,
+	   "subgraph \"%s\" {\n"
+	   "\tcolor=\"black\";\n"
+	   "\tlabel=\"%s\";\n",
+	   funcname, funcname);
 
-	  if ((i = end[INSN_UID (tmp_rtx)]) >= 0)
-	    {
-	      edge e;
-	      edge_iterator ei;
+  /* First print all basic blocks.
+     Visit the blocks in reverse post order to get a good ranking
+     of the nodes.  */
+  n = pre_and_rev_post_order_compute (NULL, rpo, true);
+  for (i = 0; i < n; i++)
+    draw_cfg_node (fp, fndecl_uid, BASIC_BLOCK (rpo[i]));
 
-	      bb = BASIC_BLOCK (i);
+  /* Draw all edges at the end to get subgraphs right for GraphViz,
+     which requires nodes to be defined before edges to cluster
+     nodes properly.
 
-	      /* End of the basic block.  */
-	      end_bb (fp);
+     Draw retreating edges as not constraining, this makes the layout
+     of the graph better.  (??? Calling mark_dfs_back may change the
+     compiler's behavior when dumping, but computing back edges here
+     for ourselves is also not desirable.)  */
+  mark_dfs_back_edges ();
+  FOR_ALL_BB (bb)
+    draw_cfg_node_succ_edges (fp, fndecl_uid, bb);
 
-	      /* Now specify the edges to all the successors of this
-		 basic block.  */
-	      FOR_EACH_EDGE (e, ei, bb->succs)
-		{
-		  if (e->dest != EXIT_BLOCK_PTR)
-		    {
-		      rtx block_head = BB_HEAD (e->dest);
+  fputs ("\t}\n", fp);
 
-		      draw_edge (fp, INSN_UID (tmp_rtx),
-				 INSN_UID (block_head),
-				 next_insn != block_head,
-				 (e->flags & EDGE_ABNORMAL ? 2 : 0));
-
-		      if (block_head == next_insn)
-			edge_printed = 1;
-		    }
-		  else
-		    {
-		      draw_edge (fp, INSN_UID (tmp_rtx), 999999,
-				 next_insn != 0,
-				 (e->flags & EDGE_ABNORMAL ? 2 : 0));
-
-		      if (next_insn == 0)
-			edge_printed = 1;
-		    }
-		}
-	    }
-
-	  if (!edge_printed)
-	    {
-	      /* Don't print edges to barriers.  */
-	      if (next_insn == 0
-		  || !BARRIER_P (next_insn))
-		draw_edge (fp, XINT (tmp_rtx, 0),
-			   next_insn ? INSN_UID (next_insn) : 999999, 0, 0);
-	      else
-		{
-		  /* We draw the remaining edges in class 3.  We have
-		     to skip over the barrier since these nodes are
-		     not printed at all.  */
-		  do
-		    next_insn = NEXT_INSN (next_insn);
-		  while (next_insn
-			 && (NOTE_P (next_insn)
-			     || BARRIER_P (next_insn)));
-
-		  draw_edge (fp, XINT (tmp_rtx, 0),
-			     next_insn ? INSN_UID (next_insn) : 999999, 0, 3);
-		}
-	    }
-	}
-
-      dump_for_graph = 0;
-
-      end_fct (fp);
-
-      /* Clean up.  */
-      free (start);
-      free (end);
-      free (in_bb_p);
-    }
-
   fclose (fp);
 }
 
+/* Start the dump of a graph.  */
+static void
+start_graph_dump (FILE *fp)
+{
+  fputs ("digraph \"\" {\n"
+	 "overlap=false;\n",
+	 fp);
+}
 
-/* Similar as clean_dump_file, but this time for graph output files.  */
+/* End the dump of a graph.  */
+static void
+end_graph_dump (FILE *fp)
+{
+  fputs ("}\n", fp);
+}
 
+/* Similar as clean_dump_file, but this time for graph output files.  */
 void
 clean_graph_dump_file (const char *base)
 {
-  size_t namelen = strlen (base);
-  size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
-  char *buf = XALLOCAVEC (char, namelen + extlen);
-  FILE *fp;
-
-  memcpy (buf, base, namelen);
-  memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
-
-  fp = fopen (buf, "w");
-
-  if (fp == NULL)
-    fatal_error ("can%'t open %s: %m", buf);
-
-  gcc_assert (graph_dump_format == vcg);
-  fputs ("graph: {\nport_sharing: no\n", fp);
-
+  FILE *fp = open_graph_file (base, "w");
+  start_graph_dump (fp);
   fclose (fp);
 }
 
@@ -420,19 +267,7 @@ clean_graph_dump_file (const char *base)
 void
 finish_graph_dump_file (const char *base)
 {
-  size_t namelen = strlen (base);
-  size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
-  char *buf = XALLOCAVEC (char, namelen + extlen);
-  FILE *fp;
-
-  memcpy (buf, base, namelen);
-  memcpy (buf + namelen, graph_ext[graph_dump_format], extlen);
-
-  fp = fopen (buf, "a");
-  if (fp != NULL)
-    {
-      gcc_assert (graph_dump_format == vcg);
-      fputs ("}\n", fp);
-      fclose (fp);
-    }
+  FILE *fp = open_graph_file (base, "a");
+  end_graph_dump (fp);
+  fclose (fp);
 }
Index: graph.h
===================================================================
--- graph.h	(revision 193650)
+++ graph.h	(working copy)
@@ -20,7 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_GRAPH_H
 #define GCC_GRAPH_H
 
-extern void print_rtl_graph_with_bb (const char *, rtx);
+extern void print_rtl_graph_with_bb (const char *, tree);
 extern void clean_graph_dump_file (const char *);
 extern void finish_graph_dump_file (const char *);
 
Index: passes.c
===================================================================
--- passes.c	(revision 193650)
+++ passes.c	(working copy)
@@ -239,19 +239,18 @@ finish_optimization_passes (void)
     {
       dump_start (pass_profile.pass.static_pass_number, NULL);
       print_combine_total_stats ();
-      dump_finish (pass_combine.pass.static_pass_number);
+      dump_finish (pass_profile.pass.static_pass_number);
     }
 
   /* Do whatever is necessary to finish printing the graphs.  */
-  if (graph_dump_format != no_graph)
-    for (i = TDI_end; (dfi = get_dump_file_info (i)) != NULL; ++i)
-      if (dump_initialized_p (i)
-	  && (dfi->pflags & TDF_GRAPH) != 0
-	  && (name = get_dump_file_name (i)) != NULL)
-	{
-	  finish_graph_dump_file (name);
-	  free (name);
-	}
+  for (i = TDI_end; (dfi = get_dump_file_info (i)) != NULL; ++i)
+    if (dump_initialized_p (i)
+	&& (dfi->pflags & TDF_GRAPH) != 0
+	&& (name = get_dump_file_name (i)) != NULL)
+      {
+	finish_graph_dump_file (name);
+	free (name);
+      }
 
   timevar_pop (TV_DUMP);
 }
@@ -1775,18 +1774,16 @@ execute_function_dump (void *data ATTRIBUTE_UNUSED
       if (cfun->curr_properties & PROP_trees)
         dump_function_to_file (current_function_decl, dump_file, dump_flags);
       else
-	{
-	  print_rtl_with_bb (dump_file, get_insns (), dump_flags);
+	print_rtl_with_bb (dump_file, get_insns (), dump_flags);
 
-	  if ((cfun->curr_properties & PROP_cfg)
-	      && graph_dump_format != no_graph
-	      && (dump_flags & TDF_GRAPH))
-	    print_rtl_graph_with_bb (dump_file_name, get_insns ());
-	}
-
       /* Flush the file.  If verification fails, we won't be able to
 	 close the file before aborting.  */
       fflush (dump_file);
+
+      if ((cfun->curr_properties & PROP_cfg)
+	  && (cfun->curr_properties & PROP_rtl)
+	  && (dump_flags & TDF_GRAPH))
+	print_rtl_graph_with_bb (dump_file_name, cfun->decl);
     }
 }
 
@@ -2336,13 +2333,11 @@ execute_one_pass (struct opt_pass *pass)
 
   if (initializing_dump
       && dump_file
-      && graph_dump_format != no_graph
+      && (dump_flags & TDF_GRAPH)
       && cfun
       && (cfun->curr_properties & (PROP_cfg | PROP_rtl))
 	  == (PROP_cfg | PROP_rtl))
     {
-      get_dump_file_info (pass->static_pass_number)->pflags |= TDF_GRAPH;
-      dump_flags |= TDF_GRAPH;
       clean_graph_dump_file (dump_file_name);
     }
 
Index: ddg.c
===================================================================
--- ddg.c	(revision 193650)
+++ ddg.c	(working copy)
@@ -753,7 +753,7 @@ print_ddg (FILE *file, ddg_ptr g)
 }
 
 /* Print the given DDG in VCG format.  */
-void
+DEBUG_FUNCTION void
 vcg_print_ddg (FILE *file, ddg_ptr g)
 {
   int src_cuid;
Index: toplev.c
===================================================================
--- toplev.c	(revision 193650)
+++ toplev.c	(working copy)
@@ -49,7 +49,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "basic-block.h"
 #include "intl.h"
 #include "ggc.h"
-#include "graph.h"
 #include "regs.h"
 #include "timevar.h"
 #include "diagnostic.h"
Index: tree-optimize.c
===================================================================
--- tree-optimize.c	(revision 193650)
+++ tree-optimize.c	(working copy)
@@ -38,7 +38,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "ggc.h"
 #include "cgraph.h"
-#include "graph.h"
 #include "cfgloop.h"
 #include "except.h"
 #include "plugin.h"
Index: testsuite/gcc.dg/20050811-1.c
===================================================================
--- testsuite/gcc.dg/20050811-1.c	(revision 193650)
+++ testsuite/gcc.dg/20050811-1.c	(working copy)
@@ -1,6 +1,6 @@
-/* Test whether -dv -fdump-rtl-all doesn't crash.  */
+/* Test whether -fdump-rtl-all-graph doesn't crash.  */
 /* { dg-do compile } */
-/* { dg-options "-O2 -dv -fdump-rtl-all" } */
+/* { dg-options "-O2 -fdump-rtl-all-graph" } */
 
 int foo (void)
 {
Index: testsuite/gcc.dg/pr37858.c
===================================================================
--- testsuite/gcc.dg/pr37858.c	(revision 193650)
+++ testsuite/gcc.dg/pr37858.c	(working copy)
@@ -1,6 +1,7 @@
 /* PR middle-end/37858 */
+/* ??? With -dv removed, this test is a bit silly.  */
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-ipa-early_local_cleanups -dv" } */
+/* { dg-options "-O2 -fdump-ipa-early_local_cleanups" } */
 
 int
 main (void)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [patch] Rework RTL CFG graph dumping to dump DOT format
  2012-11-23  9:47 [patch] Rework RTL CFG graph dumping to dump DOT format Steven Bosscher
@ 2012-11-26 15:46 ` Richard Biener
  2012-11-26 15:54   ` Steven Bosscher
  2012-12-01 13:24   ` Steven Bosscher
  0 siblings, 2 replies; 7+ messages in thread
From: Richard Biener @ 2012-11-26 15:46 UTC (permalink / raw)
  To: Steven Bosscher; +Cc: GCC Patches, rsandifo

[-- Attachment #1: Type: text/plain, Size: 1492 bytes --]

On Fri, Nov 23, 2012 at 10:46 AM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
> Hello,
>
> The graph.[ch] code to dump the CFG for viewing with VCG is quite
> broken and hasn't been updated to follow the advances in the CFG
> infrastructure.
>
> The attached patch is the first in a series of patches I have planned
> to update the CFG-as-graph dumping code to dump GraphViz DOT input
> instead. The attached archive is an example input/output.
>
> There's still quite a lot of work to be done:
> - use pretty-print in the slim RTL dumping
> - move the escaped-string printing into pretty-print
> - make the basic block content dumping a cfghook
> - make these dumps work for GIMPLE also
>
> For the moment, this is a good starting point.
>
> Obviously there are no changes in code generation due to this patch,
> so IMHO this patch (and the rest of the series) should be safe for
> stage3. Hopefully everyone else agrees :-)
>
> Bootstrapped&tested on powerpc64-unknown-linux-gnu. OK for trunk?

Hmm, you are removing an (appearant) abstraction that I didn't know was
there but remember to have asked for in the thread for dumping a late
callgraph for Ada purposes.  Is the abstraction not working or was it simply
a hassle to keep the VCG path working (I don't thjnk I have ever seen a
VCG consumer ... ;)).

Btw, I of course have my own CFG dumper (producing graphviz input)
in my local tree - attached for reference (I'm simply using it from
gdb sessions).

Richard.

> Ciao!
> Steven

[-- Attachment #2: p --]
[-- Type: application/octet-stream, Size: 2641 bytes --]

Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 193816)
+++ gcc/tree-cfg.c	(working copy)
@@ -2150,6 +2154,87 @@ debug_cfg_stats (void)
   dump_cfg_stats (stderr);
 }
 
+void
+gimple_cfg2dot (const char *fname);
+void
+gimple_cfg2dot (const char *fname)
+{
+  FILE *file = fopen (fname, "w");
+  basic_block bb;
+  pretty_printer buffer;
+
+  pp_construct (&buffer, NULL, 0);
+  pp_needs_newline (&buffer) = false;
+  buffer.buffer->stream = file;
+
+  fprintf (file, "digraph cfg {\n");
+
+  FOR_EACH_BB (bb)
+    {
+      edge_iterator ei;
+      edge e;
+      gimple_stmt_iterator gsi;
+      fprintf (file, "\"BB%d\"", bb->index);
+      fprintf (file, " [shape=box,label=\"BB%d", bb->index);
+      if (current_loops
+	  && bb->loop_father)
+	{
+	  fprintf (file, " loop %d", bb->loop_father->num);
+	  if (bb->loop_father->latch == bb)
+	    fprintf (file, " (latch)");
+	  if (bb->loop_father->header == bb)
+	    fprintf (file, " (header)");
+	}
+      fprintf (file, "\\l");
+      if (!(bb->flags & BB_RTL))
+	{
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  if (!is_gimple_reg (gimple_phi_result (gsi_stmt (gsi))))
+	    continue;
+	  pp_gimple_stmt_1 (&buffer, gsi_stmt (gsi), 0, TDF_SLIM);
+	  pp_write_text_to_stream (&buffer);
+	  fprintf (file, "\\l");
+	}
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  pp_gimple_stmt_1 (&buffer, gsi_stmt (gsi), 0, TDF_SLIM);
+	  pp_write_text_to_stream (&buffer);
+	  fprintf (file, "\\l");
+	}
+	}
+      fprintf (file, "\"]");
+#if 0
+      gsi = gsi_last_bb (bb);
+      if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_COND)
+	{
+	  fprintf (file, " [shape=box,label=\"BB%d\\l", bb->index);
+	  dump_gimple_stmt (&buffer, gsi_stmt (gsi), 0, TDF_SLIM);
+	  pp_write_text_to_stream (&buffer);
+	  fprintf (file, "\"]");
+	}
+#endif
+      fprintf (file, ";\n");
+      FOR_EACH_EDGE (e, ei, bb->succs)
+	{
+	  fprintf (file, "\"BB%d\" -> \"BB%d\"", bb->index, e->dest->index);
+	  if (e->flags & EDGE_EH)
+	    fprintf (file, " [style=dashed,label=\"eh\"]");
+	  if (e->flags & EDGE_FAKE)
+	    fprintf (file, " [style=dotted]");
+	  if (e->flags & EDGE_ABNORMAL)
+	    fprintf (file, " [style=dashed,label=\"ab\"]");
+	  if (e->flags & EDGE_TRUE_VALUE)
+	    fprintf (file, " [color=green,label=\"t\"]");
+	  else if (e->flags & EDGE_FALSE_VALUE)
+	    fprintf (file, " [color=red,label=\"f\"]");
+	  fprintf (file, ";\n");
+	}
+    }
+
+  fprintf (file, "}\n");
+  fclose (file);
+}
 
 /* Dump the flowgraph to a .vcg FILE.  */
 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [patch] Rework RTL CFG graph dumping to dump DOT format
  2012-11-26 15:46 ` Richard Biener
@ 2012-11-26 15:54   ` Steven Bosscher
  2012-11-26 16:13     ` Richard Biener
  2012-12-01 13:24   ` Steven Bosscher
  1 sibling, 1 reply; 7+ messages in thread
From: Steven Bosscher @ 2012-11-26 15:54 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches, rsandifo

On Mon, Nov 26, 2012 at 4:46 PM, Richard Biener wrote:
> On Fri, Nov 23, 2012 at 10:46 AM, Steven Bosscher wrote:
>> Hello,
>>
>> The graph.[ch] code to dump the CFG for viewing with VCG is quite
>> broken and hasn't been updated to follow the advances in the CFG
>> infrastructure.
>>
>> The attached patch is the first in a series of patches I have planned
>> to update the CFG-as-graph dumping code to dump GraphViz DOT input
>> instead. The attached archive is an example input/output.
>>
>> There's still quite a lot of work to be done:
>> - use pretty-print in the slim RTL dumping
>> - move the escaped-string printing into pretty-print
>> - make the basic block content dumping a cfghook
>> - make these dumps work for GIMPLE also
>>
>> For the moment, this is a good starting point.
>>
>> Obviously there are no changes in code generation due to this patch,
>> so IMHO this patch (and the rest of the series) should be safe for
>> stage3. Hopefully everyone else agrees :-)
>>
>> Bootstrapped&tested on powerpc64-unknown-linux-gnu. OK for trunk?
>
> Hmm, you are removing an (appearant) abstraction that I didn't know was
> there but remember to have asked for in the thread for dumping a late
> callgraph for Ada purposes.  Is the abstraction not working or was it simply
> a hassle to keep the VCG path working (I don't thjnk I have ever seen a
> VCG consumer ... ;)).

I'm not sure what abstraction you mean. If you're talking about the
old graph.[ch], there's nothing abstract about it, it only dumps an
RTL CFG and, indeed, that wasn't working properly. The dumps were ugly
if they work at all. Each insn was dumped as a separate node and there
was no option to dump complete translation units to a single file (my
dumper does that just fine, it dumps each CFG as a disjoint subgraph).
(Some examples of what the dumps look like are attached to this
e-mail: http://gcc.gnu.org/ml/gcc-patches/2012-11/msg01977.html)

A generic graph dumping interface would be nice (graph_traits?) but
for the moment I'm just trying to make a debugging tool available.


> Btw, I of course have my own CFG dumper (producing graphviz input)
> in my local tree - attached for reference (I'm simply using it from
> gdb sessions).

I'll integrate this in my work for a follow-up patch. Well, if you'd
OK the one from this thread first, of course ;-)

Ciao!
Steven

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [patch] Rework RTL CFG graph dumping to dump DOT format
  2012-11-26 15:54   ` Steven Bosscher
@ 2012-11-26 16:13     ` Richard Biener
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Biener @ 2012-11-26 16:13 UTC (permalink / raw)
  To: Steven Bosscher; +Cc: GCC Patches, rsandifo

On Mon, Nov 26, 2012 at 4:53 PM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
> On Mon, Nov 26, 2012 at 4:46 PM, Richard Biener wrote:
>> On Fri, Nov 23, 2012 at 10:46 AM, Steven Bosscher wrote:
>>> Hello,
>>>
>>> The graph.[ch] code to dump the CFG for viewing with VCG is quite
>>> broken and hasn't been updated to follow the advances in the CFG
>>> infrastructure.
>>>
>>> The attached patch is the first in a series of patches I have planned
>>> to update the CFG-as-graph dumping code to dump GraphViz DOT input
>>> instead. The attached archive is an example input/output.
>>>
>>> There's still quite a lot of work to be done:
>>> - use pretty-print in the slim RTL dumping
>>> - move the escaped-string printing into pretty-print
>>> - make the basic block content dumping a cfghook
>>> - make these dumps work for GIMPLE also
>>>
>>> For the moment, this is a good starting point.
>>>
>>> Obviously there are no changes in code generation due to this patch,
>>> so IMHO this patch (and the rest of the series) should be safe for
>>> stage3. Hopefully everyone else agrees :-)
>>>
>>> Bootstrapped&tested on powerpc64-unknown-linux-gnu. OK for trunk?
>>
>> Hmm, you are removing an (appearant) abstraction that I didn't know was
>> there but remember to have asked for in the thread for dumping a late
>> callgraph for Ada purposes.  Is the abstraction not working or was it simply
>> a hassle to keep the VCG path working (I don't thjnk I have ever seen a
>> VCG consumer ... ;)).
>
> I'm not sure what abstraction you mean. If you're talking about the
> old graph.[ch], there's nothing abstract about it, it only dumps an
> RTL CFG and, indeed, that wasn't working properly.

Ah, ok - maybe it was my wishful thinking when glancing over the patch
and see

-static void draw_edge (FILE *, int, int, int, int);

;)

> The dumps were ugly
> if they work at all. Each insn was dumped as a separate node and there
> was no option to dump complete translation units to a single file (my
> dumper does that just fine, it dumps each CFG as a disjoint subgraph).
> (Some examples of what the dumps look like are attached to this
> e-mail: http://gcc.gnu.org/ml/gcc-patches/2012-11/msg01977.html)
>
> A generic graph dumping interface would be nice (graph_traits?) but
> for the moment I'm just trying to make a debugging tool available.
>
>
>> Btw, I of course have my own CFG dumper (producing graphviz input)
>> in my local tree - attached for reference (I'm simply using it from
>> gdb sessions).
>
> I'll integrate this in my work for a follow-up patch. Well, if you'd
> OK the one from this thread first, of course ;-)

Ok!

Thanks,
Richard.

> Ciao!
> Steven

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [patch] Rework RTL CFG graph dumping to dump DOT format
  2012-11-26 15:46 ` Richard Biener
  2012-11-26 15:54   ` Steven Bosscher
@ 2012-12-01 13:24   ` Steven Bosscher
  2012-12-01 17:41     ` Steven Bosscher
  1 sibling, 1 reply; 7+ messages in thread
From: Steven Bosscher @ 2012-12-01 13:24 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches, rsandifo

[-- Attachment #1: Type: text/plain, Size: 602 bytes --]

On Mon, Nov 26, 2012 at 4:46 PM, Richard Biener wrote:
> Btw, I of course have my own CFG dumper (producing graphviz input)
> in my local tree - attached for reference (I'm simply using it from
> gdb sessions).

Here's my version of it. I still have to fix some minor fall-out of
not flushing the pretty-printers all over the (inappropriate) place,
but the graph dumps seem to work nicely so far. Perhaps you can try it
out and see if this is to your liking? :-)

Bootstrapped&tested on {powerpc64,x86_64}-unknown-linux-gnu. As I
said: Still fixing some minor tree dump related fall-out.

Ciao!
Steven

[-- Attachment #2: graph_dump_draft.diff --]
[-- Type: application/octet-stream, Size: 12257 bytes --]

	* rtl.h (print_insn_with_notes): Prototype.
	* sched-vis.c (print_insn_with_notes): Export it.

	* gimple-pretty-print.h (gimple_dump_bb_for_graph): Prototype.
	* gimple-pretty-print.c (print_gimple_expr): Flush the buffer.
	(pp_gimple_stmt_1): Don't do it here.
	(gimple_dump_bb_for_graph): New function.
	* tree-pretty-print.c (dump_generic_node): Don't flush the buffer here.

	* graph.h (print_rtl_graph_with_bb): Rename to print_graph_cfg.
	* graph.c: Include gimple.h, dumpfile.h, and gimple-pretty-print.h.
	(draw_cfg_node): Handle GIMPLE basic blocks also.
	(print_rtl_graph_with_bb): Rename to print_graph_cfg.
	* passes.c (finish_optimization_passes): Don't finish graph dumps here.
	(execute_function_dump): Use print_graph_cfg. Enable dumping the CFG
	for GIMPLE also.
	(pass_init_dump_file): Wrap in TV_DUMP.  Set up CFG graph dumps.
	(pass_fini_dump_file): Wrap in TV_DUMP.  Finish graph dumps.
	(execute_one_pass): Don't set up graph dumps here.

Index: rtl.h
===================================================================
--- rtl.h	(revision 193990)
+++ rtl.h	(working copy)
@@ -2606,6 +2606,7 @@ extern void dump_rtl_slim (FILE *, const_rtx, cons
 extern void print_value (pretty_printer *, const_rtx, int);
 extern void print_pattern (pretty_printer *, const_rtx, int);
 extern void print_insn (pretty_printer *, const_rtx, int);
+extern void print_insn_with_notes (pretty_printer *, const_rtx);
 extern const char *str_pattern_slim (const_rtx);
 
 /* In function.c */
Index: sched-vis.c
===================================================================
--- sched-vis.c	(revision 193990)
+++ sched-vis.c	(working copy)
@@ -719,7 +719,7 @@ print_insn (pretty_printer *pp, const_rtx x, int v
 /* Prerry-print a slim dump of X (an insn) to PP, including any register
    note attached to the instruction.  */
 
-static void
+void
 print_insn_with_notes (pretty_printer *pp, const_rtx x)
 {
   pp_string (pp, print_rtx_head);
Index: gimple-pretty-print.h
===================================================================
--- gimple-pretty-print.h	(revision 193989)
+++ gimple-pretty-print.h	(working copy)
@@ -32,5 +32,6 @@ extern void print_gimple_seq (FILE *, gimple_seq,
 extern void print_gimple_stmt (FILE *, gimple, int, int);
 extern void print_gimple_expr (FILE *, gimple, int, int);
 extern void pp_gimple_stmt_1 (pretty_printer *, gimple, int, int);
+extern void gimple_dump_bb_for_graph (pretty_printer *, basic_block);
 
 #endif /* ! GCC_GIMPLE_PRETTY_PRINT_H */
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c	(revision 193989)
+++ gimple-pretty-print.c	(working copy)
@@ -111,6 +111,7 @@ print_gimple_expr (FILE *file, gimple g, int spc,
   flags |= TDF_RHS_ONLY;
   maybe_init_pretty_print (file);
   pp_gimple_stmt_1 (&buffer, g, spc, flags);
+  pp_flush (&buffer);
 }
 
 
@@ -2048,12 +2049,6 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple g
     default:
       GIMPLE_NIY;
     }
-
-  /* If we're building a diagnostic, the formatted text will be
-     written into BUFFER's stream by the caller; otherwise, write it
-     now.  */
-  if (!(flags & TDF_DIAGNOSTIC))
-    pp_write_text_to_stream (buffer);
 }
 
 
@@ -2271,3 +2266,45 @@ gimple_dump_bb (FILE *file, basic_block bb, int in
     }
   dump_gimple_bb_footer (file, bb, indent, flags);
 }
+
+/* Dumps basic block BB to pretty-printer PP with default dump flags and
+   no indentation, for use as a label of a DOT graph record-node.
+   ??? Should just use gimple_dump_bb_buff here, except that value profiling
+   histogram dumping doesn't know about pretty-printers.  */
+
+void
+gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
+{
+  gimple_stmt_iterator gsi;
+
+  pp_printf (pp, "<bb %d>:\n", bb->index);
+  pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
+
+  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple phi = gsi_stmt (gsi);
+      if (!virtual_operand_p (gimple_phi_result (phi))
+	  || (dump_flags & TDF_VOPS))
+	{
+	  pp_character (pp, '|');
+	  pp_write_text_to_stream (pp);
+	  pp_string (pp, "# ");
+	  pp_gimple_stmt_1 (pp, phi, 0, dump_flags);
+	  pp_newline (pp);
+	  pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
+	}
+    }
+
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple stmt = gsi_stmt (gsi);
+      pp_character (pp, '|');
+      pp_write_text_to_stream (pp);
+      pp_gimple_stmt_1 (pp, stmt, 0, dump_flags);
+      pp_newline (pp);
+      pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
+    }
+  dump_implicit_edges (pp, bb, 0, dump_flags);
+  pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
+}
+
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 193989)
+++ tree-pretty-print.c	(working copy)
@@ -2410,11 +2410,6 @@ dump_generic_node (pretty_printer *buffer, tree no
   if (is_stmt && is_expr)
     pp_semicolon (buffer);
 
-  /* If we're building a diagnostic, the formatted text will be written
-     into BUFFER's stream by the caller; otherwise, write it now.  */
-  if (!(flags & TDF_DIAGNOSTIC))
-    pp_write_text_to_stream (buffer);
-
   return spc;
 }
 
Index: graph.h
===================================================================
--- graph.h	(revision 193989)
+++ graph.h	(working copy)
@@ -20,7 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_GRAPH_H
 #define GCC_GRAPH_H
 
-extern void print_rtl_graph_with_bb (const char *, tree);
+extern void print_graph_cfg (const char *, tree);
 extern void clean_graph_dump_file (const char *);
 extern void finish_graph_dump_file (const char *);
 
Index: graph.c
===================================================================
--- graph.c	(revision 193990)
+++ graph.c	(working copy)
@@ -28,8 +28,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "basic-block.h"
 #include "rtl.h"
 #include "tree.h"
+#include "gimple.h"
 #include "graph.h"
+#include "dumpfile.h"
 #include "pretty-print.h"
+#include "gimple-pretty-print.h"
 
 /* DOT files with the .dot extension are recognized as document templates
    by a well-known piece of word processing software out of Redmond, WA.
@@ -82,8 +85,6 @@ init_graph_slim_pretty_print (FILE *fp)
 static void
 draw_cfg_node (pretty_printer *pp, int fndecl_uid, basic_block bb)
 {
-  rtx insn;
-  bool first = true;
   const char *shape;
   const char *fillcolor;
 
@@ -115,27 +116,26 @@ draw_cfg_node (pretty_printer *pp, int fndecl_uid,
       pp_character (pp, '{');
       pp_write_text_to_stream (pp);
 
-      /* TODO: inter-bb stuff.  */
-      FOR_BB_INSNS (bb, insn)
+      /* This would be easier if there'd be an IR independent iterator...  */
+      if (current_ir_type () == IR_GIMPLE)
+        gimple_dump_bb_for_graph (pp, bb);
+      else
 	{
-	  if (! first)
+	  rtx insn;
+	  bool first = true;
+
+	  /* TODO: inter-bb stuff.  */
+	  FOR_BB_INSNS (bb, insn)
 	    {
-	      pp_character (pp, '|');
-	      pp_write_text_to_stream (pp);
+	      if (! first)
+		{
+		  pp_character (pp, '|');
+		  pp_write_text_to_stream (pp);
+		}
+	      first = false;
+	      print_insn_with_notes (pp, insn);
+	      pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 	    }
-	  first = false;
-
-	  print_insn (pp, insn, 1);
-	  pp_newline (pp);
-	  if (INSN_P (insn) && REG_NOTES (insn))
-	    for (rtx note = REG_NOTES (insn); note; note = XEXP (note, 1))
-	      {
-		pp_printf (pp, "      %s: ",
-			   GET_REG_NOTE_NAME (REG_NOTE_KIND (note)));
-		print_pattern (pp, XEXP (note, 0), 1);
-		pp_newline (pp);
-	      }
-	  pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 	}
       pp_character (pp, '}');
     }
@@ -189,10 +189,10 @@ draw_cfg_node_succ_edges (pretty_printer *pp, int
   pp_flush (pp);
 }
 
-/* Print a graphical representation of the CFG of function FUN.
-   Currently only supports RTL in cfgrtl or cfglayout mode, GIMPLE is TODO.  */
+/* Print a graphical representation of the CFG of function FUN.  */
+
 void
-print_rtl_graph_with_bb (const char *base, tree fndecl)
+print_graph_cfg (const char *base, tree fndecl)
 {
   const char *funcname = fndecl_name (fndecl);
   int fndecl_uid = DECL_UID (fndecl);
Index: passes.c
===================================================================
--- passes.c	(revision 193989)
+++ passes.c	(working copy)
@@ -223,10 +223,6 @@ rest_of_type_compilation (tree type, int toplev)
 void
 finish_optimization_passes (void)
 {
-  int i;
-  struct dump_file_info *dfi;
-  char *name;
-
   timevar_push (TV_DUMP);
   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
     {
@@ -234,24 +230,12 @@ finish_optimization_passes (void)
       end_branch_prob ();
       dump_finish (pass_profile.pass.static_pass_number);
     }
-
   if (optimize > 0)
     {
       dump_start (pass_profile.pass.static_pass_number, NULL);
       print_combine_total_stats ();
       dump_finish (pass_profile.pass.static_pass_number);
     }
-
-  /* Do whatever is necessary to finish printing the graphs.  */
-  for (i = TDI_end; (dfi = get_dump_file_info (i)) != NULL; ++i)
-    if (dump_initialized_p (i)
-	&& (dfi->pflags & TDF_GRAPH) != 0
-	&& (name = get_dump_file_name (i)) != NULL)
-      {
-	finish_graph_dump_file (name);
-	free (name);
-      }
-
   timevar_pop (TV_DUMP);
 }
 
@@ -1785,9 +1769,8 @@ execute_function_dump (void *data ATTRIBUTE_UNUSED
       fflush (dump_file);
 
       if ((cfun->curr_properties & PROP_cfg)
-	  && (cfun->curr_properties & PROP_rtl)
 	  && (dump_flags & TDF_GRAPH))
-	print_rtl_graph_with_bb (dump_file_name, cfun->decl);
+	print_graph_cfg (dump_file_name, cfun->decl);
     }
 }
 
@@ -2069,11 +2052,16 @@ pass_init_dump_file (struct opt_pass *pass)
   /* If a dump file name is present, open it if enabled.  */
   if (pass->static_pass_number != -1)
     {
+      timevar_push (TV_DUMP);
       bool initializing_dump = !dump_initialized_p (pass->static_pass_number);
       dump_file_name = get_dump_file_name (pass->static_pass_number);
       dump_start (pass->static_pass_number, &dump_flags);
       if (dump_file && current_function_decl)
         dump_function_header (dump_file, current_function_decl, dump_flags);
+      if (dump_file && (dump_flags & TDF_GRAPH)
+	  && cfun && (cfun->curr_properties & PROP_cfg))
+	clean_graph_dump_file (dump_file_name);
+      timevar_pop (TV_DUMP);
       return initializing_dump;
     }
   else
@@ -2086,14 +2074,21 @@ pass_init_dump_file (struct opt_pass *pass)
 void
 pass_fini_dump_file (struct opt_pass *pass)
 {
+  timevar_push (TV_DUMP);
+
   /* Flush and close dump file.  */
   if (dump_file_name)
     {
+      gcc_assert (dump_file);
+      if (dump_flags & TDF_GRAPH
+	  && cfun && (cfun->curr_properties & PROP_cfg))
+	finish_graph_dump_file (dump_file_name);
       free (CONST_CAST (char *, dump_file_name));
       dump_file_name = NULL;
     }
 
   dump_finish (pass->static_pass_number);
+  timevar_pop (TV_DUMP);
 }
 
 /* After executing the pass, apply expected changes to the function
@@ -2250,7 +2245,6 @@ override_gate_status (struct opt_pass *pass, tree
 bool
 execute_one_pass (struct opt_pass *pass)
 {
-  bool initializing_dump;
   unsigned int todo_after = 0;
 
   bool gate_status;
@@ -2308,7 +2302,7 @@ execute_one_pass (struct opt_pass *pass)
      This is a hack until the new folder is ready.  */
   in_gimple_form = (cfun && (cfun->curr_properties & PROP_trees)) != 0;
 
-  initializing_dump = pass_init_dump_file (pass);
+  pass_init_dump_file (pass);
 
   /* Run pre-pass verification.  */
   execute_todo (pass->todo_flags_start);
@@ -2335,16 +2329,6 @@ execute_one_pass (struct opt_pass *pass)
 
   do_per_function (update_properties_after_pass, pass);
 
-  if (initializing_dump
-      && dump_file
-      && (dump_flags & TDF_GRAPH)
-      && cfun
-      && (cfun->curr_properties & (PROP_cfg | PROP_rtl))
-	  == (PROP_cfg | PROP_rtl))
-    {
-      clean_graph_dump_file (dump_file_name);
-    }
-
   if (profile_report && cfun && (cfun->curr_properties & PROP_cfg))
     check_profile_consistency (pass->static_pass_number, 0, true);
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [patch] Rework RTL CFG graph dumping to dump DOT format
  2012-12-01 13:24   ` Steven Bosscher
@ 2012-12-01 17:41     ` Steven Bosscher
  2012-12-03 11:05       ` Richard Biener
  0 siblings, 1 reply; 7+ messages in thread
From: Steven Bosscher @ 2012-12-01 17:41 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches, rsandifo

On Sat, Dec 1, 2012 at 2:23 PM, Steven Bosscher wrote:
> On Mon, Nov 26, 2012 at 4:46 PM, Richard Biener wrote:
>> Btw, I of course have my own CFG dumper (producing graphviz input)
>> in my local tree - attached for reference (I'm simply using it from
>> gdb sessions).
>
> Here's my version of it. I still have to fix some minor fall-out of
> not flushing the pretty-printers all over the (inappropriate) place,
> but the graph dumps seem to work nicely so far. Perhaps you can try it
> out and see if this is to your liking? :-)
>
> Bootstrapped&tested on {powerpc64,x86_64}-unknown-linux-gnu. As I
> said: Still fixing some minor tree dump related fall-out.

I only need this fix on top of the patch:

diff -u tree-pretty-print.c tree-pretty-print.c
--- tree-pretty-print.c (working copy)
+++ tree-pretty-print.c (working copy)
@@ -161,6 +161,7 @@
 {
   maybe_init_pretty_print (file);
   dump_generic_node (&buffer, t, 0, flags, false);
+  pp_flush (&buffer);
 }

 /* Dump the name of a _DECL node and its DECL_UID if TDF_UID is set


Bootstrapped&tested on powerpc64-unknown-linux-gnu. OK for trunk?

Ciao!
Steven

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [patch] Rework RTL CFG graph dumping to dump DOT format
  2012-12-01 17:41     ` Steven Bosscher
@ 2012-12-03 11:05       ` Richard Biener
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Biener @ 2012-12-03 11:05 UTC (permalink / raw)
  To: Steven Bosscher; +Cc: GCC Patches, rsandifo

On Sat, Dec 1, 2012 at 6:40 PM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
> On Sat, Dec 1, 2012 at 2:23 PM, Steven Bosscher wrote:
>> On Mon, Nov 26, 2012 at 4:46 PM, Richard Biener wrote:
>>> Btw, I of course have my own CFG dumper (producing graphviz input)
>>> in my local tree - attached for reference (I'm simply using it from
>>> gdb sessions).
>>
>> Here's my version of it. I still have to fix some minor fall-out of
>> not flushing the pretty-printers all over the (inappropriate) place,
>> but the graph dumps seem to work nicely so far. Perhaps you can try it
>> out and see if this is to your liking? :-)
>>
>> Bootstrapped&tested on {powerpc64,x86_64}-unknown-linux-gnu. As I
>> said: Still fixing some minor tree dump related fall-out.
>
> I only need this fix on top of the patch:
>
> diff -u tree-pretty-print.c tree-pretty-print.c
> --- tree-pretty-print.c (working copy)
> +++ tree-pretty-print.c (working copy)
> @@ -161,6 +161,7 @@
>  {
>    maybe_init_pretty_print (file);
>    dump_generic_node (&buffer, t, 0, flags, false);
> +  pp_flush (&buffer);
>  }
>
>  /* Dump the name of a _DECL node and its DECL_UID if TDF_UID is set
>
>
> Bootstrapped&tested on powerpc64-unknown-linux-gnu. OK for trunk?

Nice.

Ok!

Thanks,
Richard.

> Ciao!
> Steven

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-12-03 11:05 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-23  9:47 [patch] Rework RTL CFG graph dumping to dump DOT format Steven Bosscher
2012-11-26 15:46 ` Richard Biener
2012-11-26 15:54   ` Steven Bosscher
2012-11-26 16:13     ` Richard Biener
2012-12-01 13:24   ` Steven Bosscher
2012-12-01 17:41     ` Steven Bosscher
2012-12-03 11:05       ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).