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.
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.
> 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.