[PATCH] Improve alloca alignment

Jeff Law law@redhat.com
Wed Jul 26 19:12:00 GMT 2017


On 07/26/2017 11:39 AM, Wilco Dijkstra wrote:
> This patch improves alloca alignment.  Currently alloca reserves
> too much space as it aligns twice, and generates unnecessary stack
> alignment code.  For example alloca (16) generates:
> 
> 	sub	sp, sp, #32   ???
> 	mov	x1, sp
> 
> Similarly alloca (x) generates:
> 
> 	add	x0, x0, 30    ???
> 	and	x0, x0, -16
> 	sub	sp, sp, x0
> 	mov	x0, sp
> 
> __builtin_alloca_with_align (x, 256):
> 	add	x0, x0, 78    ???
> 	and	x0, x0, -16
> 	sub	sp, sp, x0
> 	add	x0, sp, 63
> 	and	x0, x0, -64
> 
> As can be seen the alignment adjustment value is incorrect.
> When the requested alignment is lower than the stack alignment, no
> extra alignment is needed.  If the requested alignment is higher,
> we need to increase the size by the difference of the requested 
> alignment and the stack alignment.  As a result, the alloca alignment
> is exactly as expected:
> 
> alloca (16):
> 	sub	sp, sp, #16
> 	mov	x1, sp
> 
> alloca (x):
> 	add	x0, x0, 15
> 	and	x0, x0, -16
> 	sub	sp, sp, x0
> 	mov	x0, sp
> 
> __builtin_alloca_with_align (x, 256):
> 	add	x0, x0, 63
> 	and	x0, x0, -16
> 	sub	sp, sp, x0
> 	add	x0, sp, 63
> 	and	x0, x0, -64
> 
> ChangeLog:
> 2017-07-26  Wilco Dijkstra  <wdijkstr@arm.com>
> 
> 	* explow.c (get_dynamic_stack_size): Improve dynamic alignment.
Hehe.  This stuff is a mess.  Dominik went round and round in this code
about a year ago, I'm not sure we ever got it right for the cases he
wanted to improve.

This is something I wanted to look at but had deferred (it makes writing
some stack-clash tests of this code more painful than it really needs to
be).


> 
> --
> diff --git a/gcc/explow.c b/gcc/explow.c
> index 50074e281edd5270c76d29feac6b7a92f598d11d..fbdda5fa1e303664e346f975270415b40aed252d 100644
> --- a/gcc/explow.c
> +++ b/gcc/explow.c
> @@ -1234,15 +1234,22 @@ get_dynamic_stack_size (rtx *psize, unsigned size_align,
>       example), so we must preventively align the value.  We leave space
>       in SIZE for the hole that might result from the alignment operation.  */
>  
> -  extra = (required_align - BITS_PER_UNIT) / BITS_PER_UNIT;
> -  size = plus_constant (Pmode, size, extra);
> -  size = force_operand (size, NULL_RTX);
> -
> -  if (flag_stack_usage_info && pstack_usage_size)
> -    *pstack_usage_size += extra;
> +  /* Since the stack is presumed to be aligned before this allocation,
> +     we only need to increase the size of the allocation if the required
> +     alignment is more than the stack alignment.
> +     Note size_align doesn't need to be updated - if it is larger than the
> +     stack alignment, size remains a multiple of the stack alignment, so
> +     we can skip rounding up to the stack alignment.  */
> +  if (required_align > MAX_SUPPORTED_STACK_ALIGNMENT)
> +    {
> +      extra = (required_align - MAX_SUPPORTED_STACK_ALIGNMENT)
> +	/ BITS_PER_UNIT;
> +      size = plus_constant (Pmode, size, extra);
> +      size = force_operand (size, NULL_RTX);
>  
> -  if (extra && size_align > BITS_PER_UNIT)
> -    size_align = BITS_PER_UNIT;
> +      if (flag_stack_usage_info && pstack_usage_size)
> +	*pstack_usage_size += extra;
> +    }
So it's unclear to me why you increase the size iff REQUIRED_ALIGN is
greater than MAX_SUPPORTED_STACK_ALIGNMENT.

ISTM the safe assumption we can make in this code is that the stack is
aligned to STACK_BOUNDARY.  If so, isn't the right test

(required_align > STACK_BOUNDARY)?

And once we decide to make an adjustment, isn't the right adjustment to
make (required_align - STACK_BOUNDARY) / BITS_PER_UNIT?

I feel like I must be missing something really important here.

jeff



More information about the Gcc-patches mailing list