> -----Ursprüngliche Nachricht----- > Von: Alexander Monakov <amonakov@xxxxxxxxx> > Gesendet: Mittwoch, 10. April 2024 11:17 > An: stefan@xxxxxxxxx > Cc: gcc-help@xxxxxxxxxxx > Betreff: Re: optimizer discards sign information > > > On Wed, 10 Apr 2024, stefan@xxxxxxxxx wrote: > > > Hi all, > > > > I just stumbled over an issue, which is present in almost all gcc versions. > > I worked around using inline assembly… Maybe gcc behaves correct and I > > am wrong? Here is the code: > > > > https://godbolt.org/z/cW8jcdh56 > > > > typedef unsigned long long int u64; > > typedef unsigned int u32; > > typedef unsigned short u16; > > > > u64 foo(u16 a, u16 b) { > > u32 x = a * b; > > u64 r = x; > > return r; > > } > > > > And on gcc 13.2 x86.64 you get > > > > foo: > > movzx esi, si > > movzx edi, di > > imul edi, esi > > movsx rax, edi > > ret > > > > > > There is a sign extension! The optimizer step discards the information > > > > x_6 = (u32) _3; > > > > and uses _3 directly instead, which is signed. > > > > Am I wrong or is it gcc? > > GCC is not wrong. When your code computes x: > > u32 x = a * b; > > 'a' and 'b' are first promoted to int according to C language rules, and the > multiplication happens in the signed int type, with UB on overflow. > The compiler deduces the range of signed int temporary holding the result of > the multiplication is [0, 0x7fffffff], which allows to propagate it to the > assignment of 'r' (which in the end produces a sign extension, as you > observed, so the propagation did not turn out to be useful). > > u16 * u16 is a famous footgun for sure. I'd suggest 'x = 1u * a * b' > as a fix for the code. > > Alexander Thank you for the fix 😊 I considered u32 x = a * b; as good enough, since from my understanding, x *is* unsigned. Adding the multiplication with 1u resolves this. regards Stefan