Bug 55747 - Extra registers are saved in functions that only call noreturn functions
Summary: Extra registers are saved in functions that only call noreturn functions
Status: RESOLVED WONTFIX
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 4.8.0
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-12-20 01:12 UTC by Joshua Conner
Modified: 2013-10-04 20:08 UTC (History)
1 user (show)

See Also:
Host:
Target: sh*-*-* arm*-*-* cris*-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-01-06 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Joshua Conner 2012-12-20 01:12:40 UTC
On architectures such as ARM, where a link register is used to save the return address, this value does not need to be saved in a function that only calls noreturn functions.

For example, if I build the following source:

  __attribute__((noreturn))
  extern void bar (void);

  int x;

  void foo (void)
  {
    if (x)
      bar ();
  }

Using the options "-O2", the link register is saved:

  stmfd   sp!, {r3, lr}
  ...
  ldmeqfd sp!, {r3, pc}

However, this is unnecessary since the only way the link register cannot be corrupted since any calls to "bar" will not return.

Note that I am not filing this as an ARM target bug since the issue appears to be a general problem related to dataflow analysis not tracking the difference between calls to normal functions and calls to noreturn functions.  At any rate, I see a similar problem in our custom target as well.
Comment 1 Andrew Pinski 2012-12-20 01:22:11 UTC
Actually noreturns are handled special in the compiler.  I filed this bug over 6 years ago and it was closed as invalid back then.
Comment 2 Hans-Peter Nilsson 2013-01-06 08:26:11 UTC
Similarly observed for cris-elf with -O2, r194929, JFTR.

If this changes, some attribute markup should be added to keep return-addresses for noreturn functions, for sake of stack-traces.  Also return-addresses need to be generally kept when -fexceptions and similar are in effect, as noreturn functions can still throw.
Comment 3 Oleg Endo 2013-10-04 18:46:21 UTC
On SH there's a similar issue.  E.g. compiling

void exit (int __status) __attribute__ ((noreturn));

int test (int a, int b, int c)
{
  if (a == b)
    return 5;

  if (a)
    exit (0);

  return 0;
}

with -O2 -m4 results in:

_test:
        cmp/eq  r5,r4
        bt/s    .L3
        tst     r4,r4
        bf/s    .L10
        mov     #0,r0
        rts
        nop
.L3:
        rts
        mov     #5,r0
.L10:
        mov.l   .L11,r1
        sts.l   pr,@-r15     // push return address register
        jsr     @r1          // jump to subroutine
        mov     #0,r4
.L12:
        .align 2
.L11:
        .long   _exit

The jsr should be a simple jmp and the pr push is not required (as with leaf function calls).
Comment 4 Richard Earnshaw 2013-10-04 20:08:41 UTC
Sorry, we're not going to change this.  Removing the saved lr value would break back-tracing out of functions that called abort().