This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/70166] Wrong optimization of type punning in unions with 2d array
- From: "ch3root at openwall dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 11 Mar 2016 14:20:50 +0000
- Subject: [Bug c/70166] Wrong optimization of type punning in unions with 2d array
- Auto-submitted: auto-generated
- References: <bug-70166-4 at http dot gcc dot gnu dot org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70166
--- Comment #2 from Alexander Cherepanov <ch3root at openwall dot com> ---
On 03/11/2016 12:16 PM, rguenth at gcc dot gnu.org wrote:
> You are not accessing through the union type but through a pointer to double
> and int because u.a and p->d decay to a pointer:
>
> *(int *) &u.a = 1;
> *(double *) &p->d = 0.0;
> if (*(int *) &u.a != 0)
> {
> abort ();
This is true but I'm afraid it doesn't explain anything.
First of all, some data points:
- the example works fine with 1d array;
- the example works fine with **u.a replaced by u.a[0][0], *u.a[0] or
(*u.a)[0];
- the example fails in the same way with u.a and p->d wrapped in structs.
In all these cases u.a and p->d decay to a pointer too but gcc does the
right thing anyway. Furthermore, saying that the problem is in
array-to-pointer decay means that arrays inside unions (including
recursively) cannot be accessed directly at all (they would work only
wrapped in structs and copied in and out inside these structs). I guess
this is not intended and arrays inside unions are supposed to work somehow.
Ok, let's change if to "if (**u.a != (*u.a)[0])" and do -fdump-tree-all.
In 003t.original we have this:
*(int *) &u.a = 1;
*(double *) &p->d = 0.0;
if (*(int *) &u.a != (*(int[1] *) &u.a)[0])
{
abort ();
and in 004t.gimple we have this:
D.1636 = &u.a;
D.1639 = MEM[(int *)D.1636];
D.1640 = u.a[0][0];
if (D.1639 != D.1640) goto <D.1641>; else goto <D.1642>;
<D.1641>:
abort ();
It seems the general direction is to convert * to [] but gcc fails to
convert **. Different treatment of **x and x[0][0] is not limited to
unions in any way. In other cases I guess it will just prevent some
optimizations but with unions it has a user-visible effect.