Author: ycwu
Date: 2011-08-09 04:24:33 -0400 (Tue, 09 Aug 2011)
New Revision: 3712

Modified:
   trunk/osprey/be/cg/bb.h
   trunk/osprey/be/cg/bbutil.cxx
   trunk/osprey/be/cg/cg.cxx
   trunk/osprey/common/com/config.cxx
   trunk/osprey/common/util/tracing.c
   trunk/osprey/common/util/tracing.h
Log:
adds support to print VCG graphs for procedure CFGs, at
various points in CG.

Specifically, the 'V' character can be used (to create VCG graphs)
wherever the 'r' character is used to print the CG IR.
Examples:
-Wb,-tVa - create a VCG graph, in CG, for all phases where we would
          dump the IR
-Wb,-tVSCH create a VCG graph just for the scheduling phase.
Currently, these options only support VCG generation in CG; however,
they could be extended to support VCG generation in phases that come
before CG.
VCG graphs are named as follows:
<procedure_name>.<phase_name>.vcg
So for a procedure 'proc', -Wb,-tVSCH will create a file called:
proc.SCH.vcg.  This way, the -Wb,-tVa option can create multiple VCG
files - all with unique names.  "phase_names" are obtained from the
"Phases" table in tracing.c

Some notes on implementation:
The implementation uses the existing functionality to print BBs, OPs,
... The difference is that for VCG graphs, we need the BBs, OPs, to be
printed to a string rather than to a file.  The lowest-level helper
functions (e.g. Print_OP_No_SrcLine) call fprintf a large number of
times.  Rather, than overhauling this code, to print to either a
string or a file, a simpler approach was taken:
- print BBs to a temporary file
- Read the file into a string.
This made the implementation much simpler, *and* it was much less
intrusive to existing code.  In addition, modifying the existing code
would have involved either:
- testing on multiple platforms (which were not available to the developer)
- only providing support for certain platforms (which would make the
existing code even more complex).
Printing to a file and reading back to a string obviously takes more
time than writing directly to a string; however, given that this is an
internal option only, a slight increase in compile time should be
acceptable.
-------------------------
Following is an example to use VCG

$ cat vcg.c
extern void foo(int x);
extern void bar(int x);
extern int x;

void
sub (int z)
{
 if (z == 42) {
   foo(x);
 }
 else {
   bar(x);
 }
}

$ opencc -O -c -Wb,-tVa vcg.c
$ ls *.vcg
sub.EBO.vcg  sub.EXP.vcg  sub.GCM.vcg  sub.LOP.vcg  sub.SCH.vcg
sub.EMT.vcg  sub.FLW.vcg  sub.GLR.vcg  sub.LRA.vcg


Modified: trunk/osprey/be/cg/bb.h
===================================================================
--- trunk/osprey/be/cg/bb.h     2011-08-08 07:47:30 UTC (rev 3711)
+++ trunk/osprey/be/cg/bb.h     2011-08-09 08:24:33 UTC (rev 3712)
@@ -1252,6 +1252,10 @@
 extern void BB_Transfer_Callinfo(BB* from, BB* to);
 extern void BB_Transfer_Asminfo (BB *from, BB *to);
 
+/* Print just the Procedure name from the BB text */
+#pragma mips_frequency_hint NEVER Get_Procedure_Name
+extern char *Get_Procedure_Name ( void );
+
 /* Print the given BB or BBLIST: */
 extern void Print_BB_Header ( BB *bp,
                              BOOL flow_info_only, BOOL print_tn_info );

Modified: trunk/osprey/be/cg/bbutil.cxx
===================================================================
--- trunk/osprey/be/cg/bbutil.cxx       2011-08-08 07:47:30 UTC (rev 3711)
+++ trunk/osprey/be/cg/bbutil.cxx       2011-08-09 08:24:33 UTC (rev 3712)
@@ -101,6 +101,10 @@
 #include "lra.h"
 #include "bb_set.h"       // BB_SET_* routines 
 #include "DaVinci.h"
+#include "vcg.h"
+#include <sstream>
+#include <fstream>
+#include <cstdlib>
 #include "cg.h"
 #ifdef TARG_IA64
 #include "ipfec_options.h"
@@ -1227,14 +1231,39 @@
 
 /* ================================================================= */
 
+/* ====================================================================
+ *
+ * Get_Procedure_Name
+ *
+ *   Helper rotuines to get the procedure name - separate from the rest
+ *   of the BB text.
+ *
+ * ====================================================================
+ */
+char *
+Get_Procedure_Name ( BB *bp )
+{
+  ANNOTATION *ant = ANNOT_Get (BB_annotations(bp), ANNOT_ENTRYINFO);
+  ENTRYINFO *ent = ANNOT_entryinfo (ant);
+  return ST_name(ENTRYINFO_name(ent));
+}
+
+char *
+Get_Procedure_Name ( void )
+{
+  for (BB* bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
+    if ( BB_entry(bb) ) {
+      return Get_Procedure_Name(bb);
+    }
+  }
+  return NULL;
+}
+
 void Print_BB ( BB *bp )
 {
-#if defined(VENDOR_OSP)
   BBLIST *bl;
   if ( BB_entry(bp) ) {
-    ANNOTATION *ant = ANNOT_Get (BB_annotations(bp), ANNOT_ENTRYINFO);
-    ENTRYINFO *ent = ANNOT_entryinfo (ant);
-    fprintf ( TFile, "\n\t.proc  %s#\n", ST_name(ENTRYINFO_name(ent)) );
+    fprintf ( TFile, "\n\t.proc  %s#\n", Get_Procedure_Name(bp) );
   }
   fprintf ( TFile, "%s", SBar);
   fprintf ( TFile, "// Block: %d", BB_id(bp) );
@@ -1248,9 +1277,6 @@
   }
   fprintf ( TFile, "\n" );
   fprintf ( TFile, "%s", SBar );
-#else  
-  fprintf ( TFile, "%sBB:%d \n%s", SBar, BB_id(bp), SBar );
-#endif
   Print_BB_Header ( bp, FALSE, TRUE );
   Print_BB_Pragmas ( bp );
   fprintf ( TFile, "\n" );
@@ -3448,4 +3474,159 @@
   }
   MEM_POOL_Pop(&MEM_local_pool);
 }
- 
+
+/*========================================================================
+ *
+ * VCG support for CG
+ *
+ *========================================================================
+ */
+
+/*========================================================================
+ *
+ *  Get_BB_Labels
+ *
+ *    Excerpt labels for the BB and append them to the stringstream.
+ *
+ *========================================================================
+ */
+void
+Get_BB_Labels(BB* bb, std::stringstream &ss)
+{
+  if (BB_has_label(bb)) {
+    ANNOTATION *ant;
+    for (ant = ANNOT_First(BB_annotations(bb), ANNOT_LABEL);
+        ant != NULL;
+        ant = ANNOT_Next(ant, ANNOT_LABEL)) {
+      LABEL_IDX label = ANNOT_label(ant);
+      ss << LABEL_name(label);
+    }
+    ss << "\n";
+  }
+}
+
+/*========================================================================
+ *
+ *  get_vcg_node
+ *
+ *    Create a VCG node corresponding to a BB.  This routine reuses the
+ *    support to print a BB.  Basically we:
+ *    - save off TFile
+ *    - open a temp file
+ *    - point TFile to the temp file
+ *    - call the appropriate "print" command
+ *    - restore TFile
+ *    - close the temp file
+ *    - read the temp file into a string
+ *    - use that string as the VCG node info
+ *    While this process is a bit convoluted:
+ *    - we reuse the existing infrastructure to print BBs
+ *    - VCG dumps look like regular ASCII dumps
+ *    - we aovid duplicating code
+ *    Unfortunately, the existing BB print routines were not written in a
+ *    more modular way - i.e. the print statments are in the lowest level
+ *    routines.  This was the best way to reuse the code without overhauling
+ *    it.  While opening/clsong files can be innefficient, at the worst, it
+ *    only imapcts the performance of an internal tracing option.
+ *
+ *========================================================================
+ */
+VCGNode*
+get_vcg_node(MEM_POOL* mpool, VCGGraph& vcg, BB* bb)
+{
+  std::stringstream title_ss;
+  title_ss << "BB:";
+  title_ss << (INT32) BB_id(bb);
+  char* title = (char *) MEM_POOL_Alloc(mpool, title_ss.str().size()+1);
+  strcpy(title, title_ss.str().c_str());
+  VCGNode* bb_node =CXX_NEW(VCGNode(title, title), mpool);
+
+  FILE *save_f, *temp_f;
+  char ch;
+
+  save_f = TFile;
+  temp_f = fopen("/tmp/vcg", "w");
+  Set_Trace_File_internal(temp_f);
+  if (BB_first_op(bb)) Print_OPs (BB_first_op(bb));
+  Set_Trace_File_internal(save_f);
+  fclose(temp_f);
+  std::ifstream info1_from ("/tmp/vcg");
+  std::stringstream info1_to;
+  Get_BB_Labels(bb, info1_to);
+  while (info1_from.get(ch)) {
+    if (ch != '"') {
+      info1_to.put(ch);
+    }
+  }
+  char* info1_info = (char *) MEM_POOL_Alloc(mpool, info1_to.str().size()+1);
+  strcpy(info1_info, info1_to.str().c_str());
+  bb_node->info(1,info1_info);
+
+  save_f = TFile;
+  temp_f = fopen("/tmp/vcg", "w");
+  Set_Trace_File_internal(temp_f);
+  if (BB_first_op(bb)) Print_OPs_No_SrcLines (BB_first_op(bb));
+  Set_Trace_File_internal(save_f);
+  fclose(temp_f);
+  std::ifstream info2_from ("/tmp/vcg");
+  std::stringstream info2_to;
+  Get_BB_Labels(bb, info2_to);
+  while (info2_from.get(ch)) {
+    if (ch != '"') {
+      // Skip '"', since this deliniates the VCG string.
+      info2_to.put(ch);
+    }
+  }
+  char* info2_info = (char *) MEM_POOL_Alloc(mpool, info2_to.str().size()+1);
+  strcpy(info2_info, info2_to.str().c_str());
+  bb_node->info(2,info2_info);
+  system("rm -f /tmp/vcg");
+
+  vcg.addNode(*bb_node);
+  return bb_node;
+}
+
+/*========================================================================
+ *
+ *  draw_vcg_flow_graph
+ *
+ *    Create a VCG graph of the CG VCG
+ *
+ *========================================================================
+ */
+void
+draw_vcg_flow_graph(const char* fname)
+{
+  MEM_POOL vcg_pool;
+  MEM_POOL_Initialize(&vcg_pool, "CFG VCG pool", FALSE);
+  VCGGraph vcg("CFG VCG dump");
+  int max_id = 0;
+  for (BB* bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
+    if (BB_id(bb) > max_id) max_id = BB_id(bb);
+  }
+  VCGNode** vcg_nodes =
+    (VCGNode **) MEM_POOL_Alloc(&vcg_pool, sizeof(VCGNode*) * (max_id + 1));
+
+  for (BB* bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
+    VCGNode* vcg_node = get_vcg_node(&vcg_pool, vcg, bb);
+    vcg_nodes[BB_id(bb)] = vcg_node;
+  }
+  for (BB* bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
+    BBLIST *bl;
+    BB *succ;
+    FOR_ALL_BB_SUCCS(bb,bl) {
+      succ = BBLIST_item(bl);
+      VCGEdge* edge =
+       CXX_NEW(VCGEdge(vcg_nodes[BB_id(bb)]->title(),
+                       vcg_nodes[BB_id(succ)]->title()),
+               &vcg_pool);
+      edge->lineStyle(Continuous);
+      vcg.addEdge(*edge);
+    }
+  }
+  
+  vcg.infoName(1, "Insts with source");
+  vcg.infoName(2, "Insts without source");
+  vcg.emit(fname);
+  MEM_POOL_Delete(&vcg_pool);
+}

Modified: trunk/osprey/be/cg/cg.cxx
===================================================================
--- trunk/osprey/be/cg/cg.cxx   2011-08-08 07:47:30 UTC (rev 3711)
+++ trunk/osprey/be/cg/cg.cxx   2011-08-09 08:24:33 UTC (rev 3712)
@@ -114,6 +114,7 @@
 #include "hb.h"
 #include "pqs_cg.h"
 #include "tag.h"
+#include <sstream>
 #ifdef TARG_IA64
 #include "ipfec.h"
 #include "ipfec_defs.h"
@@ -227,6 +228,8 @@
 REGISTER_SET caller_saved_regs_used[ISA_REGISTER_CLASS_MAX+1];
 #endif
 
+extern void draw_vcg_flow_graph(const char* fname);
+
 /* Stuff that needs to be done at the start of each PU in cg. */
 void
 CG_PU_Initialize (WN *wn_pu)
@@ -2077,6 +2080,33 @@
 #endif         
   }
 }
+  
+static void
+Trace_VCG (
+  INT phase,            /* Phase after which we're printing */
+  const char *pname )   /* Print name for phase */
+{
+  if ( Get_Trace ( TKIND_VCG, phase ) ) {
+    std::stringstream vcg_title_ss;
+    char *proc_name = Get_Procedure_Name();
+    if (proc_name) 
+      vcg_title_ss << proc_name << ".";
+    else
+      vcg_title_ss << "noname" << "."; 
+    char *phase_id = Get_Trace_Phase_Id(phase);
+    if (phase_id)
+      vcg_title_ss << phase_id << ".vcg";
+    else
+      vcg_title_ss << phase << ".vcg";
+    MEM_POOL temp_pool;
+    MEM_POOL_Initialize(&temp_pool, "temp pool", FALSE);
+    char* vcg_title =
+      (char *) MEM_POOL_Alloc(&temp_pool, vcg_title_ss.str().size()+1);
+    strcpy(vcg_title, vcg_title_ss.str().c_str());
+    draw_vcg_flow_graph(vcg_title);
+    MEM_POOL_Delete(&temp_pool);
+  }
+}
 
 static void
 Trace_TN (
@@ -2138,6 +2168,10 @@
      */
     Trace_IR ( pass, s, bb );
 
+    /* Check to see if we should create a VCG of the CFG.
+     */
+    Trace_VCG ( pass, s );
+    
     /* Check to see if we should give a memory allocation trace.
      */
     Trace_Memory_Allocation ( pass, s );

Modified: trunk/osprey/common/com/config.cxx
===================================================================
--- trunk/osprey/common/com/config.cxx  2011-08-08 07:47:30 UTC (rev 3711)
+++ trunk/osprey/common/com/config.cxx  2011-08-09 08:24:33 UTC (rev 3712)
@@ -2214,6 +2214,17 @@
        break;
 #endif
 
+    case 'V':
+       if (strcmp(cp, "a") == 0) {
+         Set_All_Trace( TKIND_VCG );
+         cp++;
+       }
+       else {
+         Set_Trace (TKIND_VCG,
+                    Get_Trace_Phase_Number ( &cp, option ) );
+       }
+       break;
+
     case 0:   
        ErrMsg ( EC_Trace_Flag, '?', option );
        return FALSE;

Modified: trunk/osprey/common/util/tracing.c
===================================================================
--- trunk/osprey/common/util/tracing.c  2011-08-08 07:47:30 UTC (rev 3711)
+++ trunk/osprey/common/util/tracing.c  2011-08-09 08:24:33 UTC (rev 3712)
@@ -106,6 +106,7 @@
 static UINT TI_Mask;                   /* Info mask */
 static UINT TD_Mask;                   /* Debug option mask */
 static UINT TI_Phase[TP_COUNT];                /* IR trace flags */
+static UINT TV_Phase[TP_COUNT];                /* VCG trace flags */
 static UINT TS_Phase[TP_COUNT];                /* SYMTAB trace flags */
 static UINT TN_Phase[TP_COUNT];                /* TN trace flags */
 static UINT TA_Phase[TP_COUNT];                /* Memory Allocation Trace */
@@ -156,7 +157,7 @@
  * not be used for the same phase, except that the listing routine
  * will then print them all...
  */
-static PDESC Phases[] = {
+PDESC Phases[] = {
   /* Miscellaneous "phases": */
   { TP_PTRACE1,                "PT1",  "Performance #1" },
   { TP_PTRACE2,                "PT2",  "Performance #2" },
@@ -230,6 +231,30 @@
 
 /* ====================================================================
  *
+ * Get_Trace_Phase_Id
+ *
+ * Given a phase number, return the 3-character phase id (or NULL, if
+ * it does not exist).
+ *
+ * ====================================================================
+ */
+
+char *
+Get_Trace_Phase_Id(INT32 number)
+{
+  PDESC *phase = Phases;
+  
+  while ( PD_num(phase) != TP_COUNT ) {
+    if ( PD_num(phase) == number ) {
+      return PD_id(phase);
+    }
+    ++phase;
+  }
+  return NULL;
+}
+
+/* ====================================================================
+ *
  * Get_Trace_Phase_Number
  *
  * Extract the phase number from a trace option.  It is either numeric,
@@ -300,6 +325,7 @@
  *  TKIND_INFO         flag mask       Enable masked traces
  *  TKIND_DEBUG                flag mask       Enable masked options
  *  TKIND_IR           phase number    Enable IR trace for phase
+ *  TKIND_VCG          phase number    Enable VCG dump for phase
  *  TKIND_SYMTAB       phase number    Enable SYMTAB trace for phase
  *  TKIND_TN           phase number    Enable TN trace for phase
  *  TKIND_BB           BB number       Restrict tracing to BB
@@ -343,6 +369,15 @@
       }
       return;
 
+    /* VCG phase: */
+    case TKIND_VCG:
+      if ( arg != Check_Range (arg, TP_MIN, TP_LAST, 0) ) {
+       ErrMsg ( EC_Trace_Phase, arg, TP_MIN, TP_LAST );
+      } else {
+       TV_Phase[arg] = TRUE;
+      }
+      return;
+
     /* SYMTAB phase: */
     case TKIND_SYMTAB:
       if ( arg != Check_Range (arg, TP_MIN, TP_LAST, 0) ) {
@@ -562,6 +597,10 @@
     case TKIND_IR:
       result = TI_Phase[arg];
       break;
+    /* VCG phase: */
+    case TKIND_VCG:
+      result = TV_Phase[arg];
+      break;
     /* SYMTAB phase: */
     case TKIND_SYMTAB:
       result = TS_Phase[arg];

Modified: trunk/osprey/common/util/tracing.h
===================================================================
--- trunk/osprey/common/util/tracing.h  2011-08-08 07:47:30 UTC (rev 3711)
+++ trunk/osprey/common/util/tracing.h  2011-08-09 08:24:33 UTC (rev 3712)
@@ -151,7 +151,8 @@
 #define TKIND_XPHASE   -7      /* Specify final execution phase */
 #define TKIND_CTRL     -8      /* Specify a control option */
 #define TKIND_ALLOC    -9      /* Trace memory allocation */
-#define TKIND_MIN      -10     /* Smallest valid function number */
+#define TKIND_VCG      -10     /* Trace VCG for the given pass */
+#define TKIND_MIN      -11     /* Smallest valid function number */
 
 /* Several predefined masks for TKIND_INFO cases: */
 #define TINFO_TIME     1       /* Timing/resource information */
@@ -260,6 +261,9 @@
  */
 #define TP_LAST                76      /* Largest valid phase number */
 #define TP_COUNT       77      /* Number of valid phase numbers */
+
+/* Retrieve 3-character phase id, given a phase number */
+extern char *Get_Trace_Phase_Id(INT32 number);
        
 /* Extract the phase number from a trace option: */
 extern INT32 Get_Trace_Phase_Number ( char **cp, char *arg );
@@ -297,6 +301,7 @@
  *  TKIND_INFO         flag mask       Enable masked traces
  *  TKIND_DEBUG                flag mask       Enable masked options
  *  TKIND_IR           phase number    Enable IR trace for phase
+ *  TKIND_VCG          phase number    Enable VCG dump for phase
  *  TKIND_SYMTAB       phase number    Enable SYMTAB trace for phase
  *  TKIND_TN           phase number    Enable TN trace for phase
  *  TKIND_BB           BB number       Restrict tracing to BB


------------------------------------------------------------------------------
uberSVN's rich system and user administration capabilities and model 
configuration take the hassle out of deploying and managing Subversion and 
the tools developers use with it. Learn more about uberSVN and get a free 
download at:  http://p.sf.net/sfu/wandisco-dev2dev
_______________________________________________
Open64-devel mailing list
Open64-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/open64-devel

Reply via email to