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.

Reply via email to