Hi Richard,
> > This is my proposed solution to PR middle-end/123826.  Initially I
> > thought this would be a "one line change", adding a test for
> > flag_errno_math to gimple_expand_builtin_pow.  Unfortunately this
> > revealed a second later problem, where pow (with constant
> > arguments) was still getting evaluated at compile-time, even when the
> > result is known to overflow.
> >
> > It's ancient history, but shortly after I added support for pow as a
> > builtin, I contributed code to evaluate it at compile-time when the
> > exponent is an integer constant.  Since then we now use MPFR to
> > evaluate libm math functions at compile-time.  However the vestigial
> > call to evaluate pow via real_powi still exists, and gets invoked
> > after do_mpfr_arg2/mpfr_pow correctly determines that we shouldn't
> > evaluate pow at compile-time.  This patch reorganizes fold_const_pow
> > paying attention to signaling NaNs (PR 61441) and flag_errno_math.
> > Most importantly normal cases like pow(2.0,3.0) and pow(3.0,0.5) still
> > get evaluated at compile-time.
> >
> > This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
> > and make -k check, both with and without --target_board=unix{-m32},
> > with no new failures.  Ok for mainline?
> 
> I think the testcases need to check math_errhandling & MATH_ERRNO otherwise
> BSDs will likely runfail the testcases.

Many thanks for the review, and pointing me to C99's math_errhandling.
For the record, the idiom that I went with [which alas is still a test of the
system's libm implementation] looks like:

/* PR middle-end/123826 */
/* { dg-do run } */
/* { dg-options "-O2" } */

#ifdef __NO_MATH_ERRNO__
int main() { return 0; }
#else
#include <errno.h>
#include <float.h>
#include <math.h>

double foo(double x)
{
  return pow(x, 2.0);
}

int main()
{
#ifdef math_errhandling
#ifdef MATH_ERRNO
  if ((math_errhandling & MATH_ERRNO) == 0)
    return 0;
#else
  if ((math_errhandling & 1) == 0)
    return 0;
#endif
#endif

  errno = 0;
  double x = foo(DBL_MAX);
  if (errno != ERANGE)
    __builtin_abort ();
  return 0;
}
#endif


The __NO_MATH_ERRNO__ test checks GCC's predefined macro,  as set by
-fno-math-errno, and can be used by targets/backends that don’t have errno.h.
c99's math_errhandling is allowed to call a function, so it's a run-time test 
on 
platforms that support it.  Platforms that define math_errhandling should also
define MATH_ERRNO (to 1), but a little paranoia can't hurt.

I've no doubt someone somewhere might need an xfail (which is why I split
the pow and powf test cases just in case these behave differently).

> Other than that, OK.
Thanks, pushed.

> 
> I did think of making use of frange in gimple_expand_builtin_pow, but I 
> suspect
> overflow and underflow are difficult to check for and it's probably not worth 
> the
> trouble.
> 
> Thanks,
> Richard.
> 
> >
> > 2026-02-02  Roger Sayle  <[email protected]>
> >
> > gcc/ChangeLog
> >         PR middle-end/123826
> >         * tree-ssa-math-opts.cc (gimple_expand_builtin_pow): Add test
> >         for flag_errno_math.
> >         * fold-const-call.cc (fold_const_pow): Reorganize, eliminating
> >         call to real_powi, and letting do_mpfr_arg2 do all the heavy
> >         lifting.
> >
> > gcc/testsuite/ChangeLog
> >         PR middle-end/123826
> >         * gcc.dg/errno-2.c: New test case.
> >         * gcc.dg/errno-3.c: Likewise.
> >

Reply via email to