[PATCH] Fix PR rtl-optimization/25654 (P1 4.0/4.1/4.2 Regression)

Richard Guenther rguenther@suse.de
Mon Jan 16 16:00:00 GMT 2006


On Mon, 16 Jan 2006, Richard Guenther wrote:

> This patch fixes the stack slot sharing aliasing problem by making sure
> to add conflicts for unions of the same type.
> 
> Bootstrapped and regtested on x86_64-unknown-linux-gnu.
> 
> Ok for mainline and branches?

Honza still figures out more failing testcases, this patch
fixes two of them while leaving the following (invalid because
of aliasing issues char vs. int/short) failing:

-O2 -mpreferred-stack-boundary=2 -S -march=i686 -frename-registers

struct setconflict
{
  char a[36];
  int b;
};

int
main ()
{
  int sum = 0;
  {
    struct setconflict a;
    short *c;
    c = (void *)a.a;
    asm ("": "=r" (c):"0" (c));
    *c = 0;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }
  {
    struct setconflict a;
    int *c;
    c = (void *)a.a;
    asm ("": "=r" (c):"0" (c));
    *c = 1;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }

  printf ("%d\n",sum);
  if (sum != 1)
    abort();
  return 0;
}

Does this look invalid to anyone else?

Richard.


2006-01-16  Steven Bosscher  <stevenb.gcc@gmail.com>
	Jan Hubicka  <jh@suse.cz>
	Richard Guenther  <rguenther@suse.de>

	PR rtl-optimization/25654
	* cfgexpand.c (stack_var_conflict_p): Make sure to add conflicts
	for variables with the same union type.

	* gcc.dg/torture/pr25654.c: New testcase.
	* gcc.target/i386/pr25654-3.c: Likewise.

Index: cfgexpand.c
===================================================================
*** cfgexpand.c	(revision 109743)
--- cfgexpand.c	(working copy)
*************** stack_var_conflict_p (size_t x, size_t y
*** 272,281 ****
    gcc_assert (index < stack_vars_conflict_alloc);
    return stack_vars_conflict[index];
  }
!   
  /* A subroutine of expand_used_vars.  If two variables X and Y have alias
     sets that do not conflict, then do add a conflict for these variables
!    in the interference graph.  We also have to mind MEM_IN_STRUCT_P and
     MEM_SCALAR_P.  */
  
  static void
--- 272,305 ----
    gcc_assert (index < stack_vars_conflict_alloc);
    return stack_vars_conflict[index];
  }
!  
! /* Returns true if TYPE is or contains a union type.  */
! 
! static bool
! aggregate_contains_union_type (tree type)
! {
!   tree field;
! 
!   if (TREE_CODE (type) == UNION_TYPE
!       || TREE_CODE (type) == QUAL_UNION_TYPE)
!     return true;
!   if (TREE_CODE (type) == ARRAY_TYPE)
!     return aggregate_contains_union_type (TREE_TYPE (type));
!   if (TREE_CODE (type) != RECORD_TYPE)
!     return false;
! 
!   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
!     if (TREE_CODE (field) == FIELD_DECL)
!       if (aggregate_contains_union_type (TREE_TYPE (field)))
! 	return true;
! 
!   return false;
! }
! 
  /* A subroutine of expand_used_vars.  If two variables X and Y have alias
     sets that do not conflict, then do add a conflict for these variables
!    in the interference graph.  We also need to make sure to add conflicts
!    for unions of the same type.  We also have to mind MEM_IN_STRUCT_P and
     MEM_SCALAR_P.  */
  
  static void
*************** add_alias_set_conflicts (void)
*** 292,298 ****
  	{
  	  tree type_j = TREE_TYPE (stack_vars[j].decl);
  	  bool aggr_j = AGGREGATE_TYPE_P (type_j);
! 	  if (aggr_i != aggr_j || !objects_must_conflict_p (type_i, type_j))
  	    add_stack_var_conflict (i, j);
  	}
      }
--- 316,325 ----
  	{
  	  tree type_j = TREE_TYPE (stack_vars[j].decl);
  	  bool aggr_j = AGGREGATE_TYPE_P (type_j);
! 	  if (aggr_i != aggr_j
! 	      || !objects_must_conflict_p (type_i, type_j)
! 	      || (aggregate_contains_union_type (type_i)
! 		  && type_i == type_j))
  	    add_stack_var_conflict (i, j);
  	}
      }
Index: testsuite/gcc.dg/torture/pr25654.c
===================================================================
*** testsuite/gcc.dg/torture/pr25654.c	(revision 0)
--- testsuite/gcc.dg/torture/pr25654.c	(revision 0)
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do run } */
+ 
+ extern void abort (void) __attribute__((noreturn));
+ 
+ union setconflict
+ {
+   short a[20];
+   int b[10];
+ };
+ 
+ int
+ main ()
+ {
+   int sum = 0;
+   {
+     union setconflict a;
+     short *c;
+     c = a.a;
+     asm ("": "=r" (c):"0" (c));
+     *c = 0;
+     asm ("": "=r" (c):"0" (c));
+     sum += *c;
+   }
+   {
+     union setconflict a;
+     int *c;
+     c = a.b;
+     asm ("": "=r" (c):"0" (c));
+     *c = 1;
+     asm ("": "=r" (c):"0" (c));
+     sum += *c;
+   }
+ 
+   if (sum != 1)
+     abort();
+   return 0;
+ }
Index: testsuite/gcc.target/i386/pr25654-3.c
===================================================================
*** testsuite/gcc.target/i386/pr25654-3.c	(revision 0)
--- testsuite/gcc.target/i386/pr25654-3.c	(revision 0)
***************
*** 0 ****
--- 1,41 ----
+ /* { dg-do run } */
+ /* { dg-options "-O2 -mpreferred-stack-boundary=2 -march=i686 -frename-registers" } */
+ 
+ extern void abort (void) __attribute__((noreturn));
+ 
+ struct wrapper {
+ union setconflict
+ {
+   short a[20];
+   int b[10];
+ } a;
+ };
+ 
+ int
+ main ()
+ {
+   int sum = 0;
+   {
+     struct wrapper a;
+     short *c;
+     c = a.a.a;
+     asm ("": "=r" (c):"0" (c));
+     *c = 0;
+     asm ("": "=r" (c):"0" (c));
+     sum += *c;
+   }
+   {
+     struct wrapper a;
+     int *c;
+     c = a.a.b;
+     asm ("": "=r" (c):"0" (c));
+     *c = 1;
+     asm ("": "=r" (c):"0" (c));
+     sum += *c;
+   }
+ 
+   if (sum != 1)
+     abort();
+   return 0;
+ }
+ 



More information about the Gcc-patches mailing list