[Bug c/91373] gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91373 --- Comment #7 from Qiang --- Sorry to be a bother and thanks all of you. '-fsanitize=undefined' & '-fwrapv' are new item to me. '-fsanitize=undefined' is helpful to me to find out the similar issue in our code. '-fwrapv' may hide other potential issue. I'll do more check later follow the following instructions before reporting a bug: 'Before reporting that GCC compiles your code incorrectly, compile it with gcc -Wall -Wextra and see whether this shows anything wrong with your code. Similarly, if compiling with -fno-strict-aliasing -fwrapv -fno-aggressive-loop-optimizations makes a difference, or if compiling with -fsanitize=undefined produces any run-time errors, then your code is probably not correct.'
[Bug c/91373] gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91373 --- Comment #6 from Jonathan Wakely --- And Bugzilla asks you to read https://gcc.gnu.org/bugs before creating a new bug, and that page asks you to try -fsanitize=undefined to see if your code is undefined. If you'd done that you'd have been told your code is undefined.
[Bug c/91373] gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91373 --- Comment #5 from Marc Glisse --- Note that gcc (like clang) provides a tool to help you detect this kind of issue. If you compile with -fsanitize=undefined, then at runtime you will see: main.c:7:20: runtime error: signed integer overflow: 63139 * 36032 cannot be represented in type 'int'
[Bug c/91373] gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91373 --- Comment #4 from Andrew Pinski --- >If GCC need to follow rule, it should not be relative to GCC optimization. So there are two rules here getting involved. One is the implicit promoting to int. The second rule is that signed integer overflow is undefined. It is the second rule which you are running into. Gcc only takes into account the undefined behavior (at runtime) while compiling with optimization. If you want gcc to say signed integer to have defined behavior for overflow (wrapping), then you can use the -fwrapv option.
[Bug c/91373] gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91373 --- Comment #3 from Andrew Pinski --- >but it's a burden that tool need user to explicitly cast it too follow the >implicit rule, isn't it? Except that is what the language says. It is like saying a natural language rules dont need to be followed (well maybe a bad example because natural language rules are broken all the time).
[Bug c/91373] gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91373 --- Comment #2 from Qiang --- Hi Andrew, Thank your for your quickly reply. I still have some questions about this issue. It's very natural to write down the following code. All arguments are declared with 'U16', and the return type is 'U32'. U32 foo(U16 d1, U16 d2) { U32 data2 = d1 * d2; printf("data2: 0x%08x, data2 >> 31: %d, data2 >> 30: %d\n", data2, data2 >> 31, data2 >> 30); return data2; } It works under the old gcc like (gcc4.6.3 + '-O2') or VS2015. Also works under gcc5.4.0/gcc6.2.0 + '-O0'/'-O1'. But it failed under gcc5.4.0/gcc6.2.0 + '-O2'. If GCC need to follow rule, it should not be relative to GCC optimization. Why does it get different result with different optimization level? Even if there is U16 overflow issue, it's natural that user want GCC tool to take them as 'U32' argument because the return type is 'U32'. The following code works, but it's a burden that tool need user to explicitly cast it too follow the implicit rule, isn't it? U32 data2 = (U32)d1 * (U32)d2;
[Bug c/91373] gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91373 Andrew Pinski changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #1 from Andrew Pinski --- U16_0 * U16_1 Is really: ((int)(U16_0)) * ((int)(U16_1)) Due to C/C++ promption rules. Which means in this case, it overflows and since both were positive (due to u16 promoting to int) to begin with, shifting to get to the sign bit will always be 0. If you want to unsigned 32 as the type, then you need to explictly cast it.