public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Fix PR middle-end/46894
@ 2011-01-13 16:36 Eric Botcazou
  2011-01-13 17:07 ` Richard Henderson
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Botcazou @ 2011-01-13 16:36 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 2543 bytes --]

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

[-- Attachment #2: pr46894.diff --]
[-- Type: text/x-diff, Size: 1591 bytes --]

Index: explow.c
===================================================================
--- explow.c	(revision 168704)
+++ explow.c	(working copy)
@@ -1148,6 +1148,7 @@ allocate_dynamic_stack_space (rtx size,
 {
   HOST_WIDE_INT stack_usage_size = -1;
   rtx final_label, final_target, target;
+  unsigned extra_align = 0;
   bool must_align;
 
   /* If we're asking for zero bytes, it doesn't matter what we point
@@ -1230,22 +1231,26 @@ allocate_dynamic_stack_space (rtx size,
      If we have to align, we must leave space in SIZE for the hole
      that might result from the alignment operation.  */
 
-  must_align = (crtl->preferred_stack_boundary < required_align);
-#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET)
-  must_align = true;
-#endif
-
-  if (must_align)
+  if (crtl->preferred_stack_boundary < required_align)
     {
-      unsigned extra, extra_align;
-
+      must_align = true;
       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;
+    }
+
+  /* ??? STACK_POINTER_OFFSET is always defined now.  */
+#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET)
+  must_align = true;
+  extra_align = BITS_PER_UNIT;
+#endif
+
+  if (must_align)
+    {
+      unsigned extra = (required_align - extra_align) / BITS_PER_UNIT;
 
       size = plus_constant (size, extra);
       size = force_operand (size, NULL_RTX);

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-01-18 21:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-13 16:36 [patch] Fix PR middle-end/46894 Eric Botcazou
2011-01-13 17:07 ` Richard Henderson
2011-01-13 17:24   ` Eric Botcazou
2011-01-13 18:25     ` Richard Henderson
2011-01-13 18:57       ` Eric Botcazou
2011-01-14 17:27         ` IainS
2011-01-15 16:03           ` Eric Botcazou
2011-01-18 21:45             ` Eric Botcazou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).