From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 071E63848012; Wed, 24 Feb 2021 01:07:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 071E63848012 From: "vz-gcc at zeitlins dot org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/99234] New: Regression: wrong result for 1.0/3.0 when -fno-omit-frame-pointer -frounding-math used together Date: Wed, 24 Feb 2021 01:07:16 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 10.2.1 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: vz-gcc at zeitlins dot org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Feb 2021 01:07:17 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D99234 Bug ID: 99234 Summary: Regression: wrong result for 1.0/3.0 when -fno-omit-frame-pointer -frounding-math used together Product: gcc Version: 10.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: vz-gcc at zeitlins dot org Target Milestone: --- Please see the following test case minimized by cvise: ---------------------------------- >8 -------------------------------------- // When compiled with // // g++ -Wall -O2 -fno-omit-frame-pointer -frounding-math test.cpp // // using x86_64-w64-mingw32-g++ version 10-win32 20210110 (GCC) from Debian // g++-mingw-w64-x86-64-win32 10.2.1-6+24.1 package or gcc version 10.2.0 // (Rev6, Built by MSYS2 project) this test case computes a wrong result for // the second division below. #include #include #include #include double numeric_io_cast(const std::string& from) { char* rendptr; double value =3D std::strtod(from.c_str(), &rendptr); if('\0' !=3D *rendptr) throw std::logic_error(""); return value; } double numeric_io_cast(char const* from) { return numeric_io_cast(std::string(from)); } int main(int, char* []) { std::printf("1.0 / 3.0 =3D %f\n", 1.0 / 3.0); // =3D> 1.0 / 3.0 =3D 0.3= 33333 try { numeric_io_cast(""); numeric_io_cast("1e"); } catch(std::logic_error const&) { } std::printf("1.0 / 3.0 =3D %f\n", 1.0 / 3.0); // =3D> 1.0 / 3.0 =3D 0.0= 00000 return 0; } ---------------------------------- >8 -------------------------------------- The comments in the code indicate the output produced when using MinGW gcc 10.2. The same code worked fine with different versions of gcc 8 and also w= orks when using native Linux gcc 10.2.1. It always works fine for 32 bit compiler (which produces completely different code). Also, just in case it can be helpful (even though I'm afraid it isn't...), = it the problem disappears when using the 10.x compilers mentioned above if eit= her of the following is true: 1. You use -O0 or -O3 (but it gives the same results with -O1 and -O2). 2. You don't use -fno-omit-frame-pointer. 3. You don't use -frounding-math. 4. You use 2.0, 4.0 or 8.0 instead of 3.0 (but it fails similarly with 5.0,= 7.0 etc). 5. You use something other than std::logic_error (or a class derived from it such as std::invalid_argument), i.e. throwing a simple class, even deriving from std::exception, makes the problem disappear. 6. You remove the (clearly unnecessary!) numeric_io_cast() overload taking char* and rely on implicit conversion doing the same thing. Looking at the generated code the problem seems relatively clear: the compi= ler assumes the xmm register containing the result is preserved when it's clobbered. But I have no idea where to start looking in gcc to find why doe= s it assume this and how to fix this. I'd also like to note that IMO it's a pretty bad bug because it silently results in completely wrong behaviour in the code which worked perfectly we= ll before and, of course, it took quite some time before we actually found what was going on and why did the tests suddenly start failing in "impossible" w= ays after upgrading to MinGW 10.=