[patch] Fix PR middle-end/46894

Eric Botcazou ebotcazou@adacore.com
Thu Jan 13 16:36:00 GMT 2011


Hi,

this is a fallout of Richard's stack realignment patch (PR rtl-opt/33721) 
visible on PowerPC 32-bit.  The problem is that in the checkg_32qi function:

typedef int __attribute__((mode(QI))) qi;

typedef qi __attribute__((vector_size (32))) v32qi;

typedef union U32QI { v32qi v; qi a[32]; } u32qi;

extern v32qi g_v32qi;

void checkg_32qi (void)
{
  u32qi u;
  qi *p = u.a;
  u.v = g_v32qi;
  checkp_32qi (p);
}

'u' overlaps 'p' on the stack:

(gdb) p &u
$26 = (u32qi *) 0xffffe500
(gdb) p &p
$27 = (qi **) 0xffffe518

The dynamic allocation for the super-aligned variable is broken:

(gdb) p/x $r1
$28 = 0xffffe510

(gdb) p/x $r0
$30 = 0xffffe500

the difference should be at least 32.

The wrong computation is done in allocate_dynamic_stack_space:

  if (must_align)
    {
      unsigned extra, extra_align;

      if (required_align > PREFERRED_STACK_BOUNDARY)
	extra_align = PREFERRED_STACK_BOUNDARY;
      else if (required_align > STACK_BOUNDARY)
	extra_align = STACK_BOUNDARY;
      else
	extra_align = BITS_PER_UNIT;
      extra = (required_align - extra_align) / BITS_PER_UNIT;

      size = plus_constant (size, extra);
      size = force_operand (size, NULL_RTX);

      if (flag_stack_usage)
	stack_usage_size += extra;

      if (extra && size_align > extra_align)
	size_align = extra_align;
    }

(gdb) p required_align
$10 = 256
(gdb) p extra_align
$11 = 128
(gdb) p extra
$12 = 16

but virtual_stack_dynamic_rtx isn't aligned, i.e. STACK_DYNAMIC_OFFSET is 
defined and isn't a multiple of PREFERRED_STACK_BOUNDARY, it's 8 here.

The attached patch forces extra_align to BITS_PER_UNIT in this case, i.e.

#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET)
  must_align = true;
#endif

Now there is a hitch: since

2003-10-07  Geoffrey Keating  <geoffk@apple.com>

	* function.c (pad_to_arg_alignment): Take STACK_POINTER_OFFSET into
	account	when aligning arguments.
	* calls.c (STACK_POINTER_OFFSET): Move default from here ...
	* defaults.h (STACK_POINTER_OFFSET): ... to here.

STACK_POINTER_OFFSET is always defined, so we always align; with the patch, 
we'll additionally always assume BITS_PER_UNIT.  But I guess this latter 
pessimization is dwarfed by the former.  What do you think, Richard?

Lightly tested on x86 and PowerPC Linux for now.


2011-01-13  Eric Botcazou  <ebotcazou@adacore.com>

	PR middle-end/46894
	* explow.c (allocate_dynamic_stack_space): Do not assume more than
	BITS_PER_UNIT alignment if STACK_DYNAMIC_OFFSET or STACK_POINTER_OFFSET
	are defined.


-- 
Eric Botcazou
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pr46894.diff
Type: text/x-diff
Size: 1591 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20110113/e2f2886e/attachment.bin>


More information about the Gcc-patches mailing list