
Wrong optimization with aliasing - luu
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69776
======
nmc
TL;DR: the bug is due to GCC's optimization feature called full redundancy
elimination (FRE).

It treats "int a=* pi; * pi=a" as a redundant store and removes it, as
explained in the 5th comment:

[https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69776#c5](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69776#c5)

------
sharpneli
I is not wrong optimization. The guy is explicitly breaking the C
specification by doing that.

The correct way of accessing a variable like that is trough an union. Here is
an example [http://pastebin.com/8V3whcL3](http://pastebin.com/8V3whcL3)

Alternatively one can make both of them as volatile. That will basically force
the compiler do all the loads and stores.

I really hate it when people write code that breaks the spec and then
complains to the compiler maker. And now they actually changed the compiler to
work with the code that is simply wrong.

Just as what happened with glibc memcpy (works like memmove due to people not
knowing what they are doing and then crying for the libraries to change their
behaviour to match their own incompetence).

~~~
pascal_cuoq
> The correct way of accessing a variable like that is trough an union.

It's funny you should say that, because people have been taking the exact
opposite viewpoint for years: “union do not allow type-punning because it was
only clarified in TC3 of C99 that they do. memcpy has always been the correct
way to type-pun.”

The bug reporter is referring to the rules described in 6.5:6 and 6.5:7 of C11
(the same rules are included in C99, but interestingly not in C90, meaning
that “gcc -std=c90” should go theoretically easy with the type-based
optimizations. It doesn't). Here is a link:
[http://port70.net/~nsz/c/c11/n1570.html#6.5p6](http://port70.net/~nsz/c/c11/n1570.html#6.5p6)

And an excerpt for your convenience:

If a value is copied into an object having no declared type using memcpy or
memmove, or […], then the effective type of the modified object for that
access and for subsequent accesses that do not modify the value is the
effective type of the object from which the value is copied, if it has one

How do you interpret the above paragraph?

~~~
maxlybbert
I've been under the impression that unions don't truly allow type punning, but
given that the practice was widespread (e.g., it was used in the code Protocol
Buffers generated a few years ago), it was a pretty safe bet compilers would
support it as an extension.

I was also under the impression that the One True Way to type pun was to cast
to char*, which is allowed to alias, and then cast again to the type you
actually want.

~~~
asgfoi
_I was also under the impression that the One True Way to type pun was to cast
to char_ , which is allowed to alias, and then cast again to the type you
actually want.*

That clearly doesn't work, but I can see from a naive perspective why some
think that. It feels like a nice hack, but a cast to char* doesn't "remove"
the original type.

To be clear: char* can alias any type, but only char* can alias char*.

------
greglindahl
-fstrict-aliasing is on by default in gcc at -O2 and above. I'm surprised that the bug discussion doesn't mention that.

The PathScale compiler had a fair number of customers who complained about
"bugs" that went away with -fnostrict-aliasing. We told them to use
-fnostrict-aliasing.

~~~
Too
I think it's quite obvious strict aliasing is implied in this case. The bug is
than _even with strict aliasing_ he should get the result he wants, because
the last time he wrote to the pointer before reading it as an int he wrote it
as an int and hence it should keep the int-value 1.

Having that said, balancing aliasing like this is just asking for trouble,
don't try this at home.

EDIT: The more i look at it the more i think he is wrong. Since pi and pd
_shouldn 't_ be able to alias, the last assignment to both of them is allowed
to reorder. This is just UB.

------
amelius
I wonder why this wasn't caught by the extensive set of regression tests of
GCC.

~~~
anon4
Because they don't think it's a regression, it's working as intended.

~~~
tetromino_
No, apparently a gcc developer agreed that there was a regression and it
wasn't working as intended. They've just fixed a reduced test case [1],
although according to the original reporter, there remains an additional
problem to be fixed.

[1]
[https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=23341...](https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=233418)

