<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/108232>108232</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
C++: Incorrect optimization regarding strict-aliasing rules
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
naprimeroleg
</td>
</tr>
</table>
<pre>
#include <memory>
void foo( void* a, void* b, int cond)
{
short* pa = new(a) short;
// store (1)
*pa = 1;
if ( cond ) { return; }
int* pb = new(b) int;
// store (2)
*pb = 2;
short* pa2 = new(a) short;
// store (3)
*pa2 = 1;
}
https://godbolt.org/z/qh6P3Ps8e
In this example, clang compiler optimized away the last store (3):
foo(void*, void*, int):
mov word ptr [rdi], 1
test edx, edx
je .LBB0_1
ret
.LBB0_1:
mov dword ptr [rsi], 2
ret
Supposedly, the compiler used strict-aliasing rules here.
However, this optimization is incorrect. The situation may be as follows. Suppose we have some storage,
and arguments a==b both point to this storage. In our function "foo", we
- at first, create object of type "short" in this storage (storing the value "1")
- then, we create the object of type "int" and store the value "2"; the previous object's life is implicitly ended (it has no destructor)
- finally, we create the object of type "short" (again storing the value "1"); again, the previous object's life is ended.
So, the last store cannot be eliminated.
Gcc and msvc compilers keep this store (they don't optimize it out)
Note, that according to the C++-standard:
"6.6.3 Object lifetime
...
4
The properties ascribed to objects and references throughout this document
apply for a given object or reference only during its lifetime..."
So the strict-aliasing rules also can be applied only to objects which live simultaneously.
If the behaviour of Clang were correct (objects lifetime not taken into account in strict-aliasing analysis),
then it would be impossible to correctly write user-defined allocators (like boost.allocator), where the
same memory storage is reused for different user objects and for own allocator data.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUVl2P4joS_TXmpdQInKaBBx6aZtltabU70sz7lRNXiGccV65dIcP8-ivbIUDPaK4uDwng-jhV51QlKgRzcog7sdqL1WGmem7I75zqvGnRk8XTrCR92QlZGFfZXiOI4q3FlvxFFP8Si4NYvJ7JaKiJhNxA_C7kKygh36YfZfxhHENFTgu5zW5ivc9fAABCQ56jbadAFAdwOAi5UUJux6PizljIo5BHCEweQcjNcooJQr6OEZYPLqaOhgkAxKBivQeP3Hsnij2I9eHO1GUg5R2QMvrEgynmRwzyhiEhfB395QOMuzLlP6-z-CnHGOVW61RJvjbMXRDFa450Il2S5Tn5k5DHH0Ie_2xePhWfwgbvnd4dcGMC4HfVdhYjeZVV7gQVtZ2x6IE6Nq35gRrUoC7ADYJVgT8gLcZ4WRqjGO50Mari3hRaOsfaYCCvoWMPYrX32ojVIVovb9XHD2PgeEf9PZ7G28P5V4T5f_f7xR8f_Dxy_uN6OqUfP1cU-gFGuMKQo_UUJ18_911HAbW9RKPYlKlhfUANgb2p-ElZo4JxJ_C9xQANepznAP-hAc_os7cJ1zYrNuTABDCuIu-x4jl8aRCC4T6fteoCJYIKUJO1NIQ5jGBgQGjUGSFQi4kfdYqM5oTKaVD-1LfoOIASxUEUhxJK4gY6ihPLlKGMnnN4d0C9h7p3VUotpEz8yoh6GHX0BIqhNj5wEo9HxQhUfsWKgWrgSxdVIsdpkGDcQ5aooPg1Nim28axsnxyWKc_2moQbdDntNUe0_jlPEpmEWG1W6ENQGYMW-_Rn5_FsqA9jECHXAaypMXW_7aypDNsLoNMY98jGMDQqgCPQGNj3FZO_A1gbp2yWw99hnHoR18FJGQe_7UCxh2R1VdrvgCe0o8Q-09XjbmAr5RxxVBBa0xqneLLP139XVepeG87VJOoA3xC7G3GJNm7wApqckGue1gQYBur5tvnT9X_EmMEoBlVV5HUqlxK8NyH3Qu6fAiunldfTjAopX-Yv8wL-n3sYq2TTjsqbz0fgz_n2JfWGOvRsMIAKlTcl6pgldyqkwjzW6NFVGIAbT_2poZ5zaZqqNB_jxHSdvUBNHhSczBndRKW_BQFy9gK6T_QZDhPGiE7KKxOpzl8vBWUDRVrSVHedNahz0DvcQ2OqBqyJw23a3rJySH2wlwfq3uuUpsRGRYH4qLm3tM0HjNTnhRKpu8a9goWoCVbf0MUtTYmi3jEkaT6CVk7ZSzAhMnzdLXE4I_ED9VbHOkzbUQimtBirGBPbCwzeMMYN6Z801sbFp4q1VCkmHyIwa74hlESB59NBzgRD3J6xwJwzqBYhv51Mu8QE8Jj2b2RNmzqRxCnhgwbiMQ3ulhy0YjU2c6Z3hd4WWzXD3XItXxYvxUauZ81OK7XE9bNc6Xr9rKr1Yi2rxbZel3qrNitZz8xOLuTzYrtcLp-XC_ky13q70nqr6mK1rtZFKZ4X2Cpj59ae2_hsnpkQetwtFxtZyJlVJdqQ3tCkdDhAOo0yWh1mfhednsr-FMTzwprA4RaGDVvcjYMkild4vz4_Hp8sHk8qz94vxTjrvd19eJEw3PTlvKJWyGPMN96eOk95_RwTyiDkcSzjvJN_BQAA__9xoEir">