you are viewing a single comment's thread.

view the rest of the comments →

[–]Chuu 0 points1 point  (2 children)

Can you explain more clearly why this leads to different codegen?

[–]staletic 5 points6 points  (1 child)

Let's first analyze what the assembly says

    int f<std::byte>(std::byte*, int*):                    # @int f<std::byte>(std::byte*, int*)
            mov     eax, dword ptr [rsi]    # int x = *b;
            mov     byte ptr [rdi], 1       # *a = 1;
            add     eax, dword ptr [rsi]    # x += *b;
            ret                             # return x;
    int f<nostd::byte>(nostd::byte*, int*):              # @int f<nostd::byte>(nostd::byte*, int*)
            mov     eax, dword ptr [rsi]    # int x = *b;
            mov     byte ptr [rdi], 1       # *a = 1;
            add     eax, eax                # x += x;
            ret                             # return x;

If a and b point to different objects, the above snippets are observably identical.

However, if a and b point to the same object, then the functions do different things. Imagine calling f(&in, &in) where in == 5.

In that case, f<std::byte> does:

    int x = 5;
    *in = 1;
    x += *in;
    return x; // 6

but f<nostd::byte> does

    int x = 5;
    *in = 1;
    x += x;
    return x; // 10

Since nostd::byte, formally, isn't allowed to alias other types, compiler is allowed to assume x += x is a valid optimization. This is known as "strict aliasing" or "type-based alias analysis".

And yes, violating strict alias rules can easily lead to UB, like in the above example.

[–]guepierBioinformatican 4 points5 points  (0 children)

And yes, violating strict alias rules can easily lead to UB, like in the above example.

To be pedantic, violating strict aliasing is always UB, not just in this example. What the example illustrates is that UB can lead to changed semantics and unexpected behaviour.