[Bug c/91373] gcc6.2.0: ((U32)((U16 * U16)) >> 31) cannot always get correct result with gcc -O2

2019-08-06 Thread qiang.fu at verisilicon dot com
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

2019-08-06 Thread redi at gcc dot gnu.org
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

2019-08-06 Thread glisse at gcc dot gnu.org
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

2019-08-06 Thread pinskia at gcc dot gnu.org
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

2019-08-06 Thread pinskia at gcc dot gnu.org
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

2019-08-06 Thread qiang.fu at verisilicon dot com
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

2019-08-05 Thread pinskia at gcc dot gnu.org
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.