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 ||