https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91645
Bug ID: 91645 Summary: Missed optimization with sqrt(x*x) Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: lisyarus at gmail dot com Target Milestone: --- Based on a discussion on stackoverflow: https://stackoverflow.com/questions/57673825/how-to-force-gcc-to-assume-that-a-floating-point-expression-is-non-negative. With gcc-trunk and '-std=c++17 -O3', the function float test (float x) { return std::sqrt(x*x); } produces the following assembly: test(float): mulss xmm0, xmm0 pxor xmm2, xmm2 ucomiss xmm2, xmm0 movaps xmm1, xmm0 sqrtss xmm1, xmm1 ja .L8 movaps xmm0, xmm1 ret .L8: sub rsp, 24 movss DWORD PTR [rsp+12], xmm1 call sqrtf movss xmm1, DWORD PTR [rsp+12] add rsp, 24 movaps xmm0, xmm1 ret As far as I can tell, it calls sqrtf, unless the argument to sqrt is >= 0, to check for negatives/NaN's and set the appropriate errno. The behavior is reasonable, as expected. Adding '-fno-math-errno', '-ffast-math', or '-ffinite-math-only' removes all the clutter and compiles the same code into the neat test(float): mulss xmm0, xmm0 sqrtss xmm0, xmm0 ret Now, the problem is that GCC doesn't seem to optimize away the call to sqrtf based on some surrounding code. As an example, it would be neat to have this (or something similar) to get compiled into the same mulss-sqrtss-ret: float test (float x) { float y = x*x; if (y >= 0.f) return std::sqrt(y); __builtin_unreachable(); } If I understand it correctly, the 'y >= 0.f' excludes 'y' being NaN and 'y' being negative (though this is excluded by 'y = x*x'), so there is no need to check if the argument to `std::sqrt` is any bad, enabling to just do 'sqrtss' and return. Furthemore, adding e.g. '#pragma GCC optimize ("no-math-errno")' before the 'test' function doesn't lead to optimizing it either, though I'm not sure whether this is expected to work and/or requires a separate bugtracker issue.