[Bug c++/79373] New: For loop optimization bug: condition ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79373 Bug ID: 79373 Summary: For loop optimization bug: condition ignored Product: gcc Version: 5.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: steven.p.pigeon at gmail dot com Target Milestone: --- Created attachment 40668 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40668&action=edit Collected data for bug (followed collection instructions) The condition in the following for-loop is ignored when the following program is optimized with -O3: for (int i=-32768; i<32768; i++) { int w=wstream::_16_to_24(i); int j=wstream::_24_to_16(w); if (i!=j) std::cout << " failed on: " << i << " = " << j << std::endl; } with functions (in class wstream) static int32_t _16_to_24(int16_t x) { int32_t t=x; t+=(1u<<15); t*=65793; t/=256; return t-(1u<<23); } static int16_t _24_to_16(int32_t x) { return ((x+(1u<<23))*257)/65793-(1u<<15); } with *no* side-effects. Program works properly when optimizations are disabled (-O0), or functions modified slightly (ignore the fact that both function aren't exactly inverse of each other). Attached is an archive with full program, Makefile used to generate code, and collected information as directed for a bug report (gcc -v -save-temps ...).
[Bug c++/79373] For loop optimization bug: condition ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79373 --- Comment #2 from Steven Pigeon --- (In reply to Andrew Pinski from comment #1) > I am suspecting this: > t*=65793; > > overflows. > > Can you try with -fsanitize=undefined ? The bug disappears with g++ -fsanitize=undefined -O3 -std=c++11 test-wave-stream.cpp Yes, it overflows for some values (and is undefined behavior?). But it shouldn't affect the for-loop. At worse, the returned values should be random-looking and the unit test should fail with a message.
[Bug c++/79373] For loop optimization bug: condition ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79373 --- Comment #5 from Steven Pigeon --- The problem is not the function that overflows. It's the loop that calls them that never stops. I don't see how that's "resolved": the overflow in the function should not affect the loop that calls it.
[Bug c++/79373] For loop optimization bug: condition ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79373 --- Comment #7 from Steven Pigeon --- (In reply to Andrew Pinski from comment #6) > Once undefined behavior happens all bets are off of any behavior of the > program. > > In this case the function is in lined and the optimizers see i cannot > overflow the multiply so it removes the loop check. I do understand that this is what happens (the code is fixed by promoting int32_t t=x to int64_t t=x) but the undefined behavior affects a variable (and its associated comparison) that should not be affected by it. It's as if this program int32_t f(int16_t x) { return x*65793; } for (int i=-32768; i<32768; i++) std::cout << f(i) << std::endl; would just never stop. Would that be expected?
[Bug c++/79373] For loop optimization bug: condition ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79373 --- Comment #10 from Steven Pigeon --- (In reply to Jonathan Wakely from comment #9) > (In reply to Steven Pigeon from comment #7) > > I do understand that this is what happens (the code is fixed by promoting > > int32_t t=x to int64_t t=x) but the undefined behavior affects a variable > > (and its associated comparison) that should not be affected by it. > > The C++ standards defines undefined behavior as "behavior for which this > International Standard imposes no requirements". No requirements. Not > "doesn't affect things that you think shouldn't be affected". All bets are > off. > > There is no requirement for a compiler to do something you find > unsurprising, or to limit the scope of the bug to parts of the code you > expect to misbehave. That's somewhat disconcerting, as some programs do rely on "expected undefined behavior". For example, val = ((state[0] * 1103515245) + 12345) & 0x7fff; (found in http://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/random_r.c;hb=glibc-2.15#l375 ) will overflow (because if I understand correctly, in an int times int operation, neither operands are promoted to a larger int type, and if overflow occurs, it's undefined behavior). Should that mess up the program in unpredictable ways? I'm trying to understand what exactly I'm fighting in order to avoid further problems.