https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91645
--- Comment #6 from rguenther at suse dot de <rguenther at suse dot de> --- On Thu, 5 Sep 2019, lisyarus at gmail dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91645 > > --- Comment #5 from Nikita Lisitsa <lisyarus at gmail dot com> --- > Oh, thank you a lot! Indeed, this version compiles to just mulss & sqrtss > > float test (float x) > { > float y = x*x; > if (std::isless(y, 0.f)) > __builtin_unreachable(); > return std::sqrt(y); > } > > Yet, I still don't quite understand what is happening here. Is it because the > standard '<' operator is still subject to FE_* ? It's probably because our jump-threading is imperfect if I interpret Marcs comment correctly. When seeing LE_EXPR we only consider if (FLOAT_TYPE_P (TREE_TYPE (op0))) { build_and_record_new_cond (ORDERED_EXPR, op0, op1, p); } so we know it's ORDERED but we don't register it's known to be UNLE as well. > Concerning pragmas, the code > > #pragma GCC optimize ("no-math-errno") > float test (float x) > { > return std::sqrt(x*x); > } > > produces the following assembly > > std::sqrt(float): > pxor xmm2, xmm2 > movaps xmm1, xmm0 > ucomiss xmm2, 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 > test(float): > mulss xmm0, xmm0 > jmp std::sqrt(float) > > So, the only notable difference is that now 'std::sqrt(float)' is not inlined, > but is tail-called instead. Thus, the pragma seems not to work? True, there may already be a bug about this. The issue is that whether functions set errno or not is decided globally and this info isn't changed between functions according to pragmas.