*BSD News Article 6936


Return to BSD News archive

Path: sserve!manuel.anu.edu.au!munnari.oz.au!sgiblab!darwin.sura.net!Sirius.dfn.de!mailgzrz.TU-Berlin.DE!news.netmbx.de!Germany.EU.net!mcsun!sunic!dkuug!dkuug!flshub!phk
From: phk@data.fls.dk (Poul-Henning Kamp)
Newsgroups: comp.unix.bsd
Subject: [386bsd] PATCH: BB-profiling for gcc
Message-ID: <1992Oct22.194443.19798@data.fls.dk>
Date: 22 Oct 92 19:44:43 GMT
Organization: FLS Data A/S, Valby, Copenhagen, Denmark.
Lines: 178

What is BB-profiling ?
----------------------
BB-profiling is profiling of the actual basic-block of the compiled code.
This is in many respects superior to normal 'clock-tick' or caller/called
profiling.  A very good introduction is:

	P. J. Weinberger:
	"Cheap Dynamic Instruction Counting"
	AT&T Bell Laboratories Technical Journal
	Vol. 63, No. 8, October 1984

	reprinted in:
	"Unix System, Readings & Applications Vol II"
	Prentice-Hall, ISBN 0-13-939845-7

The Diffs Part One:
-------------------
The diffs take to three parts, the first and shorter part is the actual 
instructions to gcc to produce the profiling code:

diff -C2 -r /ref/usr/src/usr.bin/gcc/cc1/config/tm-i386b.h /usr/src/usr.bin/gcc/cc1/config/tm-i386b.h
*** /ref/usr/src/usr.bin/gcc/cc1/config/tm-i386b.h	Mon Apr 13 13:52:51 1992
--- /usr/src/usr.bin/gcc/cc1/config/tm-i386b.h	Sun Oct 11 05:20:22 1992
***************
*** 77,78 ****
--- 77,92 ----
  #define FUNCTION_PROFILER(FILE, LABELNO)  \
     fprintf (FILE, "\tmovl $LP%d,%%eax\n\tcall mcount\n", (LABELNO));
+ 
+ #define FUNCTION_BLOCK_PROFILER(FILE,LABELNO) { \
+    fprintf (FILE, "\tcmpl $0,LPBX0\n"); \
+    fprintf (FILE, "\tjnz 1f\n"); \
+    fprintf (FILE, "\tpushl $LPBX0\n"); \
+    fprintf (FILE, "\tcall __bb_init_func\n"); \
+    fprintf (FILE, "\taddl $4,%%esp\n1:\n"); }
+ 
+ /* do work, but quite large...
+ #define BLOCK_PROFILER(FILE,BLOCKNO) \
+    fprintf (FILE, "\tpushf\n\tincl (LPBX2+%d)\n\tpopf\n", 4*(BLOCKNO));
+ */
+ #define BLOCK_PROFILER(FILE,BLOCKNO) \
+    fprintf (FILE, "\tincl (LPBX2+%d)\n", 4*(BLOCKNO)); CC_STATUS_INIT;


The Diffs Part Two:
-------------------
This is patches for gcc, to include certain kind of debugging  when -a is
specified.  Problem is that the kernel with -g is HUGE !!! 
This is slightly smaller.  This patch is optional, but you're kind
of clue-less without the line# info.

diff -C2 -r /ref/usr/src/usr.bin/gcc/cc1/dbxout.c /usr/src/usr.bin/gcc/cc1/dbxout.c
*** /ref/usr/src/usr.bin/gcc/cc1/dbxout.c	Tue Oct 16 21:16:31 1990
--- /usr/src/usr.bin/gcc/cc1/dbxout.c	Sun Oct 11 06:36:03 1992
***************
*** 205,208 ****
--- 205,225 ----
  }
  
+ void
+ dbxout_init_min (asm_file, input_file_name)
+      FILE *asm_file;
+      char *input_file_name;
+ {
+   asmfile = asm_file;
+ 
+   typevec_len = 100;
+   typevec = (enum typestatus *) xmalloc (typevec_len * sizeof typevec[0]);
+   bzero (typevec, typevec_len * sizeof typevec[0]);
+ 
+   /* Used to put `Ltext:' before the reference, but that loses on sun 4.  */
+   fprintf (asmfile,
+ 	   "\t.stabs \"%s\",%d,0,0,Ltext\nLtext:\n",
+ 	   input_file_name, N_SO);
+ }
+ 
  /* Continue a symbol-description that gets too big.
     End one symbol table entry with a double-backslash
diff -C2 -r /ref/usr/src/usr.bin/gcc/cc1/emit-rtl.c /usr/src/usr.bin/gcc/cc1/emit-rtl.c
*** /ref/usr/src/usr.bin/gcc/cc1/emit-rtl.c	Fri Feb  2 14:51:21 1990
--- /usr/src/usr.bin/gcc/cc1/emit-rtl.c	Sun Oct 11 06:08:16 1992
***************
*** 41,44 ****
--- 41,45 ----
  #include "insn-config.h"
  #include "real.h"
+ #include "flags.h"
  
  #define max(A,B) ((A) > (B) ? (A) : (B))
***************
*** 1548,1551 ****
--- 1549,1554 ----
  
    no_line_numbers = ! write_symbols;
+   if(profile_block_flag)
+ 	no_line_numbers=0;
    
    /* Init the tables that describe all the pseudo regs.  */
diff -C2 -r /ref/usr/src/usr.bin/gcc/cc1/final.c /usr/src/usr.bin/gcc/cc1/final.c
*** /ref/usr/src/usr.bin/gcc/cc1/final.c	Mon Aug  6 15:12:00 1990
--- /usr/src/usr.bin/gcc/cc1/final.c	Sun Oct 11 06:36:18 1992
***************
*** 590,594 ****
        if (prescan > 0)
  	break;
!       if (write_symbols == NO_DEBUG)
  	break;
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
--- 590,594 ----
        if (prescan > 0)
  	break;
!       if (write_symbols == NO_DEBUG && !profile_block_flag)
  	break;
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
***************
*** 1124,1128 ****
      }
  
!   if (write_symbols == SDB_DEBUG || write_symbols == DBX_DEBUG)
      {
  #ifdef SDB_DEBUGGING_INFO
--- 1124,1128 ----
      }
  
!   if (write_symbols == SDB_DEBUG || write_symbols == DBX_DEBUG || profile_block_flag)
      {
  #ifdef SDB_DEBUGGING_INFO
diff -C2 -r /ref/usr/src/usr.bin/gcc/cc1/toplev.c /usr/src/usr.bin/gcc/cc1/toplev.c
*** /ref/usr/src/usr.bin/gcc/cc1/toplev.c	Wed May  8 10:47:11 1991
--- /usr/src/usr.bin/gcc/cc1/toplev.c	Sun Oct 11 06:37:45 1992
***************
*** 1154,1157 ****
--- 1154,1159 ----
       and output the predefined types.  */
  #ifdef DBX_DEBUGGING_INFO
+   if (profile_block_flag)
+     dbxout_init_min (asm_out_file, main_input_filename);
    if (write_symbols == DBX_DEBUG)
      dbxout_init (asm_out_file, main_input_filename);
***************
*** 1762,1765 ****
--- 1764,1769 ----
  
  #ifdef DBX_DEBUGGING_INFO
+   if (profile_block_flag)
+     TIMEVAR (symout_time, dbxout_symbol (decl));
    if (write_symbols == DBX_DEBUG)
      TIMEVAR (symout_time, dbxout_function (decl));

The Diffs Part Three:
---------------------
This is a piece of code to be included in the binary (kernel/program), to
link together the BB-profile blocks.

It is very important ***NOT*** to compile this with -a !!

---- CUT HERE ----
struct bb {
	int	init;
	char	*filename;
	int	*counts;
	int	ncounts;
	struct	bb	*next;
	int	*addresses;
	} *__bb_count_head;

_bb_init_func(struct bb *p)
	{
	p->init++;
	p->next = __bb_count_head;
	__bb_count_head=p;
	}
---- CUT HERE ----
-- 
phk@data.fls.dk		  || 			$HOME
Poul-Henning Kamp	  ||	
FLS DATA A/S		  ||			sweet
Phone: (+45) 36 18 12 35  ||