[Bug c/91373] New: 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 Bug ID: 91373 Summary: gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2 Product: gcc Version: 6.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: qiang.fu at verisilicon dot com Target Milestone: --- Created attachment 46676 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46676&action=edit main.c Hi, I met an issue with gcc6.2.0: ((U16 * U16) >> 31) cannot always get expected result for gcc optimization switch '-O2'. e.g. (63139 * 36032) >> 30 = 0x2 // right (63139 * 36032) >> 31 = 0x0 // wrong, should be 0x1. I create a test case for it, see the attachement(main.c). It passed on gcc 4.6.3, but failed with gcc6.2.0 + release build(gcc -O2) gcc -O2 main.c -o test ./test 63139 36032 data1: 0x879a1e40, data1 >> 31: 1, data1 >> 30: 2 data2: 0x879a1e40, data2 >> 31: 0, data1 >> 30: 2 This test passed if build with -O0 or -O1 with gcc6.2.0 GCC version: 6.2.0 * gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/6.2.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ../configure -enable-checking=release -enable-languages=c,c++ -disable-multilib Thread model: posix gcc version 6.2.0 (GCC)
[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 --- 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.'