diff options
Diffstat (limited to 'gcc/wide-int-range.h')
-rw-r--r-- | gcc/wide-int-range.h | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/gcc/wide-int-range.h b/gcc/wide-int-range.h new file mode 100644 index 0000000..4421bc8 --- /dev/null +++ b/gcc/wide-int-range.h @@ -0,0 +1,115 @@ +/* Support routines for range operations on wide ints. + Copyright (C) 2018 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, + bool overflow_wraps); +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, + bool overflow_wraps); +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_can_optimize_bit_op (tree_code, + const wide_int &lb, + const wide_int &ub, + const wide_int &mask); +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); + +/* Return TRUE if shifting by range [MIN, MAX] is undefined behavior. */ + +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); +} + +#endif /* GCC_WIDE_INT_RANGE_H */ |