static bool fold_const_pow (real_value *result, const real_value *arg0, const real_value *arg1, const real_format *format) { if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format)) return true; /* Check for an integer exponent. */ REAL_VALUE_TYPE cint1; HOST_WIDE_INT n1 = real_to_integer (arg1); real_from_integer (&cint1, VOIDmode, n1, SIGNED); /* Attempt to evaluate pow at compile-time, unless this should raise an exception. */ if (real_identical (arg1, &cint1) && (n1 > 0 || (!flag_trapping_math && !flag_errno_math) || !real_equal (arg0, &dconst0))) { bool inexact = real_powi (result, format, arg0, n1); if (flag_unsafe_math_optimizations || !inexact) return true; } return false; }
static bool fold_const_logb (real_value *result, const real_value *arg, const real_format *format) { switch (arg->cl) { case rvc_nan: /* If arg is +-NaN, then return it. */ *result = *arg; return true; case rvc_inf: /* If arg is +-Inf, then return +Inf. */ *result = *arg; result->sign = 0; return true; case rvc_zero: /* Zero may set errno and/or raise an exception. */ return false; case rvc_normal: /* For normal numbers, proceed iff radix == 2. In GCC, normalized significands are in the range [0.5, 1.0). We want the exponent as if they were [1.0, 2.0) so get the exponent and subtract 1. */ if (format->b == 2) { real_from_integer (result, format, REAL_EXP (arg) - 1, SIGNED); return true; } return false; } gcc_unreachable (); }
void fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig, size_t buf_size) { REAL_VALUE_TYPE real_value, base_value, fixed_value; real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), f_orig->mode); real_from_integer (&real_value, VOIDmode, f_orig->data.low, f_orig->data.high, UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode)); real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value); real_to_decimal (str, &fixed_value, buf_size, 0, 1); }
void fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig, size_t buf_size) { REAL_VALUE_TYPE real_value, base_value, fixed_value; signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED; real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), VOIDmode); real_from_integer (&real_value, VOIDmode, wide_int::from (f_orig->data, GET_MODE_PRECISION (f_orig->mode), sgn), sgn); real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value); real_to_decimal (str, &fixed_value, buf_size, 0, 1); }
static void gen_conditions_for_pow_cst_base (tree base, tree expn, vec<gimple> conds, unsigned *nconds) { inp_domain exp_domain; /* Validate the range of the base constant to make sure it is consistent with check_pow. */ REAL_VALUE_TYPE mv; REAL_VALUE_TYPE bcv = TREE_REAL_CST (base); gcc_assert (!REAL_VALUES_EQUAL (bcv, dconst1) && !REAL_VALUES_LESS (bcv, dconst1)); real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED); gcc_assert (!REAL_VALUES_LESS (mv, bcv)); exp_domain = get_domain (0, false, false, 127, true, false); gen_conditions_for_domain (expn, exp_domain, conds, nconds); }
static bool check_pow (gimple pow_call) { tree base, expn; enum tree_code bc, ec; if (gimple_call_num_args (pow_call) != 2) return false; base = gimple_call_arg (pow_call, 0); expn = gimple_call_arg (pow_call, 1); if (!check_target_format (expn)) return false; bc = TREE_CODE (base); ec = TREE_CODE (expn); /* Folding candidates are not interesting. Can actually assert that it is already folded. */ if (ec == REAL_CST && bc == REAL_CST) return false; if (bc == REAL_CST) { /* Only handle a fixed range of constant. */ REAL_VALUE_TYPE mv; REAL_VALUE_TYPE bcv = TREE_REAL_CST (base); if (REAL_VALUES_EQUAL (bcv, dconst1)) return false; if (REAL_VALUES_LESS (bcv, dconst1)) return false; real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, 0, 1); if (REAL_VALUES_LESS (mv, bcv)) return false; return true; } else if (bc == SSA_NAME) { tree base_val0, base_var, type; gimple base_def; int bit_sz; /* Only handles cases where base value is converted from integer values. */ base_def = SSA_NAME_DEF_STMT (base); if (gimple_code (base_def) != GIMPLE_ASSIGN) return false; if (gimple_assign_rhs_code (base_def) != FLOAT_EXPR) return false; base_val0 = gimple_assign_rhs1 (base_def); base_var = SSA_NAME_VAR (base_val0); if (!DECL_P (base_var)) return false; type = TREE_TYPE (base_var); if (TREE_CODE (type) != INTEGER_TYPE) return false; bit_sz = TYPE_PRECISION (type); /* If the type of the base is too wide, the resulting shrink wrapping condition will be too conservative. */ if (bit_sz > MAX_BASE_INT_BIT_SIZE) return false; return true; } else return false; }