diff --git a/gcc/builtins.c b/gcc/builtins.c index 25e01e4092b..25282d2122d 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -2067,6 +2067,7 @@ mathfn_built_in_2 (tree type, combined_fn fn) CASE_MATHFN (REMQUO) CASE_MATHFN_FLOATN (RINT) CASE_MATHFN_FLOATN (ROUND) + CASE_MATHFN_FLOATN (ROUNDEVEN) CASE_MATHFN (SCALB) CASE_MATHFN (SCALBLN) CASE_MATHFN (SCALBN) diff --git a/gcc/builtins.def b/gcc/builtins.def index ef89729fd0c..f1b6830a49c 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -308,6 +308,7 @@ DEF_C99_BUILTIN (BUILT_IN_CBRT, "cbrt", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_ DEF_C99_BUILTIN (BUILT_IN_CBRTF, "cbrtf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_CBRTL, "cbrtl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) DEF_LIB_BUILTIN (BUILT_IN_CEIL, "ceil", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_ROUNDEVEN, "roundeven", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILF, "ceilf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILL, "ceill", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) #define CEIL_TYPE(F) BT_FN_##F##_##F diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c index 06a420601c0..6f4fea63b0c 100644 --- a/gcc/fold-const-call.c +++ b/gcc/fold-const-call.c @@ -773,6 +773,16 @@ fold_const_call_ss (real_value *result, combined_fn fn, CASE_CFN_CEIL_FN: if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) { + fprintf (stderr, "\n"); + fprintf (stderr, "cl: %u\n", arg->cl); + fprintf (stderr, "sign: %u\n", arg->sign); + fprintf (stderr, "signalling: %u\n", arg->signalling); + fprintf (stderr, "canonical: %u\n", arg->canonical); + fprintf (stderr, "uexp: %u\n", arg->uexp); + + fprintf (stderr, "sig: "); + for (int i = 0; i < SIGSZ; i++) + fprintf (stderr, "%lx ", arg->sig[i]); real_ceil (result, format, arg); return true; } @@ -792,6 +802,15 @@ fold_const_call_ss (real_value *result, combined_fn fn, } return false; + CASE_CFN_ROUNDEVEN: + CASE_CFN_ROUNDEVEN_FN: + if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) + { + real_roundeven (result, format, arg); + return true; + } + return false; + CASE_CFN_LOGB: return fold_const_logb (result, arg, format); diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index cda314e1121..b89918815f9 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -224,6 +224,7 @@ DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary) DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary) DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary) DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary) +DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary) DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary) /* Binary math functions. */ diff --git a/gcc/optabs.def b/gcc/optabs.def index 5a67f5eed5e..eb9e22acd8f 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -267,6 +267,7 @@ OPTAB_D (fnms_optab, "fnms$a4") OPTAB_D (rint_optab, "rint$a2") OPTAB_D (round_optab, "round$a2") +OPTAB_D (roundeven_optab, "roundeven$a2") OPTAB_D (floor_optab, "floor$a2") OPTAB_D (ceil_optab, "ceil$a2") OPTAB_D (btrunc_optab, "btrunc$a2") diff --git a/gcc/real.c b/gcc/real.c index f822ae82d61..9c57f50e8fc 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -1956,6 +1956,8 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size, int real_from_string (REAL_VALUE_TYPE *r, const char *str) { + fprintf (stderr, "\nreal_from_string: str = %s\n", str); + int exp = 0; bool sign = false; @@ -5004,10 +5006,39 @@ void real_round (REAL_VALUE_TYPE *r, format_helper fmt, const REAL_VALUE_TYPE *x) { +#if 0 do_add (r, x, &dconsthalf, x->sign); do_fix_trunc (r, r); if (fmt) real_convert (r, fmt, r); +#endif + fprintf (stderr, "\nhere\n"); + real_value z; + do_fix_trunc (&z, x); + HOST_WIDE_INT i = real_to_integer (&z); + fprintf (stderr, "\n i = %ld\n", i); + if (i % 2) + do_add (r, &z, &dconstm1, 0); + else + *r = z; +} + +/* Round X to nearest even integer towards zero. */ + +void +real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt, + const REAL_VALUE_TYPE *x) +{ + REAL_VALUE_TYPE t; + + do_fix_trunc (&t, x); + HOST_WIDE_INT i = real_to_integer (&t); + fprintf (stderr, "\nhere\n"); + fprintf (stderr, "\n i = %ld\n", i); + if(i % 2) + do_add (r, &t, &dconstm1, 0); + else + *r = t; } /* Set the sign of R to the sign of X. */ diff --git a/gcc/real.h b/gcc/real.h index 0ce42565708..10898eae79e 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -499,6 +499,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper, const REAL_VALUE_TYPE *); extern void real_round (REAL_VALUE_TYPE *, format_helper, const REAL_VALUE_TYPE *); +extern void real_roundeven (REAL_VALUE_TYPE *, format_helper, + const REAL_VALUE_TYPE *); /* Set the sign of R to the sign of X. */ extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); diff --git a/gcc/realmpfr.c b/gcc/realmpfr.c index 10f05caaba3..4834fd017b1 100644 --- a/gcc/realmpfr.c +++ b/gcc/realmpfr.c @@ -98,6 +98,7 @@ real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, const real_format *format, mpfr_free_str (rstr); + fprintf (stderr, "\nreal_from_mpfr: buf = %s\n", buf); real_from_string (r, buf); }