static bool fold_const_builtin_load_exponent (real_value *result, const real_value *arg0, const wide_int_ref &arg1, const real_format *format) { /* Bound the maximum adjustment to twice the range of the mode's valid exponents. Use abs to ensure the range is positive as a sanity check. */ int max_exp_adj = 2 * labs (format->emax - format->emin); /* The requested adjustment must be inside this range. This is a preliminary cap to avoid things like overflow, we may still fail to compute the result for other reasons. */ if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj)) return false; REAL_VALUE_TYPE initial_result; real_ldexp (&initial_result, arg0, arg1.to_shwi ()); /* Ensure we didn't overflow. */ if (real_isinf (&initial_result)) return false; /* Only proceed if the target mode can hold the resulting value. */ *result = real_value_truncate (format, initial_result); return real_equal (&initial_result, result); }
static bool fold_const_call_sss (real_value *result, combined_fn fn, const real_value *arg0, const wide_int_ref &arg1, const real_format *format) { switch (fn) { CASE_CFN_LDEXP: return fold_const_builtin_load_exponent (result, arg0, arg1, format); CASE_CFN_SCALBN: CASE_CFN_SCALBLN: return (format->b == 2 && fold_const_builtin_load_exponent (result, arg0, arg1, format)); CASE_CFN_POWI: /* Avoid the folding if flag_signaling_nans is on and operand is a signaling NaN. */ if (!flag_unsafe_math_optimizations && flag_signaling_nans && REAL_VALUE_ISSIGNALING_NAN (*arg0)) return false; real_powi (result, format, arg0, arg1.to_shwi ()); return true; default: return false; } }
static bool do_mpfr_arg2 (real_value *result, int (*func) (mpfr_ptr, long, mpfr_srcptr, mp_rnd_t), const wide_int_ref &arg0, const real_value *arg1, const real_format *format) { if (format->b != 2 || !real_isfinite (arg1)) return false; int prec = format->p; mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN; mpfr_t m; mpfr_init2 (m, prec); mpfr_from_real (m, arg1, GMP_RNDN); mpfr_clear_flags (); bool inexact = func (m, arg0.to_shwi (), m, rnd); bool ok = do_mpfr_ckconv (result, m, inexact, format); mpfr_clear (m); return ok; }
static bool fold_const_call_sss (real_value *result, built_in_function fn, const real_value *arg0, const wide_int_ref &arg1, const real_format *format) { switch (fn) { CASE_FLT_FN (BUILT_IN_LDEXP): return fold_const_builtin_load_exponent (result, arg0, arg1, format); CASE_FLT_FN (BUILT_IN_SCALBN): CASE_FLT_FN (BUILT_IN_SCALBLN): return (format->b == 2 && fold_const_builtin_load_exponent (result, arg0, arg1, format)); CASE_FLT_FN (BUILT_IN_POWI): real_powi (result, format, arg0, arg1.to_shwi ()); return true; default: return false; } }