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