annotate gcc/wide-int-range.cc @ 142:c83ff0b5a2ed

merge
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 22 Nov 2018 19:45:33 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1 /* Support routines for range operations on wide ints.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2 Copyright (C) 2018 Free Software Foundation, Inc.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
3
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
4 This file is part of GCC.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
5
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
7 it under the terms of the GNU General Public License as published by
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
8 the Free Software Foundation; either version 3, or (at your option)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
9 any later version.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
10
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
14 GNU General Public License for more details.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
15
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
19
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
20 #include "config.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
21 #include "system.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
22 #include "coretypes.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
23 #include "tree.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
24 #include "function.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
25 #include "fold-const.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
26 #include "wide-int-range.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
27
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
28 /* Wrapper around wide_int_binop that adjusts for overflow.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
29
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
30 Return true if we can compute the result; i.e. if the operation
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
31 doesn't overflow or if the overflow is undefined. In the latter
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
32 case (if the operation overflows and overflow is undefined), then
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
33 adjust the result to be -INF or +INF depending on CODE, VAL1 and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
34 VAL2. Return the value in *RES.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
35
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
36 Return false for division by zero, for which the result is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
37 indeterminate. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
38
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
39 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
40 wide_int_binop_overflow (wide_int &res,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
41 enum tree_code code,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
42 const wide_int &w0, const wide_int &w1,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
43 signop sign, bool overflow_undefined)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
44 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
45 wi::overflow_type overflow;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
46 if (!wide_int_binop (res, code, w0, w1, sign, &overflow))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
47 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
48
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
49 /* If the operation overflowed return -INF or +INF depending on the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
50 operation and the combination of signs of the operands. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
51 if (overflow && overflow_undefined)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
52 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
53 switch (code)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
54 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
55 case MULT_EXPR:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
56 /* For multiplication, the sign of the overflow is given
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
57 by the comparison of the signs of the operands. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
58 if (sign == UNSIGNED || w0.sign_mask () == w1.sign_mask ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
59 res = wi::max_value (w0.get_precision (), sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
60 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
61 res = wi::min_value (w0.get_precision (), sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
62 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
63
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
64 case TRUNC_DIV_EXPR:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
65 case FLOOR_DIV_EXPR:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
66 case CEIL_DIV_EXPR:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
67 case EXACT_DIV_EXPR:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
68 case ROUND_DIV_EXPR:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
69 /* For division, the only case is -INF / -1 = +INF. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
70 res = wi::max_value (w0.get_precision (), sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
71 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
72
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
73 default:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
74 gcc_unreachable ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
75 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
76 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
77 return !overflow;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
78 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
79
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
80 /* For range [LB, UB] compute two wide_int bit masks.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
81
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
82 In the MAY_BE_NONZERO bit mask, if some bit is unset, it means that
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
83 for all numbers in the range the bit is 0, otherwise it might be 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
84 or 1.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
85
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
86 In the MUST_BE_NONZERO bit mask, if some bit is set, it means that
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
87 for all numbers in the range the bit is 1, otherwise it might be 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
88 or 1. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
89
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
90 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
91 wide_int_range_set_zero_nonzero_bits (signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
92 const wide_int &lb, const wide_int &ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
93 wide_int &may_be_nonzero,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
94 wide_int &must_be_nonzero)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
95 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
96 may_be_nonzero = wi::minus_one (lb.get_precision ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
97 must_be_nonzero = wi::zero (lb.get_precision ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
98
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
99 if (wi::eq_p (lb, ub))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
100 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
101 may_be_nonzero = lb;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
102 must_be_nonzero = may_be_nonzero;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
103 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
104 else if (wi::ge_p (lb, 0, sign) || wi::lt_p (ub, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
105 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
106 wide_int xor_mask = lb ^ ub;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
107 may_be_nonzero = lb | ub;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
108 must_be_nonzero = lb & ub;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
109 if (xor_mask != 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
110 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
111 wide_int mask = wi::mask (wi::floor_log2 (xor_mask), false,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
112 may_be_nonzero.get_precision ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
113 may_be_nonzero = may_be_nonzero | mask;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
114 must_be_nonzero = wi::bit_and_not (must_be_nonzero, mask);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
115 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
116 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
117 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
118
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
119 /* Order 2 sets of wide int ranges (w0/w1, w2/w3) and set MIN/MAX
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
120 accordingly. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
121
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
122 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
123 wide_int_range_order_set (wide_int &min, wide_int &max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
124 wide_int &w0, wide_int &w1,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
125 wide_int &w2, wide_int &w3,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
126 signop sign)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
127 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
128 /* Order pairs w0,w1 and w2,w3. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
129 if (wi::gt_p (w0, w1, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
130 std::swap (w0, w1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
131 if (wi::gt_p (w2, w3, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
132 std::swap (w2, w3);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
133
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
134 /* Choose min and max from the ordered pairs. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
135 min = wi::min (w0, w2, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
136 max = wi::max (w1, w3, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
137 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
138
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
139 /* Calculate the cross product of two sets of ranges (VR0 and VR1) and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
140 store the result in [RES_LB, RES_UB].
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
141
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
142 CODE is the operation to perform with sign SIGN.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
143
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
144 OVERFLOW_UNDEFINED is set if overflow is undefined for the operation type.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
145
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
146 Return TRUE if we were able to calculate the cross product. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
147
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
148 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
149 wide_int_range_cross_product (wide_int &res_lb, wide_int &res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
150 enum tree_code code, signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
151 const wide_int &vr0_lb, const wide_int &vr0_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
152 const wide_int &vr1_lb, const wide_int &vr1_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
153 bool overflow_undefined)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
154 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
155 wide_int cp1, cp2, cp3, cp4;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
156
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
157 /* Compute the 4 cross operations, bailing if we get an overflow we
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
158 can't handle. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
159
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
160 if (!wide_int_binop_overflow (cp1, code, vr0_lb, vr1_lb, sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
161 overflow_undefined))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
162 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
163
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
164 if (wi::eq_p (vr0_lb, vr0_ub))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
165 cp3 = cp1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
166 else if (!wide_int_binop_overflow (cp3, code, vr0_ub, vr1_lb, sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
167 overflow_undefined))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
168 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
169
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
170 if (wi::eq_p (vr1_lb, vr1_ub))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
171 cp2 = cp1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
172 else if (!wide_int_binop_overflow (cp2, code, vr0_lb, vr1_ub, sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
173 overflow_undefined))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
174 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
175
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
176 if (wi::eq_p (vr0_lb, vr0_ub))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
177 cp4 = cp2;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
178 else if (!wide_int_binop_overflow (cp4, code, vr0_ub, vr1_ub, sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
179 overflow_undefined))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
180 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
181
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
182 wide_int_range_order_set (res_lb, res_ub, cp1, cp2, cp3, cp4, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
183 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
184 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
185
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
186 /* Multiply two ranges when TYPE_OVERFLOW_WRAPS:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
187
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
188 [RES_LB, RES_UB] = [MIN0, MAX0] * [MIN1, MAX1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
189
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
190 This is basically fancy code so we don't drop to varying with an
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
191 unsigned [-3,-1]*[-3,-1].
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
192
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
193 Return TRUE if we were able to perform the operation. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
194
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
195 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
196 wide_int_range_mult_wrapping (wide_int &res_lb,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
197 wide_int &res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
198 signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
199 unsigned prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
200 const wide_int &min0_,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
201 const wide_int &max0_,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
202 const wide_int &min1_,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
203 const wide_int &max1_)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
204 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
205 /* This test requires 2*prec bits if both operands are signed and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
206 2*prec + 2 bits if either is not. Therefore, extend the values
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
207 using the sign of the result to PREC2. From here on out,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
208 everthing is just signed math no matter what the input types
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
209 were. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
210 widest2_int min0 = widest2_int::from (min0_, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
211 widest2_int max0 = widest2_int::from (max0_, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
212 widest2_int min1 = widest2_int::from (min1_, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
213 widest2_int max1 = widest2_int::from (max1_, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
214 widest2_int sizem1 = wi::mask <widest2_int> (prec, false);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
215 widest2_int size = sizem1 + 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
216
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
217 /* Canonicalize the intervals. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
218 if (sign == UNSIGNED)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
219 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
220 if (wi::ltu_p (size, min0 + max0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
221 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
222 min0 -= size;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
223 max0 -= size;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
224 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
225
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
226 if (wi::ltu_p (size, min1 + max1))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
227 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
228 min1 -= size;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
229 max1 -= size;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
230 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
231 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
232
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
233 widest2_int prod0 = min0 * min1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
234 widest2_int prod1 = min0 * max1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
235 widest2_int prod2 = max0 * min1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
236 widest2_int prod3 = max0 * max1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
237
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
238 /* Sort the 4 products so that min is in prod0 and max is in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
239 prod3. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
240 /* min0min1 > max0max1 */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
241 if (prod0 > prod3)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
242 std::swap (prod0, prod3);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
243
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
244 /* min0max1 > max0min1 */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
245 if (prod1 > prod2)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
246 std::swap (prod1, prod2);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
247
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
248 if (prod0 > prod1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
249 std::swap (prod0, prod1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
250
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
251 if (prod2 > prod3)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
252 std::swap (prod2, prod3);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
253
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
254 /* diff = max - min. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
255 prod2 = prod3 - prod0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
256 if (wi::geu_p (prod2, sizem1))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
257 /* The range covers all values. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
258 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
259
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
260 res_lb = wide_int::from (prod0, prec, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
261 res_ub = wide_int::from (prod3, prec, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
262 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
263 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
264
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
265 /* Perform multiplicative operation CODE on two ranges:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
266
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
267 [RES_LB, RES_UB] = [VR0_LB, VR0_UB] .CODE. [VR1_LB, VR1_LB]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
268
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
269 Return TRUE if we were able to perform the operation.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
270
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
271 NOTE: If code is MULT_EXPR and !TYPE_OVERFLOW_UNDEFINED, the resulting
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
272 range must be canonicalized by the caller because its components
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
273 may be swapped. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
274
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
275 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
276 wide_int_range_multiplicative_op (wide_int &res_lb, wide_int &res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
277 enum tree_code code,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
278 signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
279 unsigned prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
280 const wide_int &vr0_lb,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
281 const wide_int &vr0_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
282 const wide_int &vr1_lb,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
283 const wide_int &vr1_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
284 bool overflow_undefined)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
285 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
286 /* Multiplications, divisions and shifts are a bit tricky to handle,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
287 depending on the mix of signs we have in the two ranges, we
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
288 need to operate on different values to get the minimum and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
289 maximum values for the new range. One approach is to figure
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
290 out all the variations of range combinations and do the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
291 operations.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
292
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
293 However, this involves several calls to compare_values and it
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
294 is pretty convoluted. It's simpler to do the 4 operations
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
295 (MIN0 OP MIN1, MIN0 OP MAX1, MAX0 OP MIN1 and MAX0 OP MAX0 OP
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
296 MAX1) and then figure the smallest and largest values to form
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
297 the new range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
298 if (code == MULT_EXPR && !overflow_undefined)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
299 return wide_int_range_mult_wrapping (res_lb, res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
300 sign, prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
301 vr0_lb, vr0_ub, vr1_lb, vr1_ub);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
302 return wide_int_range_cross_product (res_lb, res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
303 code, sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
304 vr0_lb, vr0_ub, vr1_lb, vr1_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
305 overflow_undefined);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
306 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
307
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
308 /* Perform a left shift operation on two ranges:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
309
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
310 [RES_LB, RES_UB] = [VR0_LB, VR0_UB] << [VR1_LB, VR1_LB]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
311
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
312 Return TRUE if we were able to perform the operation.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
313
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
314 NOTE: The resulting range must be canonicalized by the caller
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
315 because its contents components may be swapped. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
316
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
317 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
318 wide_int_range_lshift (wide_int &res_lb, wide_int &res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
319 signop sign, unsigned prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
320 const wide_int &vr0_lb, const wide_int &vr0_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
321 const wide_int &vr1_lb, const wide_int &vr1_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
322 bool overflow_undefined)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
323 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
324 /* Transform left shifts by constants into multiplies. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
325 if (wi::eq_p (vr1_lb, vr1_ub))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
326 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
327 unsigned shift = vr1_ub.to_uhwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
328 wide_int tmp = wi::set_bit_in_zero (shift, prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
329 return wide_int_range_multiplicative_op (res_lb, res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
330 MULT_EXPR, sign, prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
331 vr0_lb, vr0_ub, tmp, tmp,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
332 /*overflow_undefined=*/false);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
333 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
334
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
335 int overflow_pos = prec;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
336 if (sign == SIGNED)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
337 overflow_pos -= 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
338 int bound_shift = overflow_pos - vr1_ub.to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
339 /* If bound_shift == HOST_BITS_PER_WIDE_INT, the llshift can
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
340 overflow. However, for that to happen, vr1.max needs to be
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
341 zero, which means vr1 is a singleton range of zero, which
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
342 means it should be handled by the previous LSHIFT_EXPR
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
343 if-clause. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
344 wide_int bound = wi::set_bit_in_zero (bound_shift, prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
345 wide_int complement = ~(bound - 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
346 wide_int low_bound, high_bound;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
347 bool in_bounds = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
348 if (sign == UNSIGNED)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
349 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
350 low_bound = bound;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
351 high_bound = complement;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
352 if (wi::ltu_p (vr0_ub, low_bound))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
353 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
354 /* [5, 6] << [1, 2] == [10, 24]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
355 /* We're shifting out only zeroes, the value increases
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
356 monotonically. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
357 in_bounds = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
358 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
359 else if (wi::ltu_p (high_bound, vr0_lb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
360 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
361 /* [0xffffff00, 0xffffffff] << [1, 2]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
362 == [0xfffffc00, 0xfffffffe]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
363 /* We're shifting out only ones, the value decreases
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
364 monotonically. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
365 in_bounds = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
366 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
367 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
368 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
369 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
370 /* [-1, 1] << [1, 2] == [-4, 4]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
371 low_bound = complement;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
372 high_bound = bound;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
373 if (wi::lts_p (vr0_ub, high_bound)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
374 && wi::lts_p (low_bound, vr0_lb))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
375 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
376 /* For non-negative numbers, we're shifting out only
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
377 zeroes, the value increases monotonically.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
378 For negative numbers, we're shifting out only ones, the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
379 value decreases monotomically. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
380 in_bounds = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
381 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
382 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
383 if (in_bounds)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
384 return wide_int_range_multiplicative_op (res_lb, res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
385 LSHIFT_EXPR, sign, prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
386 vr0_lb, vr0_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
387 vr1_lb, vr1_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
388 overflow_undefined);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
389 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
390 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
391
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
392 /* Return TRUE if a bit operation on two ranges can be easily
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
393 optimized in terms of a mask.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
394
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
395 Basically, for BIT_AND_EXPR or BIT_IOR_EXPR see if we can optimize:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
396
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
397 [LB, UB] op Z
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
398 into:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
399 [LB op Z, UB op Z]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
400
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
401 It is up to the caller to perform the actual folding above. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
402
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
403 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
404 wide_int_range_can_optimize_bit_op (tree_code code,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
405 const wide_int &lb, const wide_int &ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
406 const wide_int &mask)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
407
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
408 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
409 if (code != BIT_AND_EXPR && code != BIT_IOR_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
410 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
411 /* If Z is a constant which (for op | its bitwise not) has n
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
412 consecutive least significant bits cleared followed by m 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
413 consecutive bits set immediately above it and either
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
414 m + n == precision, or (x >> (m + n)) == (y >> (m + n)).
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
415
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
416 The least significant n bits of all the values in the range are
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
417 cleared or set, the m bits above it are preserved and any bits
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
418 above these are required to be the same for all values in the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
419 range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
420
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
421 wide_int w = mask;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
422 int m = 0, n = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
423 if (code == BIT_IOR_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
424 w = ~w;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
425 if (wi::eq_p (w, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
426 n = w.get_precision ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
427 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
428 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
429 n = wi::ctz (w);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
430 w = ~(w | wi::mask (n, false, w.get_precision ()));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
431 if (wi::eq_p (w, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
432 m = w.get_precision () - n;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
433 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
434 m = wi::ctz (w) - n;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
435 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
436 wide_int new_mask = wi::mask (m + n, true, w.get_precision ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
437 if ((new_mask & lb) == (new_mask & ub))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
438 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
439
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
440 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
441 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
442
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
443 /* Helper function for wide_int_range_optimize_bit_op.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
444
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
445 Calculates bounds and mask for a pair of ranges. The mask is the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
446 singleton range among the ranges, if any. The bounds are the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
447 bounds for the remaining range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
448
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
449 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
450 wide_int_range_get_mask_and_bounds (wide_int &mask,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
451 wide_int &lower_bound,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
452 wide_int &upper_bound,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
453 const wide_int &vr0_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
454 const wide_int &vr0_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
455 const wide_int &vr1_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
456 const wide_int &vr1_max)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
457 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
458 if (wi::eq_p (vr1_min, vr1_max))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
459 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
460 mask = vr1_min;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
461 lower_bound = vr0_min;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
462 upper_bound = vr0_max;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
463 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
464 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
465 else if (wi::eq_p (vr0_min, vr0_max))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
466 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
467 mask = vr0_min;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
468 lower_bound = vr1_min;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
469 upper_bound = vr1_max;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
470 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
471 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
472 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
473 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
474
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
475 /* Optimize a bit operation (BIT_AND_EXPR or BIT_IOR_EXPR) if
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
476 possible. If so, return TRUE and store the result in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
477 [RES_LB, RES_UB]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
478
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
479 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
480 wide_int_range_optimize_bit_op (wide_int &res_lb, wide_int &res_ub,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
481 enum tree_code code,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
482 signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
483 const wide_int &vr0_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
484 const wide_int &vr0_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
485 const wide_int &vr1_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
486 const wide_int &vr1_max)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
487 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
488 gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
489
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
490 wide_int lower_bound, upper_bound, mask;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
491 if (!wide_int_range_get_mask_and_bounds (mask, lower_bound, upper_bound,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
492 vr0_min, vr0_max, vr1_min, vr1_max))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
493 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
494 if (wide_int_range_can_optimize_bit_op (code,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
495 lower_bound, upper_bound, mask))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
496 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
497 wi::overflow_type ovf;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
498 wide_int_binop (res_lb, code, lower_bound, mask, sign, &ovf);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
499 wide_int_binop (res_ub, code, upper_bound, mask, sign, &ovf);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
500 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
501 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
502 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
503 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
504
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
505 /* Calculate the XOR of two ranges and store the result in [WMIN,WMAX].
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
506 The two input ranges are described by their MUST_BE_NONZERO and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
507 MAY_BE_NONZERO bit masks.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
508
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
509 Return TRUE if we were able to successfully calculate the new range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
510
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
511 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
512 wide_int_range_bit_xor (wide_int &wmin, wide_int &wmax,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
513 signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
514 unsigned prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
515 const wide_int &must_be_nonzero0,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
516 const wide_int &may_be_nonzero0,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
517 const wide_int &must_be_nonzero1,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
518 const wide_int &may_be_nonzero1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
519 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
520 wide_int result_zero_bits = ((must_be_nonzero0 & must_be_nonzero1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
521 | ~(may_be_nonzero0 | may_be_nonzero1));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
522 wide_int result_one_bits
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
523 = (wi::bit_and_not (must_be_nonzero0, may_be_nonzero1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
524 | wi::bit_and_not (must_be_nonzero1, may_be_nonzero0));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
525 wmax = ~result_zero_bits;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
526 wmin = result_one_bits;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
527 /* If the range has all positive or all negative values, the result
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
528 is better than VARYING. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
529 if (wi::lt_p (wmin, 0, sign) || wi::ge_p (wmax, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
530 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
531 wmin = wi::min_value (prec, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
532 wmax = wi::max_value (prec, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
533 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
534 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
535
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
536 /* Calculate the IOR of two ranges and store the result in [WMIN,WMAX].
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
537 Return TRUE if we were able to successfully calculate the new range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
538
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
539 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
540 wide_int_range_bit_ior (wide_int &wmin, wide_int &wmax,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
541 signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
542 const wide_int &vr0_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
543 const wide_int &vr0_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
544 const wide_int &vr1_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
545 const wide_int &vr1_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
546 const wide_int &must_be_nonzero0,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
547 const wide_int &may_be_nonzero0,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
548 const wide_int &must_be_nonzero1,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
549 const wide_int &may_be_nonzero1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
550 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
551 if (wide_int_range_optimize_bit_op (wmin, wmax, BIT_IOR_EXPR, sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
552 vr0_min, vr0_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
553 vr1_min, vr1_max))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
554 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
555 wmin = must_be_nonzero0 | must_be_nonzero1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
556 wmax = may_be_nonzero0 | may_be_nonzero1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
557 /* If the input ranges contain only positive values we can
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
558 truncate the minimum of the result range to the maximum
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
559 of the input range minima. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
560 if (wi::ge_p (vr0_min, 0, sign)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
561 && wi::ge_p (vr1_min, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
562 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
563 wmin = wi::max (wmin, vr0_min, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
564 wmin = wi::max (wmin, vr1_min, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
565 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
566 /* If either input range contains only negative values
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
567 we can truncate the minimum of the result range to the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
568 respective minimum range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
569 if (wi::lt_p (vr0_max, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
570 wmin = wi::max (wmin, vr0_min, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
571 if (wi::lt_p (vr1_max, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
572 wmin = wi::max (wmin, vr1_min, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
573 /* If the limits got swapped around, indicate error so we can adjust
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
574 the range to VARYING. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
575 if (wi::gt_p (wmin, wmax,sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
576 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
577 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
578 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
579
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
580 /* Calculate the bitwise AND of two ranges and store the result in [WMIN,WMAX].
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
581 Return TRUE if we were able to successfully calculate the new range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
582
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
583 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
584 wide_int_range_bit_and (wide_int &wmin, wide_int &wmax,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
585 signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
586 unsigned prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
587 const wide_int &vr0_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
588 const wide_int &vr0_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
589 const wide_int &vr1_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
590 const wide_int &vr1_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
591 const wide_int &must_be_nonzero0,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
592 const wide_int &may_be_nonzero0,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
593 const wide_int &must_be_nonzero1,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
594 const wide_int &may_be_nonzero1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
595 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
596 if (wide_int_range_optimize_bit_op (wmin, wmax, BIT_AND_EXPR, sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
597 vr0_min, vr0_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
598 vr1_min, vr1_max))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
599 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
600 wmin = must_be_nonzero0 & must_be_nonzero1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
601 wmax = may_be_nonzero0 & may_be_nonzero1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
602 /* If both input ranges contain only negative values we can
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
603 truncate the result range maximum to the minimum of the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
604 input range maxima. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
605 if (wi::lt_p (vr0_max, 0, sign) && wi::lt_p (vr1_max, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
606 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
607 wmax = wi::min (wmax, vr0_max, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
608 wmax = wi::min (wmax, vr1_max, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
609 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
610 /* If either input range contains only non-negative values
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
611 we can truncate the result range maximum to the respective
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
612 maximum of the input range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
613 if (wi::ge_p (vr0_min, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
614 wmax = wi::min (wmax, vr0_max, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
615 if (wi::ge_p (vr1_min, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
616 wmax = wi::min (wmax, vr1_max, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
617 /* PR68217: In case of signed & sign-bit-CST should
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
618 result in [-INF, 0] instead of [-INF, INF]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
619 if (wi::gt_p (wmin, wmax, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
620 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
621 wide_int sign_bit = wi::set_bit_in_zero (prec - 1, prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
622 if (sign == SIGNED
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
623 && ((wi::eq_p (vr0_min, vr0_max)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
624 && !wi::cmps (vr0_min, sign_bit))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
625 || (wi::eq_p (vr1_min, vr1_max)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
626 && !wi::cmps (vr1_min, sign_bit))))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
627 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
628 wmin = wi::min_value (prec, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
629 wmax = wi::zero (prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
630 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
631 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
632 /* If the limits got swapped around, indicate error so we can adjust
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
633 the range to VARYING. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
634 if (wi::gt_p (wmin, wmax,sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
635 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
636 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
637 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
638
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
639 /* Calculate TRUNC_MOD_EXPR on two ranges and store the result in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
640 [WMIN,WMAX]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
641
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
642 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
643 wide_int_range_trunc_mod (wide_int &wmin, wide_int &wmax,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
644 signop sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
645 unsigned prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
646 const wide_int &vr0_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
647 const wide_int &vr0_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
648 const wide_int &vr1_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
649 const wide_int &vr1_max)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
650 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
651 wide_int tmp;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
652
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
653 /* ABS (A % B) < ABS (B) and either
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
654 0 <= A % B <= A or A <= A % B <= 0. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
655 wmax = vr1_max - 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
656 if (sign == SIGNED)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
657 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
658 tmp = -1 - vr1_min;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
659 wmax = wi::smax (wmax, tmp);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
660 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
661
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
662 if (sign == UNSIGNED)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
663 wmin = wi::zero (prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
664 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
665 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
666 wmin = -wmax;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
667 tmp = vr0_min;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
668 if (wi::gts_p (tmp, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
669 tmp = wi::zero (prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
670 wmin = wi::smax (wmin, tmp);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
671 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
672 tmp = vr0_max;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
673 if (sign == SIGNED && wi::neg_p (tmp))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
674 tmp = wi::zero (prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
675 wmax = wi::min (wmax, tmp, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
676 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
677
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
678 /* Calculate ABS_EXPR on a range and store the result in [MIN, MAX]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
679
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
680 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
681 wide_int_range_abs (wide_int &min, wide_int &max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
682 signop sign, unsigned prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
683 const wide_int &vr0_min, const wide_int &vr0_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
684 bool overflow_undefined)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
685 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
686 /* Pass through VR0 the easy cases. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
687 if (sign == UNSIGNED || wi::ge_p (vr0_min, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
688 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
689 min = vr0_min;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
690 max = vr0_max;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
691 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
692 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
693
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
694 /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
695 useful range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
696 wide_int min_value = wi::min_value (prec, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
697 wide_int max_value = wi::max_value (prec, sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
698 if (!overflow_undefined && wi::eq_p (vr0_min, min_value))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
699 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
700
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
701 /* ABS_EXPR may flip the range around, if the original range
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
702 included negative values. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
703 if (wi::eq_p (vr0_min, min_value))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
704 min = max_value;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
705 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
706 min = wi::abs (vr0_min);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
707 if (wi::eq_p (vr0_max, min_value))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
708 max = max_value;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
709 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
710 max = wi::abs (vr0_max);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
711
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
712 /* If the range contains zero then we know that the minimum value in the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
713 range will be zero. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
714 if (wi::le_p (vr0_min, 0, sign) && wi::ge_p (vr0_max, 0, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
715 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
716 if (wi::gt_p (min, max, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
717 max = min;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
718 min = wi::zero (prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
719 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
720 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
721 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
722 /* If the range was reversed, swap MIN and MAX. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
723 if (wi::gt_p (min, max, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
724 std::swap (min, max);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
725 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
726
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
727 /* If the new range has its limits swapped around (MIN > MAX), then
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
728 the operation caused one of them to wrap around. The only thing
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
729 we know is that the result is positive. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
730 if (wi::gt_p (min, max, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
731 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
732 min = wi::zero (prec);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
733 max = max_value;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
734 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
735 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
736 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
737
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
738 /* Convert range in [VR0_MIN, VR0_MAX] with INNER_SIGN and INNER_PREC,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
739 to a range in [MIN, MAX] with OUTER_SIGN and OUTER_PREC.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
740
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
741 Return TRUE if we were able to successfully calculate the new range.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
742
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
743 Caller is responsible for canonicalizing the resulting range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
744
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
745 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
746 wide_int_range_convert (wide_int &min, wide_int &max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
747 signop inner_sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
748 unsigned inner_prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
749 signop outer_sign,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
750 unsigned outer_prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
751 const wide_int &vr0_min,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
752 const wide_int &vr0_max)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
753 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
754 /* If the conversion is not truncating we can convert the min and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
755 max values and canonicalize the resulting range. Otherwise we
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
756 can do the conversion if the size of the range is less than what
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
757 the precision of the target type can represent. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
758 if (outer_prec >= inner_prec
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
759 || wi::rshift (wi::sub (vr0_max, vr0_min),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
760 wi::uhwi (outer_prec, inner_prec),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
761 inner_sign) == 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
762 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
763 min = wide_int::from (vr0_min, outer_prec, inner_sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
764 max = wide_int::from (vr0_max, outer_prec, inner_sign);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
765 return (!wi::eq_p (min, wi::min_value (outer_prec, outer_sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
766 || !wi::eq_p (max, wi::max_value (outer_prec, outer_sign)));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
767 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
768 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
769 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
770
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
771 /* Calculate a division operation on two ranges and store the result in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
772 [WMIN, WMAX] U [EXTRA_MIN, EXTRA_MAX].
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
773
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
774 If EXTRA_RANGE_P is set upon return, EXTRA_MIN/EXTRA_MAX hold
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
775 meaningful information, otherwise they should be ignored.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
776
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
777 Return TRUE if we were able to successfully calculate the new range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
778
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
779 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
780 wide_int_range_div (wide_int &wmin, wide_int &wmax,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
781 tree_code code, signop sign, unsigned prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
782 const wide_int &dividend_min, const wide_int &dividend_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
783 const wide_int &divisor_min, const wide_int &divisor_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
784 bool overflow_undefined,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
785 bool &extra_range_p,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
786 wide_int &extra_min, wide_int &extra_max)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
787 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
788 extra_range_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
789
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
790 /* If we know we won't divide by zero, just do the division. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
791 if (!wide_int_range_includes_zero_p (divisor_min, divisor_max, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
792 return wide_int_range_multiplicative_op (wmin, wmax, code, sign, prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
793 dividend_min, dividend_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
794 divisor_min, divisor_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
795 overflow_undefined);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
796
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
797 /* If flag_non_call_exceptions, we must not eliminate a division
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
798 by zero. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
799 if (cfun->can_throw_non_call_exceptions)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
800 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
801
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
802 /* If we're definitely dividing by zero, there's nothing to do. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
803 if (wide_int_range_zero_p (divisor_min, divisor_max, prec))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
804 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
805
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
806 /* Perform the division in 2 parts, [LB, -1] and [1, UB],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
807 which will skip any division by zero.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
808
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
809 First divide by the negative numbers, if any. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
810 if (wi::neg_p (divisor_min, sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
811 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
812 if (!wide_int_range_multiplicative_op (wmin, wmax,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
813 code, sign, prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
814 dividend_min, dividend_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
815 divisor_min, wi::minus_one (prec),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
816 overflow_undefined))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
817 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
818 extra_range_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
819 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
820 /* Then divide by the non-zero positive numbers, if any. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
821 if (wi::gt_p (divisor_max, wi::zero (prec), sign))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
822 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
823 if (!wide_int_range_multiplicative_op (extra_range_p ? extra_min : wmin,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
824 extra_range_p ? extra_max : wmax,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
825 code, sign, prec,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
826 dividend_min, dividend_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
827 wi::one (prec), divisor_max,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
828 overflow_undefined))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
829 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
830 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
831 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
832 extra_range_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
833 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
834 }