Hi,

this is the regression introduced on 32-bit SPARC by this change:

2016-11-18  Dominik Vogt  <v...@linux.vnet.ibm.com>

        Re-apply after PR bootstrap/77359 is fixed:
        2016-08-23  Dominik Vogt  <v...@linux.vnet.ibm.com>

        * explow.c (get_dynamic_stack_size): Take known alignment of stack
        pointer + STACK_DYNAMIC_OFFSET into account when calculating the
        size needed.

and which causes the compiler to overwrite contents on the stack after a 
dynamic allocation in some cases.

IMO this patch is backwards and should not have been approved: as explained by 
the comment in get_dynamic_stack_size:

  /* We will need to ensure that the address we return is aligned to
     REQUIRED_ALIGN.  At this point in the compilation, we don't always
     know the final value of the STACK_DYNAMIC_OFFSET used in function.c
     (it might depend on the size of the outgoing parameter lists, for
     example), so we must preventively align the value.  We leave space
     in SIZE for the hole that might result from the alignment operation.  */

the function used to align the value to maintain the expected alignment of 
VIRTUAL_STACK_DYNAMIC_REGNUM.  But the new version does the opposite (without 
changing the comment):

  unsigned known_align = REGNO_POINTER_ALIGN (VIRTUAL_STACK_DYNAMIC_REGNUM);

it assumes that the alignment of VIRTUAL_STACK_DYNAMIC_REGNUM is already 
correct to optimize the dynamic allocation, i.e. to save a few bytes.

This breaks the interface between middle-end and back-end and resulted in the 
breakage of PowerPC/AIX and now of the 32-bit SPARC port.  And the failure 
mode is quite nasty: the entire testsuite of the compiler proper, including 
Ada, is clean on 32-bit SPARC and the issue only shows up in the libgomp 
testsuite, probably because of specific patterns.

IMO it's very likely that other architectures among the ~50 supported ones are 
affected and the issue might show up only in very peculiar circumstances as on 
32-bit SPARC so I think we should repair the breakage for GCC 7.  The attached 
patch is a middle ground between the previously working and currently broken 
situations: if the back-end defines STACK_DYNAMIC_OFFSET, then the middle-end 
assumes that STACK_DYNAMIC_OFFSET maintains the alignment; if it doesn't, 
which means the default value of STACK_DYNAMIC_OFFSET computed in function.c 
is used instead, then the middle-end maintains the alignment itself.

Tested on x86_64-suse-linux and SPARC/Solaris, OK for the mainline?


2017-01-27  Eric Botcazou  <ebotca...@adacore.com>

        PR middle-end/78468
        * explow.c (get_dynamic_stack_size): Take known alignment of stack
        pointer + STACK_DYNAMIC_OFFSET into account only if the back-end
        defines STACK_DYNAMIC_OFFSET.

-- 
Eric Botcazou
Index: explow.c
===================================================================
--- explow.c	(revision 244917)
+++ explow.c	(working copy)
@@ -1231,9 +1231,14 @@ get_dynamic_stack_size (rtx *psize, unsi
      know the final value of the STACK_DYNAMIC_OFFSET used in function.c
      (it might depend on the size of the outgoing parameter lists, for
      example), so we must preventively align the value.  We leave space
-     in SIZE for the hole that might result from the alignment operation.  */
-
+     in SIZE for the hole that might result from the alignment operation.
+     However, we assume that, if STACK_DYNAMIC_OFFSET is defined by the
+     back-end itself as opposed to function.c, it is properly aligned.  */
+#ifdef STACK_DYNAMIC_OFFSET
   unsigned known_align = REGNO_POINTER_ALIGN (VIRTUAL_STACK_DYNAMIC_REGNUM);
+#else
+  unsigned known_align = 0;
+#endif
   if (known_align == 0)
     known_align = BITS_PER_UNIT;
   if (required_align > known_align)

Reply via email to