public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug tree-optimization/61876] New: Converting __builtin_round + cast into __builtin_lround is not always equivalent in regards to math errno
@ 2014-07-22 11:08 ktkachov at gcc dot gnu.org
  2014-07-22 11:11 ` [Bug middle-end/61876] " ktkachov at gcc dot gnu.org
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: ktkachov at gcc dot gnu.org @ 2014-07-22 11:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61876

            Bug ID: 61876
           Summary: Converting __builtin_round + cast into
                    __builtin_lround is not always equivalent in regards
                    to math errno
           Product: gcc
           Version: 4.10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org

Consider code:

long int
foo (double a)
{
   return __builtin_round (a);
}

With an aarch64-none-elf toolchain this compiles to:
foo:
        fcvtas  x0, d0
        ret
whereas with an aarch64-linux toolchain this compiles to:
foo:
        b       lround

The linux (glibc) toolchain does not inline the lround implementation.

The suspicious starting point is this code in convert.c:
        CASE_FLT_FN (BUILT_IN_ROUND):
          /* Only convert in ISO C99 mode.  */
          if (!targetm.libc_has_function (function_c99_misc))
            break;
          if (outprec < TYPE_PRECISION (integer_type_node)
              || (outprec == TYPE_PRECISION (integer_type_node)
                  && !TYPE_UNSIGNED (type)))
            fn = mathfn_built_in (s_intype, BUILT_IN_IROUND);
          else if (outprec == TYPE_PRECISION (long_integer_type_node)
                   && !TYPE_UNSIGNED (type))
            fn = mathfn_built_in (s_intype, BUILT_IN_LROUND);
          else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
                   && !TYPE_UNSIGNED (type))
            fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND);
          break;
Basically it does the conversion of (cast to long int + round) == lround
But later on in builtins.c the lround does not get expanded into the sfix optab
unless -fno-math-errno is specified:

  /* There's no easy way to detect the case we need to set EDOM.  */
  if (!flag_errno_math)
    {
      rtx result = gen_reg_rtx (mode);

      /* Wrap the computation of the argument in a SAVE_EXPR, as we may
         need to expand the argument again.  This way, we will not perform
         side-effects more the once.  */
      CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg);

      op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL);

      start_sequence ();

      if (expand_sfix_optab (result, op0, builtin_optab))
        {
          /* Output the entire sequence.  */
          insns = get_insns ();
          end_sequence ();
          emit_insn (insns);
          return result;
        }

I think if the cast+round -> lround transformation is done it should be assumed
in that case that lround will not set errno.

Another approach would be to not do the transformation unless -fno-math-errno


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2014-08-05  9:58 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-22 11:08 [Bug tree-optimization/61876] New: Converting __builtin_round + cast into __builtin_lround is not always equivalent in regards to math errno ktkachov at gcc dot gnu.org
2014-07-22 11:11 ` [Bug middle-end/61876] " ktkachov at gcc dot gnu.org
2014-07-23 12:19 ` rguenth at gcc dot gnu.org
2014-07-23 13:04 ` ktkachov at gcc dot gnu.org
2014-07-24 13:23 ` ktkachov at gcc dot gnu.org
2014-07-24 13:29 ` ktkachov at gcc dot gnu.org
2014-07-24 21:12 ` joseph at codesourcery dot com
2014-07-25  9:07 ` ktkachov at gcc dot gnu.org
2014-07-25  9:09 ` mpolacek at gcc dot gnu.org
2014-07-25 13:45 ` joseph at codesourcery dot com
2014-08-05  9:53 ` ktkachov at gcc dot gnu.org
2014-08-05  9:58 ` ktkachov at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).