This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commited] output gcov files for -ftree-based-profiling too


Hi,
this patch merge some of boring bits from tree profiling branch to get
coverage sorta working on -ftree-profiling-branch.  It still can get
messed up with cfgcleanup executed earlier.  I will post separate patch
for this later.

The code is still disabled by default now.

Bootstrapped/regtested i686-pc-gnu-linux and commited.

Honza

2004-09-11  Jan Hubicka  <jh@suse.cz>
	* profile.c (BB_TO_GCOV_INDEX): move more to the front.
	(output_location): Break out from ....
	(branch_prob): ... here; handle gcov output on trees.
	* toplev.c (process_options): No longer be sorry about coverage for
	trees.
Index: profile.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/profile.c,v
retrieving revision 1.136
retrieving revision 1.93.2.25.2.7
diff -c -3 -p -r1.136 -r1.93.2.25.2.7
*** profile.c	4 Aug 2004 21:37:05 -0000	1.136
--- profile.c	6 Aug 2004 06:54:26 -0000	1.93.2.25.2.7
*************** compute_value_histograms (unsigned n_val
*** 676,681 ****
--- 677,729 ----
        free (histogram_counts[t]);
  }
  
+ #define BB_TO_GCOV_INDEX(bb)  ((bb)->index + 1)
+ /* When passed NULL as file_name, initialize.
+    When passed something else, output the neccesary commands to change
+    line to LINE and offset to FILE_NAME.  */
+ static void
+ output_location (char const *file_name, int line,
+ 		 gcov_position_t *offset, basic_block bb)
+ {
+   static char const *prev_file_name;
+   static int prev_line;
+   bool name_differs, line_differs;
+ 
+   if (!file_name)
+     {
+       prev_file_name = NULL;
+       prev_line = -1;
+       return;
+     }
+ 
+   name_differs = !prev_file_name || strcmp (file_name, prev_file_name);
+   line_differs = prev_line != line;
+ 
+   if (name_differs || line_differs)
+     {
+       if (!*offset)
+ 	{
+ 	  *offset = gcov_write_tag (GCOV_TAG_LINES);
+ 	  gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
+ 	  name_differs = line_differs=true;
+ 	}
+ 
+       /* If this is a new source file, then output the
+ 	 file's name to the .bb file.  */
+       if (name_differs)
+ 	{
+ 	  prev_file_name = file_name;
+ 	  gcov_write_unsigned (0);
+ 	  gcov_write_string (prev_file_name);
+ 	}
+       if (line_differs)
+ 	{
+ 	  gcov_write_unsigned (line);
+ 	  prev_line = line;
+ 	}
+      }
+ }
+ 
  /* Instrument and/or analyze program behavior based on program flow graph.
     In either case, this function builds a flow graph for the function being
     compiled.  The flow graph is stored in BB_GRAPH.
*************** branch_prob (void)
*** 843,849 ****
        */
    ENTRY_BLOCK_PTR->index = -1;
    EXIT_BLOCK_PTR->index = last_basic_block;
- #define BB_TO_GCOV_INDEX(bb)  ((bb)->index + 1)
  
    /* Arcs */
    if (coverage_begin_output ())
--- 887,892 ----
*************** branch_prob (void)
*** 870,875 ****
--- 913,924 ----
  		    flag_bits |= GCOV_ARC_FAKE;
  		  if (e->flags & EDGE_FALLTHRU)
  		    flag_bits |= GCOV_ARC_FALLTHROUGH;
+ 		  /* On trees we don't have fallthru flags, but we can
+ 		     recompute them from CFG shape.  */
+ 		  if (ir_type ()
+ 		      && e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)
+ 		      && e->src->next_bb == e->dest)
+ 		    flag_bits |= GCOV_ARC_FALLTHROUGH;
  
  		  gcov_write_unsigned (BB_TO_GCOV_INDEX (e->dest));
  		  gcov_write_unsigned (flag_bits);
*************** branch_prob (void)
*** 881,958 ****
      }
  
    /* Line numbers.  */
!   /* FIXME:  make this work for trees.  (Line numbers are in location_t
!      objects, but aren't always attached to the obvious tree...) */
!   if (coverage_begin_output () && !ir_type ())
      {
!       char const *prev_file_name = NULL;
!       gcov_position_t offset;
  
!       FOR_EACH_BB (bb)
  	{
! 	  rtx insn = BB_HEAD (bb);
! 	  int ignore_next_note = 0;
! 
! 	  offset = 0;
  
! 	  /* We are looking for line number notes.  Search backward
! 	     before basic block to find correct ones.  */
! 	  insn = prev_nonnote_insn (insn);
! 	  if (!insn)
! 	    insn = get_insns ();
! 	  else
! 	    insn = NEXT_INSN (insn);
! 
! 	  while (insn != BB_END (bb))
  	    {
! 	      if (NOTE_P (insn))
! 		{
! 		  /* Must ignore the line number notes that
! 		     immediately follow the end of an inline function
! 		     to avoid counting it twice.  There is a note
! 		     before the call, and one after the call.  */
! 		  if (NOTE_LINE_NUMBER (insn)
! 		      == NOTE_INSN_REPEATED_LINE_NUMBER)
! 		    ignore_next_note = 1;
! 		  else if (NOTE_LINE_NUMBER (insn) <= 0)
! 		    /*NOP*/;
! 		  else if (ignore_next_note)
! 		    ignore_next_note = 0;
! 		  else
! 		    {
! 		      expanded_location s;
  
! 		      if (!offset)
! 			{
! 			  offset = gcov_write_tag (GCOV_TAG_LINES);
! 			  gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
! 			}
  
! 		      NOTE_EXPANDED_LOCATION (s, insn);
  
! 		      /* If this is a new source file, then output the
! 			 file's name to the .bb file.  */
! 		      if (!prev_file_name
! 			  || strcmp (s.file, prev_file_name))
  			{
! 			  prev_file_name = s.file;
! 			  gcov_write_unsigned (0);
! 			  gcov_write_string (prev_file_name);
  			}
- 		      gcov_write_unsigned (s.line);
  		    }
  		}
- 	      insn = NEXT_INSN (insn);
  	    }
  
! 	  if (offset)
  	    {
! 	      /* A file of NULL indicates the end of run.  */
! 	      gcov_write_unsigned (0);
! 	      gcov_write_string (NULL);
! 	      gcov_write_length (offset);
  	    }
! 	}
      }
  
    ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
--- 930,1041 ----
      }
  
    /* Line numbers.  */
!   if (coverage_begin_output ())
      {
!       /* Initialize the output.  */
!       output_location (NULL, 0, NULL, NULL);
  
!       if (!ir_type ())
  	{
! 	  gcov_position_t offset;
  
! 	  FOR_EACH_BB (bb)
  	    {
! 	      rtx insn = BB_HEAD (bb);
! 	      int ignore_next_note = 0;
  
! 	      offset = 0;
  
! 	      /* We are looking for line number notes.  Search backward
! 		 before basic block to find correct ones.  */
! 	      insn = prev_nonnote_insn (insn);
! 	      if (!insn)
! 		insn = get_insns ();
! 	      else
! 		insn = NEXT_INSN (insn);
  
! 	      while (insn != BB_END (bb))
! 		{
! 		  if (NOTE_P (insn))
! 		    {
! 		      /* Must ignore the line number notes that
! 			 immediately follow the end of an inline function
! 			 to avoid counting it twice.  There is a note
! 			 before the call, and one after the call.  */
! 		      if (NOTE_LINE_NUMBER (insn)
! 			  == NOTE_INSN_REPEATED_LINE_NUMBER)
! 			ignore_next_note = 1;
! 		      else if (NOTE_LINE_NUMBER (insn) <= 0)
! 			/*NOP*/;
! 		      else if (ignore_next_note)
! 			ignore_next_note = 0;
! 		      else
  			{
! 		          expanded_location s;
! 		          NOTE_EXPANDED_LOCATION (s, insn);
! 			  output_location (s.file, NOTE_LINE_NUMBER (insn), &offset, bb);
  			}
  		    }
+ 		  insn = NEXT_INSN (insn);
+ 		}
+ 
+ 	      if (offset)
+ 		{
+ 		  /* A file of NULL indicates the end of run.  */
+ 		  gcov_write_unsigned (0);
+ 		  gcov_write_string (NULL);
+ 		  gcov_write_length (offset);
  		}
  	    }
+ 	}
+       else
+ 	{
+ 	  gcov_position_t offset;
+ 	  location_t *curr_location = NULL;
  
! 	  FOR_EACH_BB (bb)
  	    {
! 	      block_stmt_iterator bsi;
! 
! 	      offset = 0;
! 
! 	      if (bb == ENTRY_BLOCK_PTR->next_bb)
! 		{
! 		  curr_location = &DECL_SOURCE_LOCATION (current_function_decl);
! 		  output_location (curr_location->file, curr_location->line,
! 				   &offset, bb);
! 		}
! 
! 	      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
! 		{
! 		  tree stmt = bsi_stmt (bsi);
! #ifdef USE_MAPPED_LOCATION
! 		  curr_location = EXPR_LOCATION (stmt);
! #else
! 		  curr_location = EXPR_LOCUS (stmt);
! #endif
! 		  if (curr_location)
! 		    output_location (curr_location->file, curr_location->line,
! 				     &offset, bb);
! 		}
! 
! 	      /* Notice GOTO expressions we elliminated while constructing the
! 	         CFG.  */
! 	      if (bb->succ && !bb->succ->succ_next && bb->succ->goto_locus)
! 	        {
! 		  curr_location = bb->succ->goto_locus;
! 	          output_location (curr_location->file, curr_location->line, &offset, bb);
! 	        }
! 
! 	      if (offset)
! 		{
! 		  /* A file of NULL indicates the end of run.  */
! 		  gcov_write_unsigned (0);
! 		  gcov_write_string (NULL);
! 		  gcov_write_length (offset);
! 		}
  	    }
! 	 }
      }
  
    ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.923
diff -c -3 -p -r1.923 toplev.c
*** toplev.c	10 Sep 2004 19:03:07 -0000	1.923
--- toplev.c	11 Sep 2004 00:36:42 -0000
*************** process_options (void)
*** 1752,1759 ****
      warning ("this target machine does not have delayed branches");
  #endif
  
-   if (flag_tree_based_profiling && flag_test_coverage)
-     sorry ("test-coverage not yet implemented in trees.");
    if (flag_tree_based_profiling && flag_profile_values)
      sorry ("value-based profiling not yet implemented in trees.");
  
--- 1752,1757 ----
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.923
diff -c -3 -p -r1.923 toplev.c
*** toplev.c	10 Sep 2004 19:03:07 -0000	1.923
--- toplev.c	11 Sep 2004 00:41:36 -0000
*************** process_options (void)
*** 1752,1759 ****
      warning ("this target machine does not have delayed branches");
  #endif
  
-   if (flag_tree_based_profiling && flag_test_coverage)
-     sorry ("test-coverage not yet implemented in trees.");
    if (flag_tree_based_profiling && flag_profile_values)
      sorry ("value-based profiling not yet implemented in trees.");
  
--- 1752,1757 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]