123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- /* Support routines for range operations on wide ints.
- Copyright (C) 2018-2019 Free Software Foundation, Inc.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GCC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #ifndef GCC_WIDE_INT_RANGE_H
- #define GCC_WIDE_INT_RANGE_H
- extern bool wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
- enum tree_code code, signop sign,
- const wide_int &, const wide_int &,
- const wide_int &, const wide_int &,
- bool overflow_undefined);
- extern bool wide_int_range_mult_wrapping (wide_int &res_lb,
- wide_int &res_ub,
- signop sign,
- unsigned prec,
- const wide_int &min0_,
- const wide_int &max0_,
- const wide_int &min1_,
- const wide_int &max1_);
- extern bool wide_int_range_multiplicative_op (wide_int &res_lb,
- wide_int &res_ub,
- enum tree_code code,
- signop sign,
- unsigned prec,
- const wide_int &vr0_lb,
- const wide_int &vr0_ub,
- const wide_int &vr1_lb,
- const wide_int &vr1_ub,
- bool overflow_undefined);
- extern bool wide_int_range_lshift (wide_int &res_lb, wide_int &res_ub,
- signop sign, unsigned prec,
- const wide_int &, const wide_int &,
- const wide_int &, const wide_int &,
- bool overflow_undefined);
- extern void wide_int_range_set_zero_nonzero_bits (signop,
- const wide_int &lb,
- const wide_int &ub,
- wide_int &may_be_nonzero,
- wide_int &must_be_nonzero);
- extern bool wide_int_range_optimize_bit_op (wide_int &res_lb, wide_int &res_ub,
- enum tree_code code,
- signop sign,
- const wide_int &vr0_lb,
- const wide_int &vr0_ub,
- const wide_int &vr1_lb,
- const wide_int &vr1_ub);
- extern bool wide_int_range_get_mask_and_bounds (wide_int &mask,
- wide_int &lower_bound,
- wide_int &upper_bound,
- const wide_int &vr0_min,
- const wide_int &vr0_max,
- const wide_int &vr1_min,
- const wide_int &vr1_max);
- extern bool wide_int_range_bit_xor (wide_int &wmin, wide_int &wmax,
- signop sign,
- unsigned prec,
- const wide_int &must_be_nonzero0,
- const wide_int &may_be_nonzero0,
- const wide_int &must_be_nonzero1,
- const wide_int &may_be_nonzero1);
- extern bool wide_int_range_bit_ior (wide_int &wmin, wide_int &wmax,
- signop sign,
- const wide_int &vr0_min,
- const wide_int &vr0_max,
- const wide_int &vr1_min,
- const wide_int &vr1_max,
- const wide_int &must_be_nonzero0,
- const wide_int &may_be_nonzero0,
- const wide_int &must_be_nonzero1,
- const wide_int &may_be_nonzero1);
- extern bool wide_int_range_bit_and (wide_int &wmin, wide_int &wmax,
- signop sign,
- unsigned prec,
- const wide_int &vr0_min,
- const wide_int &vr0_max,
- const wide_int &vr1_min,
- const wide_int &vr1_max,
- const wide_int &must_be_nonzero0,
- const wide_int &may_be_nonzero0,
- const wide_int &must_be_nonzero1,
- const wide_int &may_be_nonzero1);
- extern void wide_int_range_trunc_mod (wide_int &wmin, wide_int &wmax,
- signop sign,
- unsigned prec,
- const wide_int &vr0_min,
- const wide_int &vr0_max,
- const wide_int &vr1_min,
- const wide_int &vr1_max);
- extern bool wide_int_range_abs (wide_int &min, wide_int &max,
- signop sign, unsigned prec,
- const wide_int &vr0_min,
- const wide_int &vr0_max,
- bool overflow_undefined);
- extern void wide_int_range_absu (wide_int &min, wide_int &max,
- unsigned prec,
- const wide_int &vr0_min,
- const wide_int &vr0_max);
- extern bool wide_int_range_convert (wide_int &min, wide_int &max,
- signop inner_sign,
- unsigned inner_prec,
- signop outer_sign,
- unsigned outer_prec,
- const wide_int &vr0_min,
- const wide_int &vr0_max);
- extern bool wide_int_range_div (wide_int &wmin, wide_int &wmax,
- enum tree_code code,
- signop sign, unsigned prec,
- const wide_int ÷nd_min,
- const wide_int ÷nd_max,
- const wide_int &divisor_min,
- const wide_int &divisor_max,
- bool overflow_undefined,
- bool &extra_range_p,
- wide_int &extra_min, wide_int &extra_max);
- /* Return TRUE if shifting by range [MIN, MAX] is undefined behavior,
- interpreting MIN and MAX according to SIGN. */
- inline bool
- wide_int_range_shift_undefined_p (signop sign, unsigned prec,
- const wide_int &min, const wide_int &max)
- {
- /* ?? Note: The original comment said this only applied to
- RSHIFT_EXPR, but it was being applied to both left and right
- shifts. */
- /* Shifting by any values outside [0..prec-1], gets undefined
- behavior from the shift operation. We cannot even trust
- SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
- shifts, and the operation at the tree level may be widened. */
- return wi::lt_p (min, 0, sign) || wi::ge_p (max, prec, sign);
- }
- /* Calculate MIN/MAX_EXPR of two ranges and store the result in [MIN, MAX]. */
- inline bool
- wide_int_range_min_max (wide_int &min, wide_int &max,
- tree_code code,
- signop sign, unsigned prec,
- const wide_int &vr0_min, const wide_int &vr0_max,
- const wide_int &vr1_min, const wide_int &vr1_max)
- {
- wi::overflow_type overflow;
- wide_int_binop (min, code, vr0_min, vr1_min, sign, &overflow);
- wide_int_binop (max, code, vr0_max, vr1_max, sign, &overflow);
- /* If the new range covers the entire domain, that's really no range
- at all. */
- if (min == wi::min_value (prec, sign)
- && max == wi::max_value (prec, sign))
- return false;
- return true;
- }
- /* Return TRUE if 0 is within [WMIN, WMAX]. */
- inline bool
- wide_int_range_includes_zero_p (const wide_int &wmin, const wide_int &wmax,
- signop sign)
- {
- return wi::le_p (wmin, 0, sign) && wi::ge_p (wmax, 0, sign);
- }
- /* Return TRUE if [WMIN, WMAX] is the singleton 0. */
- inline bool
- wide_int_range_zero_p (const wide_int &wmin, const wide_int &wmax,
- unsigned prec)
- {
- return wmin == wmax && wi::eq_p (wmin, wi::zero (prec));
- }
- #endif /* GCC_WIDE_INT_RANGE_H */
|