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]

x86: Not clobbering %edx at function entry when profiling


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




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