re PR rtl-optimization/25654 (RTL alias analysis unprepared to handle stack slot sharing)

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

	PR rtl-optimization/25654
	* cfgexpand.c (aggregate_contains_union_type): New function.
	(add_alias_set_conflicts): Call it.  Make sure to add conflicts
	for structure variables that contain a union type.

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

Co-Authored-By: Jan Hubicka <jh@suse.cz>
Co-Authored-By: Richard Guenther <rguenther@suse.de>

From-SVN: r110109
This commit is contained in:
Steven Bosscher 2006-01-23 09:47:01 +00:00 committed by Richard Biener
parent 0f01f026dc
commit d239ed56ab
5 changed files with 138 additions and 4 deletions

View file

@ -1,3 +1,12 @@
2006-01-23 Steven Bosscher <stevenb.gcc@gmail.com>
Jan Hubicka <jh@suse.cz>
Richard Guenther <rguenther@suse.de>
PR rtl-optimization/25654
* cfgexpand.c (aggregate_contains_union_type): New function.
(add_alias_set_conflicts): Call it. Make sure to add conflicts
for structure variables that contain a union type.
2006-01-23 Richard Sandiford <richard@codesourcery.com>
* gengtype.c (new_structure): Return the structure.

View file

@ -272,11 +272,39 @@ stack_var_conflict_p (size_t x, size_t y)
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 have to mind MEM_IN_STRUCT_P and
MEM_SCALAR_P. */
in the interference graph. We also need to make sure to add conflicts
for union containing structures. Else RTL alias analysis comes along
and due to type based aliasing rules decides that for two overlapping
union temporaries { short s; int i; } accesses to the same mem through
different types may not alias and happily reorders stores across
life-time boundaries of the temporaries (See PR25654).
We also have to mind MEM_IN_STRUCT_P and MEM_SCALAR_P. */
static void
add_alias_set_conflicts (void)
@ -287,12 +315,23 @@ add_alias_set_conflicts (void)
{
tree type_i = TREE_TYPE (stack_vars[i].decl);
bool aggr_i = AGGREGATE_TYPE_P (type_i);
bool contains_union;
contains_union = aggregate_contains_union_type (type_i);
for (j = 0; j < i; ++j)
{
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))
if (aggr_i != aggr_j
/* Either the objects conflict by means of type based
aliasing rules, or we need to add a conflict. */
|| !objects_must_conflict_p (type_i, type_j)
/* In case the types do not conflict ensure that access
to elements will conflict. In case of unions we have
to be careful as type based aliasing rules may say
access to the same memory does not conflict. So play
safe and add a conflict in this case. */
|| contains_union)
add_stack_var_conflict (i, j);
}
}

View file

@ -1,3 +1,11 @@
2006-01-23 Steven Bosscher <stevenb.gcc@gmail.com>
Jan Hubicka <jh@suse.cz>
Richard Guenther <rguenther@suse.de>
PR rtl-optimization/25654
* gcc.dg/torture/pr25654.c: New testcase.
* gcc.target/i386/pr25654.c: Likewise.
2005-01-23 Paul Thomas <pault@gcc.gnu.org>
PR fortran/25901

View file

@ -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;
}

View file

@ -0,0 +1,41 @@
/* { dg-do run { target ilp32 } } */
/* { 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;
}