Commit a41d064d by Kaveh R. Ghazi Committed by Kaveh Ghazi

builtins.c (do_mpc_arg2): New.

	* builtins.c (do_mpc_arg2): New.
	(fold_builtin_2): Fold builtin cpow.
	* real.h (HAVE_mpc_pow): New.

testsuite:
	* gcc.dg/torture/builtin-math-5.c: Add more cases.
	* gcc.dg/torture/builtin-math-6.c: Likewise.  Depend on
	effective target "mpc_pow".
	* lib/target-supports.exp (check_effective_target_mpc_pow): New.

From-SVN: r149716
parent d19cb53b
2009-07-16 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (do_mpc_arg2): New.
(fold_builtin_2): Fold builtin cpow.
* real.h (HAVE_mpc_pow): New.
2009-07-16 Bingfeng Mei <bmei@broadcom.com>
* modulo-sched.c (sms_schedule): stage_count <= 1 as correct comparison
......
......@@ -60,6 +60,9 @@ along with GCC; see the file COPYING3. If not see
#endif
#ifdef HAVE_mpc
static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
#ifdef HAVE_mpc_pow
static tree do_mpc_arg2 (tree, tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t));
#endif
#endif
/* Define the names of the builtin function types and codes. */
......@@ -10647,6 +10650,16 @@ fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
CASE_FLT_FN (BUILT_IN_HYPOT):
return fold_builtin_hypot (fndecl, arg0, arg1, type);
#ifdef HAVE_mpc_pow
CASE_FLT_FN (BUILT_IN_CPOW):
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
&& validate_arg (arg1, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
return do_mpc_arg2 (arg0, arg1, type, mpc_pow);
break;
#endif
CASE_FLT_FN (BUILT_IN_LDEXP):
return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/true);
CASE_FLT_FN (BUILT_IN_SCALBN):
......@@ -13715,6 +13728,64 @@ do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
return result;
}
/* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument
mpc function FUNC on it and return the resulting value as a tree
with type TYPE. The mpfr precision is set to the precision of
TYPE. We assume that function FUNC returns zero if the result
could be calculated exactly within the requested precision. */
#ifdef HAVE_mpc_pow
static tree
do_mpc_arg2 (tree arg0, tree arg1, tree type,
int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
{
tree result = NULL_TREE;
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
/* To proceed, MPFR must exactly represent the target floating point
format, which only happens when the target base equals two. */
if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
&& TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE
&& REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2)
{
const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
if (real_isfinite (re0) && real_isfinite (im0)
&& real_isfinite (re1) && real_isfinite (im1))
{
const struct real_format *const fmt =
REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
const int prec = fmt->p;
const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
int inexact;
mpc_t m0, m1;
mpc_init2 (m0, prec);
mpc_init2 (m1, prec);
mpfr_from_real (mpc_realref(m0), re0, rnd);
mpfr_from_real (mpc_imagref(m0), im0, rnd);
mpfr_from_real (mpc_realref(m1), re1, rnd);
mpfr_from_real (mpc_imagref(m1), im1, rnd);
mpfr_clear_flags ();
inexact = func (m0, m0, m1, crnd);
result = do_mpc_ckconv (m0, type, inexact);
mpc_clear (m0);
mpc_clear (m1);
}
}
return result;
}
# endif
#endif /* HAVE_mpc */
/* FIXME tuples.
......
......@@ -26,6 +26,9 @@
#include <mpfr.h>
#ifdef HAVE_mpc
#include <mpc.h>
# if MPC_VERSION >= MPC_VERSION_NUM(0,6,1)
# define HAVE_mpc_pow
# endif
#endif
#endif
#include "machmode.h"
......
2009-07-16 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/torture/builtin-math-5.c: Add more cases.
* gcc.dg/torture/builtin-math-6.c: Likewise. Depend on
effective target "mpc_pow".
* lib/target-supports.exp (check_effective_target_mpc_pow): New.
2009-07-16 Richard Henderson <rth@redhat.com>
* g++.dg/opt/eh4.C: New test.
......
......@@ -18,6 +18,12 @@ extern void fool (_Complex long double);
fool (__builtin_##FUNC##l (ARG##L)); \
} while (0)
#define TESTIT2(FUNC, ARG0, ARG1) do { \
foof (__builtin_##FUNC##f (ARG0##F, ARG1##F)); \
foo (__builtin_##FUNC (ARG0, ARG1)); \
fool (__builtin_##FUNC##l (ARG0##L, ARG1##L)); \
} while (0)
void bar()
{
/* An argument of NaN is not evaluated at compile-time. */
......@@ -38,9 +44,80 @@ void bar()
#endif
foo (__builtin_csqrt (-__builtin_inf()));
fool (__builtin_csqrtl (-__builtin_infl()));
/* Check for overflow/underflow. */
TESTIT (cexp, 1e20);
TESTIT (cexp, -1e20);
/* An argument of NaN is not evaluated at compile-time. */
#ifndef __SPU__
foof (__builtin_cpowf (__builtin_nanf(""), 2.5F));
#endif
foo (__builtin_cpow (__builtin_nan(""), 2.5));
fool (__builtin_cpowl (__builtin_nanl(""), 2.5L));
#ifndef __SPU__
foof (__builtin_cpowf (2.5F, __builtin_nanf("")));
#endif
foo (__builtin_cpow (2.5, __builtin_nan("")));
fool (__builtin_cpowl (2.5L, __builtin_nanl("")));
/* An argument of Inf/-Inf is not evaluated at compile-time. */
#ifndef __SPU__
foof (__builtin_cpowf (__builtin_inff(), 2.5F));
#endif
foo (__builtin_cpow (__builtin_inf(), 2.5));
fool (__builtin_cpowl (__builtin_infl(), 2.5L));
#ifndef __SPU__
foof (__builtin_cpowf (-__builtin_inff(), 2.5F));
#endif
foo (__builtin_cpow (-__builtin_inf(), 2.5));
fool (__builtin_cpowl (-__builtin_infl(), 2.5L));
#ifndef __SPU__
foof (__builtin_cpowf (2.5F, __builtin_inff()));
#endif
foo (__builtin_cpow (2.5, __builtin_inf()));
fool (__builtin_cpowl (2.5L, __builtin_infl()));
#ifndef __SPU__
foof (__builtin_cpowf (2.5F, -__builtin_inff()));
#endif
foo (__builtin_cpow (2.5, -__builtin_inf()));
fool (__builtin_cpowl (2.5L, -__builtin_infl()));
/* Check for Inv/NaN return values. */
TESTIT2 (cpow, -0.0, -4.5); /* Returns Inf */
TESTIT2 (cpow, 0.0, -4.5); /* Returns Inf */
/* Check for overflow/underflow. */
foof (__builtin_cpowf (__FLT_MAX__, 3.5F));
foof (__builtin_cpowf (__FLT_MAX__ * 1.FI, 3.5F));
foo (__builtin_cpow (__DBL_MAX__, 3.5));
foo (__builtin_cpow (__DBL_MAX__ * 1.I, 3.5));
fool (__builtin_cpowl (__LDBL_MAX__, 3.5L));
fool (__builtin_cpowl (__LDBL_MAX__ * 1.LI, 3.5L));
TESTIT2 (cpow, 2.0, 0x1p50);
TESTIT2 (cpow, 2.0, 0x1p28);
TESTIT2 (cpow, 2.0, 0x1p24);
foof (__builtin_cpowf (__FLT_MAX__, -3.5F));
foof (__builtin_cpowf (__FLT_MAX__ * 1.FI, -3.5F));
foo (__builtin_cpow (__DBL_MAX__, -3.5));
foo (__builtin_cpow (__DBL_MAX__ * 1.I, -3.5));
fool (__builtin_cpowl (__LDBL_MAX__, -3.5L));
fool (__builtin_cpowl (__LDBL_MAX__ * 1.LI, -3.5L));
TESTIT2 (cpow, 2.0, -0x1p50);
TESTIT2 (cpow, 2.0, -0x1p28);
TESTIT2 (cpow, 2.0, -0x1p24);
}
/* { dg-final { scan-tree-dump-times "csqrtf" 3 "original" } } */
/* { dg-final { scan-tree-dump-times "csqrtf" 3 "original" { target { ! { spu*-*-* } } } } } */
/* { dg-final { scan-tree-dump-times "csqrtf" 0 "original" { target { spu*-*-* } } } } */
/* { dg-final { scan-tree-dump-times "csqrt " 3 "original" } } */
/* { dg-final { scan-tree-dump-times "csqrtl" 3 "original" } } */
/* { dg-final { scan-tree-dump-times "cexpf" 2 "original" } } */
/* { dg-final { scan-tree-dump-times "cexp " 2 "original" } } */
/* { dg-final { scan-tree-dump-times "cexpl" 2 "original" } } */
/* { dg-final { scan-tree-dump-times "cpowf" 18 "original" { target { ! { spu*-*-* } } } } } */
/* { dg-final { scan-tree-dump-times "cpowf" 12 "original" { target { spu*-*-* } } } } */
/* { dg-final { scan-tree-dump-times "cpow " 18 "original" } } */
/* { dg-final { scan-tree-dump-times "cpowl" 18 "original" } } */
/* { dg-final { cleanup-tree-dump "original" } } */
......@@ -2998,3 +2998,16 @@ proc check_effective_target_mpc { } {
}
}]
}
# Return 1 if the MPC library with mpc_pow is integrated with GCC, 0 otherwise.
proc check_effective_target_mpc_pow { } {
return [check_no_compiler_messages mpc executable {
extern void link_error(void);
int main ()
{
if (__builtin_cpow(1,1) != 1)
link_error();
}
}]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment