Mercurial > hg > CbC > CbC_gcc
diff gcc/fold-const-call.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/fold-const-call.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/fold-const-call.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Constant folding for calls to built-in and internal functions. - Copyright (C) 1988-2017 Free Software Foundation, Inc. + Copyright (C) 1988-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -529,6 +529,48 @@ /* Try to evaluate: + *RESULT = nextafter (*ARG0, *ARG1) + + or + + *RESULT = nexttoward (*ARG0, *ARG1) + + in format FORMAT. Return true on success. */ + +static bool +fold_const_nextafter (real_value *result, const real_value *arg0, + const real_value *arg1, const real_format *format) +{ + if (REAL_VALUE_ISSIGNALING_NAN (*arg0) + || REAL_VALUE_ISSIGNALING_NAN (*arg1)) + return false; + + /* Don't handle composite modes, nor decimal, nor modes without + inf or denorm at least for now. */ + if (format->pnan < format->p + || format->b == 10 + || !format->has_inf + || !format->has_denorm) + return false; + + if (real_nextafter (result, format, arg0, arg1) + /* If raising underflow or overflow and setting errno to ERANGE, + fail if we care about those side-effects. */ + && (flag_trapping_math || flag_errno_math)) + return false; + /* Similarly for nextafter (0, 1) raising underflow. */ + else if (flag_trapping_math + && arg0->cl == rvc_zero + && result->cl != rvc_zero) + return false; + + real_convert (result, format, result); + + return true; +} + +/* Try to evaluate: + *RESULT = ldexp (*ARG0, ARG1) in format FORMAT. Return true on success. */ @@ -583,6 +625,26 @@ return NULL_TREE; } +/* Fold a call to IFN_REDUC_<CODE> (ARG), returning a value of type TYPE. */ + +static tree +fold_const_reduction (tree type, tree arg, tree_code code) +{ + unsigned HOST_WIDE_INT nelts; + if (TREE_CODE (arg) != VECTOR_CST + || !VECTOR_CST_NELTS (arg).is_constant (&nelts)) + return NULL_TREE; + + tree res = VECTOR_CST_ELT (arg, 0); + for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++) + { + res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i)); + if (res == NULL_TREE || !CONSTANT_CLASS_P (res)) + return NULL_TREE; + } + return res; +} + /* Try to evaluate: *RESULT = FN (*ARG) @@ -596,6 +658,7 @@ switch (fn) { CASE_CFN_SQRT: + CASE_CFN_SQRT_FN: return (real_compare (GE_EXPR, arg, &dconst0) && do_mpfr_arg1 (result, mpfr_sqrt, arg, format)); @@ -698,6 +761,7 @@ && do_mpfr_arg1 (result, mpfr_y1, arg, format)); CASE_CFN_FLOOR: + CASE_CFN_FLOOR_FN: if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) { real_floor (result, format, arg); @@ -706,6 +770,7 @@ return false; CASE_CFN_CEIL: + CASE_CFN_CEIL_FN: if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) { real_ceil (result, format, arg); @@ -714,10 +779,12 @@ return false; CASE_CFN_TRUNC: + CASE_CFN_TRUNC_FN: real_trunc (result, format, arg); return true; CASE_CFN_ROUND: + CASE_CFN_ROUND_FN: if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) { real_round (result, format, arg); @@ -1147,11 +1214,51 @@ CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS): return fold_const_builtin_nan (type, arg, false); + case CFN_REDUC_PLUS: + return fold_const_reduction (type, arg, PLUS_EXPR); + + case CFN_REDUC_MAX: + return fold_const_reduction (type, arg, MAX_EXPR); + + case CFN_REDUC_MIN: + return fold_const_reduction (type, arg, MIN_EXPR); + + case CFN_REDUC_AND: + return fold_const_reduction (type, arg, BIT_AND_EXPR); + + case CFN_REDUC_IOR: + return fold_const_reduction (type, arg, BIT_IOR_EXPR); + + case CFN_REDUC_XOR: + return fold_const_reduction (type, arg, BIT_XOR_EXPR); + default: return fold_const_call_1 (fn, type, arg); } } +/* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value + of type TYPE. */ + +static tree +fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code) +{ + if (TREE_CODE (arg1) != VECTOR_CST) + return NULL_TREE; + + unsigned HOST_WIDE_INT nelts; + if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts)) + return NULL_TREE; + + for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++) + { + arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i)); + if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0)) + return NULL_TREE; + } + return arg0; +} + /* Try to evaluate: *RESULT = FN (*ARG0, *ARG1) @@ -1179,19 +1286,26 @@ return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format); CASE_CFN_COPYSIGN: + CASE_CFN_COPYSIGN_FN: *result = *arg0; real_copysign (result, arg1); return true; CASE_CFN_FMIN: + CASE_CFN_FMIN_FN: return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format); CASE_CFN_FMAX: + CASE_CFN_FMAX_FN: return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format); CASE_CFN_POW: return fold_const_pow (result, arg0, arg1, format); + CASE_CFN_NEXTAFTER: + CASE_CFN_NEXTTOWARD: + return fold_const_nextafter (result, arg0, arg1, format); + default: return false; } @@ -1297,20 +1411,33 @@ machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0)); machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1)); - if (arg0_mode == arg1_mode + if (mode == arg0_mode && real_cst_p (arg0) && real_cst_p (arg1)) { gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode)); - if (mode == arg0_mode) + REAL_VALUE_TYPE result; + if (arg0_mode == arg1_mode) { /* real, real -> real. */ - REAL_VALUE_TYPE result; if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0), TREE_REAL_CST_PTR (arg1), REAL_MODE_FORMAT (mode))) return build_real (type, result); } + else if (arg1_mode == TYPE_MODE (long_double_type_node)) + switch (fn) + { + CASE_CFN_NEXTTOWARD: + /* real, long double -> real. */ + if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0), + TREE_REAL_CST_PTR (arg1), + REAL_MODE_FORMAT (mode))) + return build_real (type, result); + break; + default: + break; + } return NULL_TREE; } @@ -1454,6 +1581,9 @@ } return NULL_TREE; + case CFN_FOLD_LEFT_PLUS: + return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR); + default: return fold_const_call_1 (fn, type, arg0, arg1); } @@ -1473,8 +1603,29 @@ switch (fn) { CASE_CFN_FMA: + CASE_CFN_FMA_FN: return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format); + case CFN_FMS: + { + real_value new_arg2 = real_value_negate (arg2); + return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format); + } + + case CFN_FNMA: + { + real_value new_arg0 = real_value_negate (arg0); + return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format); + } + + case CFN_FNMS: + { + real_value new_arg0 = real_value_negate (arg0); + real_value new_arg2 = real_value_negate (arg2); + return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, + &new_arg2, format); + } + default: return false; } @@ -1588,20 +1739,3 @@ return fold_const_call_1 (fn, type, arg0, arg1, arg2); } } - -/* Fold a fma operation with arguments ARG[012]. */ - -tree -fold_fma (location_t, tree type, tree arg0, tree arg1, tree arg2) -{ - REAL_VALUE_TYPE result; - if (real_cst_p (arg0) - && real_cst_p (arg1) - && real_cst_p (arg2) - && do_mpfr_arg3 (&result, mpfr_fma, TREE_REAL_CST_PTR (arg0), - TREE_REAL_CST_PTR (arg1), TREE_REAL_CST_PTR (arg2), - REAL_MODE_FORMAT (TYPE_MODE (type)))) - return build_real (type, result); - - return NULL_TREE; -}