wide-int-range.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* Support routines for range operations on wide ints.
  2. Copyright (C) 2018-2019 Free Software Foundation, Inc.
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3, or (at your option)
  7. any later version.
  8. GCC is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GCC; see the file COPYING3. If not see
  14. <http://www.gnu.org/licenses/>. */
  15. #ifndef GCC_WIDE_INT_RANGE_H
  16. #define GCC_WIDE_INT_RANGE_H
  17. extern bool wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
  18. enum tree_code code, signop sign,
  19. const wide_int &, const wide_int &,
  20. const wide_int &, const wide_int &,
  21. bool overflow_undefined);
  22. extern bool wide_int_range_mult_wrapping (wide_int &res_lb,
  23. wide_int &res_ub,
  24. signop sign,
  25. unsigned prec,
  26. const wide_int &min0_,
  27. const wide_int &max0_,
  28. const wide_int &min1_,
  29. const wide_int &max1_);
  30. extern bool wide_int_range_multiplicative_op (wide_int &res_lb,
  31. wide_int &res_ub,
  32. enum tree_code code,
  33. signop sign,
  34. unsigned prec,
  35. const wide_int &vr0_lb,
  36. const wide_int &vr0_ub,
  37. const wide_int &vr1_lb,
  38. const wide_int &vr1_ub,
  39. bool overflow_undefined);
  40. extern bool wide_int_range_lshift (wide_int &res_lb, wide_int &res_ub,
  41. signop sign, unsigned prec,
  42. const wide_int &, const wide_int &,
  43. const wide_int &, const wide_int &,
  44. bool overflow_undefined);
  45. extern void wide_int_range_set_zero_nonzero_bits (signop,
  46. const wide_int &lb,
  47. const wide_int &ub,
  48. wide_int &may_be_nonzero,
  49. wide_int &must_be_nonzero);
  50. extern bool wide_int_range_optimize_bit_op (wide_int &res_lb, wide_int &res_ub,
  51. enum tree_code code,
  52. signop sign,
  53. const wide_int &vr0_lb,
  54. const wide_int &vr0_ub,
  55. const wide_int &vr1_lb,
  56. const wide_int &vr1_ub);
  57. extern bool wide_int_range_get_mask_and_bounds (wide_int &mask,
  58. wide_int &lower_bound,
  59. wide_int &upper_bound,
  60. const wide_int &vr0_min,
  61. const wide_int &vr0_max,
  62. const wide_int &vr1_min,
  63. const wide_int &vr1_max);
  64. extern bool wide_int_range_bit_xor (wide_int &wmin, wide_int &wmax,
  65. signop sign,
  66. unsigned prec,
  67. const wide_int &must_be_nonzero0,
  68. const wide_int &may_be_nonzero0,
  69. const wide_int &must_be_nonzero1,
  70. const wide_int &may_be_nonzero1);
  71. extern bool wide_int_range_bit_ior (wide_int &wmin, wide_int &wmax,
  72. signop sign,
  73. const wide_int &vr0_min,
  74. const wide_int &vr0_max,
  75. const wide_int &vr1_min,
  76. const wide_int &vr1_max,
  77. const wide_int &must_be_nonzero0,
  78. const wide_int &may_be_nonzero0,
  79. const wide_int &must_be_nonzero1,
  80. const wide_int &may_be_nonzero1);
  81. extern bool wide_int_range_bit_and (wide_int &wmin, wide_int &wmax,
  82. signop sign,
  83. unsigned prec,
  84. const wide_int &vr0_min,
  85. const wide_int &vr0_max,
  86. const wide_int &vr1_min,
  87. const wide_int &vr1_max,
  88. const wide_int &must_be_nonzero0,
  89. const wide_int &may_be_nonzero0,
  90. const wide_int &must_be_nonzero1,
  91. const wide_int &may_be_nonzero1);
  92. extern void wide_int_range_trunc_mod (wide_int &wmin, wide_int &wmax,
  93. signop sign,
  94. unsigned prec,
  95. const wide_int &vr0_min,
  96. const wide_int &vr0_max,
  97. const wide_int &vr1_min,
  98. const wide_int &vr1_max);
  99. extern bool wide_int_range_abs (wide_int &min, wide_int &max,
  100. signop sign, unsigned prec,
  101. const wide_int &vr0_min,
  102. const wide_int &vr0_max,
  103. bool overflow_undefined);
  104. extern void wide_int_range_absu (wide_int &min, wide_int &max,
  105. unsigned prec,
  106. const wide_int &vr0_min,
  107. const wide_int &vr0_max);
  108. extern bool wide_int_range_convert (wide_int &min, wide_int &max,
  109. signop inner_sign,
  110. unsigned inner_prec,
  111. signop outer_sign,
  112. unsigned outer_prec,
  113. const wide_int &vr0_min,
  114. const wide_int &vr0_max);
  115. extern bool wide_int_range_div (wide_int &wmin, wide_int &wmax,
  116. enum tree_code code,
  117. signop sign, unsigned prec,
  118. const wide_int &dividend_min,
  119. const wide_int &dividend_max,
  120. const wide_int &divisor_min,
  121. const wide_int &divisor_max,
  122. bool overflow_undefined,
  123. bool &extra_range_p,
  124. wide_int &extra_min, wide_int &extra_max);
  125. /* Return TRUE if shifting by range [MIN, MAX] is undefined behavior,
  126. interpreting MIN and MAX according to SIGN. */
  127. inline bool
  128. wide_int_range_shift_undefined_p (signop sign, unsigned prec,
  129. const wide_int &min, const wide_int &max)
  130. {
  131. /* ?? Note: The original comment said this only applied to
  132. RSHIFT_EXPR, but it was being applied to both left and right
  133. shifts. */
  134. /* Shifting by any values outside [0..prec-1], gets undefined
  135. behavior from the shift operation. We cannot even trust
  136. SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
  137. shifts, and the operation at the tree level may be widened. */
  138. return wi::lt_p (min, 0, sign) || wi::ge_p (max, prec, sign);
  139. }
  140. /* Calculate MIN/MAX_EXPR of two ranges and store the result in [MIN, MAX]. */
  141. inline bool
  142. wide_int_range_min_max (wide_int &min, wide_int &max,
  143. tree_code code,
  144. signop sign, unsigned prec,
  145. const wide_int &vr0_min, const wide_int &vr0_max,
  146. const wide_int &vr1_min, const wide_int &vr1_max)
  147. {
  148. wi::overflow_type overflow;
  149. wide_int_binop (min, code, vr0_min, vr1_min, sign, &overflow);
  150. wide_int_binop (max, code, vr0_max, vr1_max, sign, &overflow);
  151. /* If the new range covers the entire domain, that's really no range
  152. at all. */
  153. if (min == wi::min_value (prec, sign)
  154. && max == wi::max_value (prec, sign))
  155. return false;
  156. return true;
  157. }
  158. /* Return TRUE if 0 is within [WMIN, WMAX]. */
  159. inline bool
  160. wide_int_range_includes_zero_p (const wide_int &wmin, const wide_int &wmax,
  161. signop sign)
  162. {
  163. return wi::le_p (wmin, 0, sign) && wi::ge_p (wmax, 0, sign);
  164. }
  165. /* Return TRUE if [WMIN, WMAX] is the singleton 0. */
  166. inline bool
  167. wide_int_range_zero_p (const wide_int &wmin, const wide_int &wmax,
  168. unsigned prec)
  169. {
  170. return wmin == wmax && wi::eq_p (wmin, wi::zero (prec));
  171. }
  172. #endif /* GCC_WIDE_INT_RANGE_H */