Bug 50938 - x86 alloca adds 15 twice
Summary: x86 alloca adds 15 twice
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2011-10-31 17:37 UTC by Ian Lance Taylor
Modified: 2021-09-09 23:32 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-10-31 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ian Lance Taylor 2011-10-31 17:37:11 UTC
Using alloca on x86 requires that the return value be aligned to a 16-byte (boundary).  So code needs to add 15 to the size and then do & ~15.  However, compile this file:

extern void bar (char *);
void
foo (int n)
{
  bar (__builtin_alloca (n));
}

The generated code adds 30, not 15.  That is, the adjustment is made twice.  This works but wastes stack space.

The code in allocate_dynamic_stack_space in explow.c has become rather convoluted and needs to be cleaned up to make this work.  E.g., it does #if defined (STACK_POINTER_OFFSET), but defaults.h ensures that STACK_POINTER_OFFSET is always defined.
Comment 1 Paul Pluzhnikov 2011-10-31 17:43:50 UTC
This bug prevent glibc's extend_alloca from working as it is intended.

The macro (for _STACK_GROWS_DOWN) is:

# define extend_alloca(buf, len, newlen) \
  (__typeof (buf)) ({ size_t __newlen = (newlen);                             \
                      char *__newbuf = __alloca (__newlen);                   \
                      if (__newbuf + __newlen == (char *) buf)                \
                        len += __newlen;                                      \
                      else                                                    \
                        len = __newlen;                                       \
                      __newbuf; })

However due to the +30 adjustment, __newbuf + __newlen == (char *) buf is never true.

This leads to excessive stack use in glibc under some conditions.
Comment 2 Eric Botcazou 2011-10-31 20:40:55 UTC
> The code in allocate_dynamic_stack_space in explow.c has become rather
> convoluted and needs to be cleaned up to make this work.  E.g., it does #if
> defined (STACK_POINTER_OFFSET), but defaults.h ensures that
> STACK_POINTER_OFFSET is always defined.

Yep, this is PR middle-end/47353.