This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
x86: Not clobbering %edx at function entry when profiling
- To: gcc-patches at gcc dot gnu dot org
- Subject: x86: Not clobbering %edx at function entry when profiling
- From: Zack Weinberg <zack at wolery dot cumb dot org>
- Date: Wed, 12 Jul 2000 11:58:43 -0700
Over a year ago, Dimitris Michailidis <dimitris@darkside.engr.sgi.com>
pointed out that -pg and -mregparm cannot be used together on x86.
The profiling hook at function entry clobbers %edx, which has an
argument in it when -mregparm is used. Modern implementations of
mcount do not need the value we load into %edx; it's for the ancient
non-graph profiler. ("Ancient" here means "before 1982".) We also
waste a word in the data segment for each function to cater to the old
profiler.
I'm resurrecting this issue because I'd like to reduce the profiling
overhead, not particularly because of -mregparm. GCC doesn't make any
distinction between -p and -pg and I do not propose to introduce one
now. Instead, I'd like to introduce a new target macro which
indicates that the target does not need the call-count slot. With
that, and suitable modifications to FUNCTION_PROFILER, each target can
decide whether or not to support non-graph profiling. The appended
patch has the machine-independent change and the target tweak for
x86/linux, which has never had a non-graph profiler.
The patch shaves a percentage point or so off runtime of profiled
executables, and makes a hefty reduction in the size of the data
section (at least 10%).
zw
* final.c (profile_function): Do not emit profile counters in
the data section, if NO_PROFILE_COUNTERS is defined.
* tm.texi: Document NO_PROFILE_COUNTERS. Update doc for
FUNCTION_PROFILER.
* config/i386/linux.h (NO_PROFILE_COUNTERS): Define.
(FUNCTION_PROFILER): Just emit a call to mcount.
===================================================================
Index: final.c
--- final.c 2000/07/08 21:17:51 1.136
+++ final.c 2000/07/12 18:44:13
@@ -1705,7 +1705,9 @@ static void
profile_function (file)
FILE *file;
{
+#ifndef NO_PROFILE_COUNTERS
int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
+#endif
#if defined(ASM_OUTPUT_REG_PUSH)
#if defined(STRUCT_VALUE_INCOMING_REGNUM) || defined(STRUCT_VALUE_REGNUM)
int sval = current_function_returns_struct;
@@ -1715,10 +1717,12 @@ profile_function (file)
#endif
#endif /* ASM_OUTPUT_REG_PUSH */
+#ifndef NO_PROFILE_COUNTERS
data_section ();
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);
assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, 1);
+#endif
function_section (current_function_decl);
===================================================================
Index: tm.texi
--- tm.texi 2000/06/25 17:27:28 1.131
+++ tm.texi 2000/07/12 18:56:01
@@ -3502,18 +3502,24 @@ These macros will help you generate code
@item FUNCTION_PROFILER (@var{file}, @var{labelno})
A C statement or compound statement to output to @var{file} some
assembler code to call the profiling subroutine @code{mcount}.
-Before calling, the assembler code must load the address of a
-counter variable into a register where @code{mcount} expects to
-find the address. The name of this variable is @samp{LP} followed
-by the number @var{labelno}, so you would generate the name using
-@samp{LP%d} in a @code{fprintf}.
@findex mcount
-The details of how the address should be passed to @code{mcount} are
-determined by your operating system environment, not by GCC. To
-figure them out, compile a small program for profiling using the
-system's installed C compiler and look at the assembler code that
-results.
+The details of how @code{mcount} expects to be called are determined by
+your operating system environment, not by GCC. To figure them out,
+compile a small program for profiling using the system's installed C
+compiler and look at the assembler code that results.
+
+Older implementations of @code{mcount} expect the address of a counter
+variable to be loaded into some register. The name of this variable is
+@samp{LP} followed by the number @var{labelno}, so you would generate
+the name using @samp{LP%d} in a @code{fprintf}.
+
+@findex NO_PROFILE_COUNTERS
+@item NO_PROFILE_COUNTERS
+Define this macro if the @code{mcount} subroutine on your system does
+not need a counter variable allocated for each function. This is true
+for almost all modern implementations. If you define this macro, you
+must not use the @var{labelno} argument to @code{FUNCTION_PROFILER}.
@findex PROFILE_BEFORE_PROLOGUE
@item PROFILE_BEFORE_PROLOGUE
===================================================================
Index: config/i386/linux.h
--- config/i386/linux.h 2000/01/31 07:28:05 1.18
+++ config/i386/linux.h 2000/07/12 18:44:14
@@ -54,23 +54,19 @@ Boston, MA 02111-1307, USA. */
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n]
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
+/* Output assembler code to FILE to call the profiler.
+ To the best of my knowledge, no Linux libc has required the label
+ argument to mcount. */
+#define NO_PROFILE_COUNTERS
+
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE, LABELNO) \
{ \
if (flag_pic) \
- { \
- fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \
- LPREFIX, (LABELNO)); \
- fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \
- } \
+ fprintf (FILE, "\tcall\t*mcount@GOT(%%ebx)\n"); \
else \
- { \
- fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \
- fprintf (FILE, "\tcall mcount\n"); \
- } \
+ fprintf (FILE, "\tcall\tmcount\n"); \
}
#undef SIZE_TYPE