Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Donn Terry" <donnte@microsoft.com>
To: "Michael Snyder" <msnyder@redhat.com>
Cc: <gdb-patches@sources.redhat.com>
Subject: RE: Single step vs. "tail recursion" optimization
Date: Fri, 08 Nov 2002 13:57:00 -0000	[thread overview]
Message-ID: <FE465D8F724E3F4F811D067203A214AE06D7B61A@red-msg-08.redmond.corp.microsoft.com> (raw)

(I'm sorry to have to be the messenger on this one...)

Here's a mini testcase.  I've also attached the resulting .s files for
-O2 and -O3.
Shudder.  Andrew's speculation about s not working because there were no
symbols
is correct.  S-ing works until the call to getpid().

I haven't actually tried to figure out why gdb isn't doing it right in
that case
because there's actually something potentially even uglier going on in
the -O3 case.
This is something that the "management" of gdb and the "management" of
gcc are going
to have to take on and resolve as either "no, you can't sanely debug
-O3" or "we need
some help from the compiler to sort this one out".  (And if the latter,
then the same
help may be useful with the -O2 case!)  (I haven't seen this addressed,
but I could
easily have missed it.)

Note that in the case of -O3, foo() and bar() are NEVER actually called
from main,
but rather getpid() is called directly. (Note also the reordering of the
functions.)
(Seeing that this sort of optimization is pretty compellingly needed for
C++ code,
"don't do that" seems an unlikely outcome.)

Donn
P.S.  This may explain some instances of "stack unwind missed a frame"
bugs.

bar() {
    getpid();
}

foo() {
    bar();
}

main()
{
   foo();
}

------------------ -O2 -------------------
        .file   "bat.c"
.global __fltused
        .text
        .p2align 4,,15
.globl _bar
        .def    _bar;   .scl    2;      .type   32;     .endef
_bar:
        pushl   %ebp
        movl    %esp, %ebp
        popl    %ebp
        jmp     _getpid
        .p2align 4,,15
.globl _foo
        .def    _foo;   .scl    2;      .type   32;     .endef
_foo:
        pushl   %ebp
        movl    %esp, %ebp
        popl    %ebp
        jmp     _bar
        .def    ___main;        .scl    2;      .type   32;     .endef
        .p2align 4,,15
.globl _main
        .def    _main;  .scl    2;      .type   32;     .endef
_main:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %eax
        pushl   %eax
        xorl    %eax, %eax
        andl    $-16, %esp
        call    __alloca
        call    ___main
        call    _foo
        movl    %ebp, %esp
        popl    %ebp
        ret
        .def    _getpid;        .scl    2;      .type   32;     .endef
------------------------ -O3 ---------------------------------
        .file   "bat.c"
.global __fltused
        .def    ___main;        .scl    2;      .type   32;     .endef
        .text
        .p2align 4,,15
.globl _main
        .def    _main;  .scl    2;      .type   32;     .endef
_main:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %eax
        pushl   %eax
        xorl    %eax, %eax
        andl    $-16, %esp
        call    __alloca
        call    ___main
        call    _getpid             <<< NO CALL TO foo()
        movl    %ebp, %esp
        popl    %ebp
        ret
        .p2align 4,,15
.globl _bar
        .def    _bar;   .scl    2;      .type   32;     .endef
_bar:
        pushl   %ebp
        movl    %esp, %ebp
        popl    %ebp
        jmp     _getpid
        .p2align 4,,15
.globl _foo
        .def    _foo;   .scl    2;      .type   32;     .endef
_foo:
        pushl   %ebp
        movl    %esp, %ebp
        popl    %ebp
        jmp     _getpid            <<<  NOTE THAT foo() doesn't call
bar() either!
        .def    _getpid;        .scl    2;      .type   32;     .endef

-----Original Message-----
From: Michael Snyder [mailto:msnyder@redhat.com] 
Sent: Friday, November 08, 2002 11:43 AM
To: Donn Terry
Cc: gdb-patches@sources.redhat.com
Subject: Re: Single step vs. "tail recursion" optimization


Donn Terry wrote:
> 
> While debugging gdb, I ran across a really nasty little issue: the gcc

> guys (for the "bleeding edge", at least) have generated an 
> optimization such that if the last thing in function x is a function 
> call to y, it will short circut the return from x, and set things up 
> so it returns directly from y.  (A special case of tail recursion 
> optimizations.)
> 
> If you try to n (or s) over that, the debugged program runs away 
> because gdb doesn't know about that magic.  The real example is 
> regcache_raw_read, which ends in a memcpy.  Instead of jsr-ing to the 
> memcpy and then returning, it fiddles with the stack and jmps to 
> memcpy. Is this a known issue, and is it being worked, or have I just 
> run across something new to worry about?
> 
> (This is on Interix (x86, obviously from the code below) with a gcc 
> that's less than a week old.  I have no idea how long it might 
> actually have been this way.  I doubt
> the problem is actually unique to the x86 as this is a very general
> optimization.)
> 
> Donn

Tail-recursion isn't a new optimization, but I have almost no (only the
vaguest) recollection of ever having run up against 
it before.  Could be there's a change with the way GCC is 
implementing it.  Could be we never handled it before.

This sounds like a good argument for parsing the epilogue...   ;-(

Michael

> 
> Heres the code:
> 
> 0x466e37 <regcache_raw_read+151>:       mov    0x1c(%eax),%ecx
> 0x466e3a <regcache_raw_read+154>:       mov    0x18(%eax),%eax
> 0x466e3d <regcache_raw_read+157>:       mov    (%eax,%esi,4),%edx
> 0x466e40 <regcache_raw_read+160>:       mov    0x4(%ebx),%eax
> 0x466e43 <regcache_raw_read+163>:       add    %eax,%edx
> 0x466e45 <regcache_raw_read+165>:       mov    (%ecx,%esi,4),%eax
> 0x466e48 <regcache_raw_read+168>:       mov    %eax,0x10(%ebp)
> 0x466e4b <regcache_raw_read+171>:       mov    %edx,0xc(%ebp)
> 0x466e4e <regcache_raw_read+174>:       mov    %edi,0x8(%ebp)
> 0x466e51 <regcache_raw_read+177>:       lea    0xfffffff4(%ebp),%esp
> 0x466e54 <regcache_raw_read+180>:       pop    %ebx
> 0x466e55 <regcache_raw_read+181>:       pop    %esi
> 0x466e56 <regcache_raw_read+182>:       pop    %edi
> 0x466e57 <regcache_raw_read+183>:       pop    %ebp
> 0x466e58 <regcache_raw_read+184>:       jmp    0x77d91e60 <memcpy>
> 0x466e5d <regcache_raw_read+189>:       lea    0x0(%esi),%esi


             reply	other threads:[~2002-11-08 21:57 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-11-08 13:57 Donn Terry [this message]
2002-11-08 15:11 ` Michael Snyder
2002-11-13  9:43   ` Jim Blandy
2002-11-13 19:44 ` Andrew Cagney
  -- strict thread matches above, loose matches on Subject: below --
2002-11-13  9:52 Donn Terry
2002-11-07 11:18 Donn Terry
2002-11-07 17:04 ` Andrew Cagney
2002-11-08 11:43 ` Michael Snyder

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=FE465D8F724E3F4F811D067203A214AE06D7B61A@red-msg-08.redmond.corp.microsoft.com \
    --to=donnte@microsoft.com \
    --cc=gdb-patches@sources.redhat.com \
    --cc=msnyder@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox