This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][RFC] Fix PR38806, wrong TBAA pruning with unions
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 11 Jan 2009 18:22:18 +0100 (CET)
- Subject: [PATCH][RFC] Fix PR38806, wrong TBAA pruning with unions
I believe that GCC specifies that
union U { float f; int i; };
int main()
{
int i;
union U *u = (union U *)&i;
i = 1;
u->f = 0.0;
if (i != 0)
abort ();
return 0;
}
does not abort (at least that is what comments throughout
the GCC source suggest. For example:
/* If strict aliasing applies the only way to access a scalar variable
is through a pointer dereference or through a union (gcc extension). */
invoke.texi specifies
"
Similarly, access by taking the address, casting the resulting pointer
and dereferencing the result has undefined behavior, even if the cast
uses a union type, e.g.:
@smallexample
int f() @{
double d = 3.0;
return ((union a_union *) &d)->i;
@}
"
as a recent addition. Does this cover the case above? Is the only
type-punning we allow really
union.a = x;
y = union.b;
? In this case c_common_get_alias_set should not need to return 0
for unions either:
/* Permit type-punning when accessing a union, provided the access
is directly through the union. For example, this code does not
permit taking the address of a union member and then storing
through it. Even the type-punning allowed here is a GCC
extension, albeit a common and useful one; the C standard says
that such accesses have implementation-defined behavior. */
for (u = t;
TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;
u = TREE_OPERAND (u, 0))
if (TREE_CODE (u) == COMPONENT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
return 0;
Sigh, this exception always confuses me!
Richard.
2009-01-11 Richard Guenther <rguenther@suse.de>
PR tree-optimization/38806
* tree-ssa-structalias.c (may_alias_p): Do not do false pruning
on pointer-to-union points-to sets.
* gcc.c-torture/execute/20090111-1.c: New testcase.
* gcc.dg/tree-ssa/20030807-7.c: XFAIL again.
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c (revision 143251)
--- gcc/tree-ssa-structalias.c (working copy)
*************** may_alias_p (tree ptr, alias_set_type me
*** 4743,4749 ****
/* If the alias sets don't conflict then MEM cannot alias VAR. */
if (mem_alias_set != var_alias_set
! && !alias_set_subset_of (mem_alias_set, var_alias_set))
return false;
return true;
--- 4743,4754 ----
/* If the alias sets don't conflict then MEM cannot alias VAR. */
if (mem_alias_set != var_alias_set
! && !alias_set_subset_of (mem_alias_set, var_alias_set)
! /* If the pointer points to a union then we have to allow
! GCCs union type-punning extension. */
! && ((TREE_CODE (TREE_TYPE (TREE_TYPE (ptr))) != UNION_TYPE
! && TREE_CODE (TREE_TYPE (TREE_TYPE (ptr))) != QUAL_UNION_TYPE)
! || !alias_set_subset_of (var_alias_set, mem_alias_set)))
return false;
return true;
Index: gcc/testsuite/gcc.c-torture/execute/20090111-1.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/20090111-1.c (revision 0)
--- gcc/testsuite/gcc.c-torture/execute/20090111-1.c (revision 0)
***************
*** 0 ****
--- 1,19 ----
+ union U { float f; int i; };
+
+ /* GCC says the access through the union does alias the bare variable. */
+ int foo(union U *u, int *i)
+ {
+ *i = 1;
+ u->f = 0.0;
+ return *i;
+ }
+
+ extern void abort (void);
+ int main()
+ {
+ int i;
+ if (foo ((union U *)&i, &i) != 0)
+ abort ();
+ return 0;
+ }
+
Index: gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c (revision 143273)
--- gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c (working copy)
*************** simplify_condition (cond_p)
*** 33,37 ****
}
/* There should be exactly one IF conditional. */
! /* { dg-final { scan-tree-dump-times "if " 1 "vrp1" } } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */
--- 33,37 ----
}
/* There should be exactly one IF conditional. */
! /* { dg-final { scan-tree-dump-times "if " 1 "vrp1" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */