This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
MIPS _mcount-based profiling doesn't work with -abicalls (2.95.3)
- From: Rafal Boni <rafal at mediaone dot net>
- To: gcc at gcc dot gnu dot org
- Cc: binutils at sources dot redhat dot com
- Date: Wed, 14 Nov 2001 15:43:27 -0500
- Subject: MIPS _mcount-based profiling doesn't work with -abicalls (2.95.3)
[I've CC'ed binutils in case any of you folks there have an opinion, since
the things that's biting me really is assembler magic, in a sens...]
Folks:
I've been doing some work to upgrade the NetBSD MIPS toolchain to
2.95.3 and binutils 2.11.2, and other than some issues I need to
take up with the binutils folks, most things works fine.
However, I've found that executables built with profiling libraries
(which were all rebuilt with the new toolchain) all die way before
doing anything substantial -- somewhere in the startup code.
I tracked the problem down to a bad interaction between the -abicalls
option and the profiling prologue added to functions.
Here's what happens:
(1) A function that calls _mcount and uses .cprestore looks
like the following in macroized assembler:
.globl function
function:
.cpload $25
addiu $sp, $sp, -40
.cprestore 36
...
sw $gp, 36($sp)
...
<load $t9 with address of _mcount>
jalr $t9 # _mcount
subu $sp, $sp, 8 # _mcount pops 2 works from stack
(2) The assembler in turn expands the `jalr' bit into
jalr $t9 # _mcount
nop
lw $gp, 36($sp)
subu $sp, $sp, 8
Note that due to the way the .cprestore places the load of
$gp after the jump (but before the cleanup of $sp), the code
gets the wrong value of $gp.
This is all because the FUNCTION_PROFILER macro includes some hand-
scheduled MIPS assembly with the stack-adjustment put into the delay
slot of the `jal'.
I include here two patches for this problem. The first is just a
simple re-schedule of the FUNCTION_PROFILER macro which does the
stack adjust before the `jal' always. This certainly works, and
is the safer of the two solutions, but may cost some performance
in the non-abicalls call where this is not needed.
The second patch attempts to keep the hand-scheduled code for the
non-abicalls case and produce the safer code for the abicalls case.
I'd appreciate comments esp. on the second patch -- is this worth
doing, or am I asking for some other case to screw me?
Thanks!
--rafal
The `safe' patch:
Index: mips.h
===================================================================
RCS file: /cvsroot/gnusrc/gnu/dist/toolchain/gcc/config/mips/mips.h,v
retrieving revision 1.1.1.1
diff -b -u -b -u -r1.1.1.1 mips.h
--- mips.h 2000/07/26 00:18:38 1.1.1.1
+++ mips.h 2001/11/14 18:15:52
@@ -2610,13 +2610,14 @@
fprintf (FILE, "\t.set\tnoat\n"); \
fprintf (FILE, "\tmove\t%s,%s\t\t# save current return address\n", \
reg_names[GP_REG_FIRST + 1], reg_names[GP_REG_FIRST + 31]); \
- fprintf (FILE, "\tjal\t_mcount\n"); \
fprintf (FILE, \
"\t%s\t%s,%s,%d\t\t# _mcount pops 2 words from stack\n", \
TARGET_64BIT ? "dsubu" : "subu", \
reg_names[STACK_POINTER_REGNUM], \
reg_names[STACK_POINTER_REGNUM], \
Pmode == DImode ? 16 : 8); \
+ fprintf (FILE, "\tjal\t_mcount\n"); \
+ fprintf (FILE, "\tnop\n"); \
fprintf (FILE, "\t.set\treorder\n"); \
fprintf (FILE, "\t.set\tat\n"); \
}
The `less safe' patch:
Index: mips.h
===================================================================
RCS file: /cvsroot/gnusrc/gnu/dist/toolchain/gcc/config/mips/mips.h,v
retrieving revision 1.1.1.1
diff -b -u -b -u -r1.1.1.1 mips.h
--- mips.h 2000/07/26 00:18:38 1.1.1.1
+++ mips.h 2001/11/14 18:21:57
@@ -2610,6 +2610,7 @@
fprintf (FILE, "\t.set\tnoat\n"); \
fprintf (FILE, "\tmove\t%s,%s\t\t# save current return address\n", \
reg_names[GP_REG_FIRST + 1], reg_names[GP_REG_FIRST + 31]); \
+ if (!TARGET_ABICALLS) \
fprintf (FILE, "\tjal\t_mcount\n"); \
fprintf (FILE, \
"\t%s\t%s,%s,%d\t\t# _mcount pops 2 words from stack\n", \
@@ -2617,6 +2618,10 @@
reg_names[STACK_POINTER_REGNUM], \
reg_names[STACK_POINTER_REGNUM], \
Pmode == DImode ? 16 : 8); \
+ if (TARGET_ABICALLS) { \
+ fprintf (FILE, "\tjal\t_mcount\n"); \
+ fprintf (FILE, "\tnop\n"); \
+ } \
fprintf (FILE, "\t.set\treorder\n"); \
fprintf (FILE, "\t.set\tat\n"); \
}
----
Rafal Boni rafal@mediaone.net