https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103699

--- Comment #7 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Petr from comment #6)
> For now I have disabled unaligned load/store optimizations in my projects
> when dealing with GCC 11 and upwards.

As I mentioned you could just add the may_alias attribute and it will work too.
You were just lucky that you only ran into this issue for GCC 11 really

> I still think that GCC is wrong in this case regardless of strict aliasing.
> The code in func_u32() is essentially creating a constant, and GCC 11+ is
> the only compiler returning it wrong and also inconsistently between
> optimization levels.

No you are still violating C/C++ aliasing rules. No matter what you think. It
is undefined behavior.
Strict aliasing is only enabled for -O2 and above which is why it might look
inconsistent. Plus since it is undefined behavior different optimizations level
will always have different behavior.

Again the following code:
    uint8_t array[16] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    writeU64be(array + 6, 0xAABBCCDDEEFF1213);
    return readU32be(array + 7);

Which does basically:
    uint8_t array[16] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    *(unsigned long*)(array+6) = __builtin_bswap64(0xAABBCCDDEEFF1213);
    return *(unsigned*)(array+7);

is undefined as you write to array+6 as an unsigned long but then read array+7
as an unsigned type. 

Plus aligned(1) attribute has nothing to do with the issue here:
Take:
static unsigned g(unsigned *a)
{
    return *a;
}

unsigned f(void)
{
    unsigned char array[16] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    *(unsigned long*)(array) = __builtin_bswap64(0xAABBCCDDEEFF1213);
    return g((unsigned*)(array));
}
----- CUT ---
Compile it with -O2  -fno-early-inlining and you will same bad results as you
had got with aligned.

Reply via email to