[Bug tree-optimization/91645] Missed optimization with sqrt(x*x)

rguenther at suse dot de gcc-bugzilla@gcc.gnu.org
Thu Sep 5 09:19:00 GMT 2019


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.


More information about the Gcc-bugs mailing list