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