public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug target/16325] New: value profiling clobbers gp on mips
@ 2004-07-02  3:16 wilson at gcc dot gnu dot org
  2004-07-02  3:19 ` [Bug target/16325] " wilson at gcc dot gnu dot org
                   ` (12 more replies)
  0 siblings, 13 replies; 16+ messages in thread
From: wilson at gcc dot gnu dot org @ 2004-07-02  3:16 UTC (permalink / raw)
  To: gcc-bugs

A customer reported that compiling SPEC95 using FDO (i.e. -fprofile-generate and
-fprofile-use) and -mabi=32 causes 146.wave5 to fail.  I don't think I can
distribute SPEC95 sources, but I have managed to create a small C testcase which
I will attach.

The problem here is a bit involved, and depends on several aspects of the MIPS ABI.

The value profiling code is enabled by -fprofile-generate.  This code
instruments divides by registers, to check for cases where we are always
dividing by the same value.  Such cases can be optimized to use constant divides
instead.  This code emits DImode comparisons.  For a 32-bit MIPS target, this
means a cmpdi2 libcall.  If you have a divide inside a leaf function, it will no
longer be a leaf function after profile.c runs.  This happens after virtual
register instantiation, and before reload.

On the MIPS, the ABI traditionally makes the FP equal to the SP immediately
after the prologue.  Thus STARTING_FRAME_OFFSET includes the size of the
outgoing args and space for the gp save area.  In this case, during virtual
register elimination, current_function_outgoing_args_size is 0, so the local
variables are placed at offset 8 (4 bytes for gp save area, 4 bytes for stack
alignment).

When we get to reload, current_function_outgoing_args_size is now 16.  This is
because cmpdi2 needs 16 bytes of arguments, and ABI32 allocates stack space for
arguments in registers.  INITIAL_ELIMINATION_OFFSET defines the offset between
the fp and sp as zero.  The FP gets eliminated, and now the local args start at
sp+8.  Meanwhile, compute_frame_size sees that we have 16 bytes of outgoing
args, so the gp save area is placed at sp+16.

We now have the problem that the local args area overlaps the gp save area.  If
you store to a local arg that overlaps the gp save area, call a function, and
then restore gp after the function returns, then the gp is clobbered.  The next
use of the gp results in a bus error/segmentation fault or similar problem.

If we want the ability to make libcalls in leaf functions, then it seems to me
that this is a flaw in the MIPS ABI.  We can't eliminate the FP to be the same
as the SP.  At best, we can make the FP be SP+outgoing args size.  This implies
that we remove current_function_outgoing_args_size from STARTING_FRAME_OFFSET,
and add it to INITIAL_ELIMINATION_OFFSET.  However, this is effectively an ABI
change.  This will perhaps effect EH info, debugging info, debuggers (that
disassemble prologues), asms that make assumptions about FP values, and perhaps
other things.  It isn't clear that this change is safe or desirable.

An alternative solution is to eliminate the cmpdi2 libcalls.  One way to do this
is to modify mips.md to add a 32-bit cmpdi2 pattern.  I believe this can be done
in 8 instructions, 4 for a subtract, and 4 to reduce the result to -1/0/1.  This
is a bit large for a define_expand/define_insn though.  It isn't clear if this
is desirable.

Another way to eliminate the libcalls would be to change gcov_type from DImode
to SImode.  However, this potentially causes compatibility problems, as it will
change the format of some profiling files.  There are potential cross
compilation problems.  This overrides a deliberate decision by the profile
maintainers to use DImode to avoid overflowing SImode counters.  It isn't clear
that this is desirable.

Another solution is to just add extra bytes to leaf function stack frames when
profiling.  This isn't very elegant, but seems like the simplest and safest
solution I can come up with.  Since profiled code will already be slow, wasting
a few bytes of stack space should not be an issue.  If we always assume that a
leaf function has 16 bytes of stack space, then the resulting code will still
work if a cmpdi2 libcall is emitted.  This is potentially fragile, as it assumes
the profiling code will never emit a libcall that uses more than 16 bytes of
stack space, but then I already said this was inelegant.  I will attach a patch
for this.  This works for the testcase.  I will be testing this against SPEC95
to make sure it works for all cases.

-- 
           Summary: value profiling clobbers gp on mips
           Product: gcc
           Version: 3.4.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: target
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: wilson at gcc dot gnu dot org
                CC: gcc-bugs at gcc dot gnu dot org
  GCC host triplet: mips64-unknown-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16325


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2004-07-30 19:35 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-02  3:16 [Bug target/16325] New: value profiling clobbers gp on mips wilson at gcc dot gnu dot org
2004-07-02  3:19 ` [Bug target/16325] " wilson at gcc dot gnu dot org
2004-07-02  3:21 ` wilson at gcc dot gnu dot org
     [not found]   ` <mailpost.1088738529.10024@news-sj1-1>
2004-07-02  3:58     ` cgd
2004-07-02  4:04       ` cgd
2004-07-02  3:58 ` cgd at broadcom dot com
2004-07-02  4:04 ` cgd at broadcom dot com
2004-07-02  4:09 ` pinskia at gcc dot gnu dot org
2004-07-03  1:00 ` wilson at specifixinc dot com
2004-07-03  1:56 ` rth at gcc dot gnu dot org
2004-07-03  2:09 ` steven at gcc dot gnu dot org
2004-07-15  0:35 ` cvs-commit at gcc dot gnu dot org
2004-07-15  0:42 ` cvs-commit at gcc dot gnu dot org
2004-07-15  0:46 ` wilson at gcc dot gnu dot org
2004-07-15  0:46 ` wilson at gcc dot gnu dot org
2004-07-30 19:35 ` pinskia at gcc dot gnu dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).