Branch data Line data Source code
1 : : /* Header file for mixed range operator class.
2 : : Copyright (C) 2017-2025 Free Software Foundation, Inc.
3 : : Contributed by Andrew MacLeod <amacleod@redhat.com>
4 : : and Aldy Hernandez <aldyh@redhat.com>.
5 : :
6 : : This file is part of GCC.
7 : :
8 : : GCC is free software; you can redistribute it and/or modify it under
9 : : the terms of the GNU General Public License as published by the Free
10 : : Software Foundation; either version 3, or (at your option) any later
11 : : version.
12 : :
13 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : : for more details.
17 : :
18 : : You should have received a copy of the GNU General Public License
19 : : along with GCC; see the file COPYING3. If not see
20 : : <http://www.gnu.org/licenses/>. */
21 : :
22 : : #ifndef GCC_RANGE_OP_MIXED_H
23 : : #define GCC_RANGE_OP_MIXED_H
24 : :
25 : : void update_known_bitmask (vrange &, tree_code, const vrange &, const vrange &);
26 : : bool minus_op1_op2_relation_effect (irange &lhs_range, tree type,
27 : : const irange &, const irange &,
28 : : relation_kind rel);
29 : :
30 : :
31 : : // Return TRUE if 0 is within [WMIN, WMAX].
32 : :
33 : : inline bool
34 : 19211443 : wi_includes_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
35 : : {
36 : 19211443 : signop sign = TYPE_SIGN (type);
37 : 19211443 : return wi::le_p (wmin, 0, sign) && wi::ge_p (wmax, 0, sign);
38 : : }
39 : :
40 : : // Return TRUE if [WMIN, WMAX] is the singleton 0.
41 : :
42 : : inline bool
43 : 2002663 : wi_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
44 : : {
45 : 2002663 : unsigned prec = TYPE_PRECISION (type);
46 : 2399974 : return wmin == wmax && wi::eq_p (wmin, wi::zero (prec));
47 : : }
48 : :
49 : :
50 : : enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL };
51 : : bool_range_state get_bool_state (vrange &r, const vrange &lhs, tree val_type);
52 : :
53 : : // If the range of either op1 or op2 is undefined, set the result to
54 : : // varying and return TRUE. If the caller truly cares about a result,
55 : : // they should pass in a varying if it has an undefined that it wants
56 : : // treated as a varying.
57 : :
58 : : inline bool
59 : 300759938 : empty_range_varying (vrange &r, tree type,
60 : : const vrange &op1, const vrange & op2)
61 : : {
62 : 300673248 : if (op1.undefined_p () || op2.undefined_p ())
63 : : {
64 : 5570921 : r.set_varying (type);
65 : 5472063 : return true;
66 : : }
67 : : else
68 : : return false;
69 : : }
70 : :
71 : : // For relation opcodes, first try to see if the supplied relation
72 : : // forces a true or false result, and return that.
73 : : // Then check for undefined operands. If none of this applies,
74 : : // return false.
75 : :
76 : : inline bool
77 : 87062143 : relop_early_resolve (irange &r, tree type, const vrange &op1,
78 : : const vrange &op2, relation_trio trio,
79 : : relation_kind my_rel)
80 : : {
81 : 87062143 : relation_kind rel = trio.op1_op2 ();
82 : : // If known relation is a complete subset of this relation, always true.
83 : 87062143 : if (relation_union (rel, my_rel) == my_rel)
84 : : {
85 : 49961 : r = range_true (type);
86 : 49961 : return true;
87 : : }
88 : :
89 : : // If known relation has no subset of this relation, always false.
90 : 87012182 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
91 : : {
92 : 45264 : r = range_false (type);
93 : 45264 : return true;
94 : : }
95 : :
96 : : // If either operand is undefined, return VARYING.
97 : 86966918 : if (empty_range_varying (r, type, op1, op2))
98 : 98858 : return true;
99 : :
100 : : return false;
101 : : }
102 : :
103 : : // ----------------------------------------------------------------------
104 : : // Mixed Mode Operators.
105 : : // ----------------------------------------------------------------------
106 : :
107 : : class operator_equal : public range_operator
108 : : {
109 : : public:
110 : : using range_operator::fold_range;
111 : : using range_operator::op1_range;
112 : : using range_operator::op2_range;
113 : : using range_operator::op1_op2_relation;
114 : : using range_operator::update_bitmask;
115 : : bool fold_range (irange &r, tree type,
116 : : const irange &op1, const irange &op2,
117 : : relation_trio = TRIO_VARYING) const final override;
118 : : bool fold_range (irange &r, tree type,
119 : : const prange &op1, const prange &op2,
120 : : relation_trio = TRIO_VARYING) const final override;
121 : : bool fold_range (irange &r, tree type,
122 : : const frange &op1, const frange &op2,
123 : : relation_trio = TRIO_VARYING) const final override;
124 : :
125 : : bool op1_range (irange &r, tree type,
126 : : const irange &lhs, const irange &val,
127 : : relation_trio = TRIO_VARYING) const final override;
128 : : bool op1_range (prange &r, tree type,
129 : : const irange &lhs, const prange &val,
130 : : relation_trio = TRIO_VARYING) const final override;
131 : : bool op1_range (frange &r, tree type,
132 : : const irange &lhs, const frange &op2,
133 : : relation_trio = TRIO_VARYING) const final override;
134 : :
135 : : bool op2_range (irange &r, tree type,
136 : : const irange &lhs, const irange &val,
137 : : relation_trio = TRIO_VARYING) const final override;
138 : : bool op2_range (prange &r, tree type,
139 : : const irange &lhs, const prange &val,
140 : : relation_trio = TRIO_VARYING) const final override;
141 : : bool op2_range (frange &r, tree type,
142 : : const irange &lhs, const frange &op1,
143 : : relation_trio rel = TRIO_VARYING) const final override;
144 : :
145 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
146 : : const irange &) const final override;
147 : : relation_kind op1_op2_relation (const irange &lhs, const prange &,
148 : : const prange &) const final override;
149 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
150 : : const frange &) const final override;
151 : : void update_bitmask (irange &r, const irange &lh,
152 : : const irange &rh) const final override;
153 : : // Check op1 and op2 for compatibility.
154 : 41374180 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
155 : 41374180 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
156 : : };
157 : :
158 : : class operator_not_equal : public range_operator
159 : : {
160 : : public:
161 : : using range_operator::fold_range;
162 : : using range_operator::op1_range;
163 : : using range_operator::op2_range;
164 : : using range_operator::op1_op2_relation;
165 : : using range_operator::update_bitmask;
166 : : bool fold_range (irange &r, tree type,
167 : : const irange &op1, const irange &op2,
168 : : relation_trio = TRIO_VARYING) const final override;
169 : : bool fold_range (irange &r, tree type,
170 : : const prange &op1, const prange &op2,
171 : : relation_trio rel = TRIO_VARYING) const final override;
172 : : bool fold_range (irange &r, tree type,
173 : : const frange &op1, const frange &op2,
174 : : relation_trio rel = TRIO_VARYING) const final override;
175 : :
176 : : bool op1_range (irange &r, tree type,
177 : : const irange &lhs, const irange &op2,
178 : : relation_trio = TRIO_VARYING) const final override;
179 : : bool op1_range (prange &r, tree type,
180 : : const irange &lhs, const prange &op2,
181 : : relation_trio = TRIO_VARYING) const final override;
182 : : bool op1_range (frange &r, tree type,
183 : : const irange &lhs, const frange &op2,
184 : : relation_trio = TRIO_VARYING) const final override;
185 : :
186 : : bool op2_range (irange &r, tree type,
187 : : const irange &lhs, const irange &op1,
188 : : relation_trio = TRIO_VARYING) const final override;
189 : : bool op2_range (prange &r, tree type,
190 : : const irange &lhs, const prange &op1,
191 : : relation_trio = TRIO_VARYING) const final override;
192 : : bool op2_range (frange &r, tree type,
193 : : const irange &lhs, const frange &op1,
194 : : relation_trio = TRIO_VARYING) const final override;
195 : :
196 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
197 : : const irange &) const final override;
198 : : relation_kind op1_op2_relation (const irange &lhs, const prange &,
199 : : const prange &) const final override;
200 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
201 : : const frange &) const final override;
202 : : void update_bitmask (irange &r, const irange &lh,
203 : : const irange &rh) const final override;
204 : : // Check op1 and op2 for compatibility.
205 : 63726325 : bool operand_check_p (tree t0, tree t1, tree t2) const final override
206 : 63726325 : { return range_compatible_p (t1, t2) && INTEGRAL_TYPE_P (t0); }
207 : : };
208 : :
209 : : class operator_lt : public range_operator
210 : : {
211 : : public:
212 : : using range_operator::fold_range;
213 : : using range_operator::op1_range;
214 : : using range_operator::op2_range;
215 : : using range_operator::op1_op2_relation;
216 : : using range_operator::update_bitmask;
217 : : bool fold_range (irange &r, tree type,
218 : : const irange &op1, const irange &op2,
219 : : relation_trio = TRIO_VARYING) const final override;
220 : : bool fold_range (irange &r, tree type,
221 : : const prange &op1, const prange &op2,
222 : : relation_trio = TRIO_VARYING) const final override;
223 : : bool fold_range (irange &r, tree type,
224 : : const frange &op1, const frange &op2,
225 : : relation_trio = TRIO_VARYING) const final override;
226 : : bool op1_range (irange &r, tree type,
227 : : const irange &lhs, const irange &op2,
228 : : relation_trio = TRIO_VARYING) const final override;
229 : : bool op1_range (prange &r, tree type,
230 : : const irange &lhs, const prange &op2,
231 : : relation_trio = TRIO_VARYING) const final override;
232 : : bool op1_range (frange &r, tree type,
233 : : const irange &lhs, const frange &op2,
234 : : relation_trio = TRIO_VARYING) const final override;
235 : : bool op2_range (irange &r, tree type,
236 : : const irange &lhs, const irange &op1,
237 : : relation_trio = TRIO_VARYING) const final override;
238 : : bool op2_range (prange &r, tree type,
239 : : const irange &lhs, const prange &op1,
240 : : relation_trio = TRIO_VARYING) const final override;
241 : : bool op2_range (frange &r, tree type,
242 : : const irange &lhs, const frange &op1,
243 : : relation_trio = TRIO_VARYING) const final override;
244 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
245 : : const irange &) const final override;
246 : : relation_kind op1_op2_relation (const irange &lhs, const prange &,
247 : : const prange &) const final override;
248 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
249 : : const frange &) const final override;
250 : : void update_bitmask (irange &r, const irange &lh,
251 : : const irange &rh) const final override;
252 : : // Check op1 and op2 for compatibility.
253 : 16855900 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
254 : 16855900 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
255 : : };
256 : :
257 : : class operator_le : public range_operator
258 : : {
259 : : public:
260 : : using range_operator::fold_range;
261 : : using range_operator::op1_range;
262 : : using range_operator::op2_range;
263 : : using range_operator::op1_op2_relation;
264 : : using range_operator::update_bitmask;
265 : : bool fold_range (irange &r, tree type,
266 : : const irange &op1, const irange &op2,
267 : : relation_trio = TRIO_VARYING) const final override;
268 : : bool fold_range (irange &r, tree type,
269 : : const prange &op1, const prange &op2,
270 : : relation_trio = TRIO_VARYING) const final override;
271 : : bool fold_range (irange &r, tree type,
272 : : const frange &op1, const frange &op2,
273 : : relation_trio rel = TRIO_VARYING) const final override;
274 : :
275 : : bool op1_range (irange &r, tree type,
276 : : const irange &lhs, const irange &op2,
277 : : relation_trio = TRIO_VARYING) const final override;
278 : : bool op1_range (prange &r, tree type,
279 : : const irange &lhs, const prange &op2,
280 : : relation_trio = TRIO_VARYING) const final override;
281 : : bool op1_range (frange &r, tree type,
282 : : const irange &lhs, const frange &op2,
283 : : relation_trio rel = TRIO_VARYING) const final override;
284 : :
285 : : bool op2_range (irange &r, tree type,
286 : : const irange &lhs, const irange &op1,
287 : : relation_trio = TRIO_VARYING) const final override;
288 : : bool op2_range (prange &r, tree type,
289 : : const irange &lhs, const prange &op1,
290 : : relation_trio = TRIO_VARYING) const final override;
291 : : bool op2_range (frange &r, tree type,
292 : : const irange &lhs, const frange &op1,
293 : : relation_trio rel = TRIO_VARYING) const final override;
294 : :
295 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
296 : : const irange &) const final override;
297 : : relation_kind op1_op2_relation (const irange &lhs, const prange &,
298 : : const prange &) const final override;
299 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
300 : : const frange &) const final override;
301 : : void update_bitmask (irange &r, const irange &lh,
302 : : const irange &rh) const final override;
303 : : // Check op1 and op2 for compatibility.
304 : 12961449 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
305 : 12961449 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
306 : : };
307 : :
308 : : class operator_gt : public range_operator
309 : : {
310 : : public:
311 : : using range_operator::fold_range;
312 : : using range_operator::op1_range;
313 : : using range_operator::op2_range;
314 : : using range_operator::op1_op2_relation;
315 : : using range_operator::update_bitmask;
316 : : bool fold_range (irange &r, tree type,
317 : : const irange &op1, const irange &op2,
318 : : relation_trio = TRIO_VARYING) const final override;
319 : : bool fold_range (irange &r, tree type,
320 : : const prange &op1, const prange &op2,
321 : : relation_trio = TRIO_VARYING) const final override;
322 : : bool fold_range (irange &r, tree type,
323 : : const frange &op1, const frange &op2,
324 : : relation_trio = TRIO_VARYING) const final override;
325 : :
326 : : bool op1_range (irange &r, tree type,
327 : : const irange &lhs, const irange &op2,
328 : : relation_trio = TRIO_VARYING) const final override;
329 : : bool op1_range (prange &r, tree type,
330 : : const irange &lhs, const prange &op2,
331 : : relation_trio = TRIO_VARYING) const final override;
332 : : bool op1_range (frange &r, tree type,
333 : : const irange &lhs, const frange &op2,
334 : : relation_trio = TRIO_VARYING) const final override;
335 : :
336 : : bool op2_range (irange &r, tree type,
337 : : const irange &lhs, const irange &op1,
338 : : relation_trio = TRIO_VARYING) const final override;
339 : : bool op2_range (prange &r, tree type,
340 : : const irange &lhs, const prange &op1,
341 : : relation_trio = TRIO_VARYING) const final override;
342 : : bool op2_range (frange &r, tree type,
343 : : const irange &lhs, const frange &op1,
344 : : relation_trio = TRIO_VARYING) const final override;
345 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
346 : : const irange &) const final override;
347 : : relation_kind op1_op2_relation (const irange &lhs, const prange &,
348 : : const prange &) const final override;
349 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
350 : : const frange &) const final override;
351 : : void update_bitmask (irange &r, const irange &lh,
352 : : const irange &rh) const final override;
353 : : // Check op1 and op2 for compatibility.
354 : 28091657 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
355 : 28091657 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
356 : : };
357 : :
358 : : class operator_ge : public range_operator
359 : : {
360 : : public:
361 : : using range_operator::fold_range;
362 : : using range_operator::op1_range;
363 : : using range_operator::op2_range;
364 : : using range_operator::op1_op2_relation;
365 : : using range_operator::update_bitmask;
366 : : bool fold_range (irange &r, tree type,
367 : : const irange &op1, const irange &op2,
368 : : relation_trio = TRIO_VARYING) const final override;
369 : : bool fold_range (irange &r, tree type,
370 : : const prange &op1, const prange &op2,
371 : : relation_trio = TRIO_VARYING) const final override;
372 : : bool fold_range (irange &r, tree type,
373 : : const frange &op1, const frange &op2,
374 : : relation_trio = TRIO_VARYING) const final override;
375 : :
376 : : bool op1_range (irange &r, tree type,
377 : : const irange &lhs, const irange &op2,
378 : : relation_trio = TRIO_VARYING) const final override;
379 : : bool op1_range (prange &r, tree type,
380 : : const irange &lhs, const prange &op2,
381 : : relation_trio = TRIO_VARYING) const final override;
382 : : bool op1_range (frange &r, tree type,
383 : : const irange &lhs, const frange &op2,
384 : : relation_trio = TRIO_VARYING) const final override;
385 : :
386 : : bool op2_range (irange &r, tree type,
387 : : const irange &lhs, const irange &op1,
388 : : relation_trio = TRIO_VARYING) const final override;
389 : : bool op2_range (prange &r, tree type,
390 : : const irange &lhs, const prange &op1,
391 : : relation_trio = TRIO_VARYING) const final override;
392 : : bool op2_range (frange &r, tree type,
393 : : const irange &lhs, const frange &op1,
394 : : relation_trio = TRIO_VARYING) const final override;
395 : :
396 : : relation_kind op1_op2_relation (const irange &lhs, const irange &,
397 : : const irange &) const final override;
398 : : relation_kind op1_op2_relation (const irange &lhs, const prange &,
399 : : const prange &) const final override;
400 : : relation_kind op1_op2_relation (const irange &lhs, const frange &,
401 : : const frange &) const final override;
402 : : void update_bitmask (irange &r, const irange &lh,
403 : : const irange &rh) const final override;
404 : : // Check op1 and op2 for compatibility.
405 : 8389039 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
406 : 8389039 : { return range_compatible_p (t2, t3) && INTEGRAL_TYPE_P (t1); }
407 : : };
408 : :
409 : : class operator_identity : public range_operator
410 : : {
411 : : public:
412 : : using range_operator::fold_range;
413 : : using range_operator::op1_range;
414 : : using range_operator::lhs_op1_relation;
415 : : bool fold_range (irange &r, tree type,
416 : : const irange &op1, const irange &op2,
417 : : relation_trio rel = TRIO_VARYING) const final override;
418 : : bool fold_range (prange &r, tree type,
419 : : const prange &op1, const prange &op2,
420 : : relation_trio rel = TRIO_VARYING) const final override;
421 : : bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
422 : : const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
423 : : relation_trio = TRIO_VARYING) const final override;
424 : : bool op1_range (irange &r, tree type,
425 : : const irange &lhs, const irange &op2,
426 : : relation_trio rel = TRIO_VARYING) const final override;
427 : : bool op1_range (prange &r, tree type,
428 : : const prange &lhs, const prange &op2,
429 : : relation_trio rel = TRIO_VARYING) const final override;
430 : : bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
431 : : const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
432 : : relation_trio = TRIO_VARYING) const final override;
433 : : relation_kind lhs_op1_relation (const irange &lhs,
434 : : const irange &op1, const irange &op2,
435 : : relation_kind rel) const final override;
436 : : relation_kind lhs_op1_relation (const prange &lhs,
437 : : const prange &op1, const prange &op2,
438 : : relation_kind rel) const final override;
439 : : };
440 : :
441 : : class operator_cst : public range_operator
442 : : {
443 : : public:
444 : : using range_operator::fold_range;
445 : : bool fold_range (irange &r, tree type,
446 : : const irange &op1, const irange &op2,
447 : : relation_trio rel = TRIO_VARYING) const final override;
448 : : bool fold_range (prange &r, tree type,
449 : : const prange &op1, const prange &op2,
450 : : relation_trio rel = TRIO_VARYING) const final override;
451 : : bool fold_range (frange &r, tree type,
452 : : const frange &op1, const frange &op2,
453 : : relation_trio = TRIO_VARYING) const final override;
454 : : };
455 : :
456 : :
457 : : class operator_cast: public range_operator
458 : : {
459 : : public:
460 : : using range_operator::fold_range;
461 : : using range_operator::op1_range;
462 : : using range_operator::lhs_op1_relation;
463 : : using range_operator::update_bitmask;
464 : : bool fold_range (irange &r, tree type,
465 : : const irange &op1, const irange &op2,
466 : : relation_trio rel = TRIO_VARYING) const final override;
467 : : bool fold_range (prange &r, tree type,
468 : : const prange &op1, const prange &op2,
469 : : relation_trio rel = TRIO_VARYING) const final override;
470 : : bool fold_range (irange &r, tree type,
471 : : const prange &op1, const irange &op2,
472 : : relation_trio rel = TRIO_VARYING) const final override;
473 : : bool fold_range (prange &r, tree type,
474 : : const irange &op1, const prange &op2,
475 : : relation_trio rel = TRIO_VARYING) const final override;
476 : : bool fold_range (frange &r, tree type,
477 : : const frange &op1, const frange &op2,
478 : : relation_trio = TRIO_VARYING) const final override;
479 : : bool fold_range (irange &r, tree type,
480 : : const frange &op1, const irange &op2,
481 : : relation_trio = TRIO_VARYING) const final override;
482 : : bool fold_range (frange &r, tree type,
483 : : const irange &op1, const frange &op2,
484 : : relation_trio = TRIO_VARYING) const final override;
485 : :
486 : : bool op1_range (irange &r, tree type,
487 : : const irange &lhs, const irange &op2,
488 : : relation_trio rel = TRIO_VARYING) const final override;
489 : : bool op1_range (prange &r, tree type,
490 : : const prange &lhs, const prange &op2,
491 : : relation_trio rel = TRIO_VARYING) const final override;
492 : : bool op1_range (irange &r, tree type,
493 : : const prange &lhs, const irange &op2,
494 : : relation_trio rel = TRIO_VARYING) const final override;
495 : : bool op1_range (prange &r, tree type,
496 : : const irange &lhs, const prange &op2,
497 : : relation_trio rel = TRIO_VARYING) const final override;
498 : : bool op1_range (frange &r, tree type,
499 : : const frange &lhs, const frange &op2,
500 : : relation_trio = TRIO_VARYING) const final override;
501 : : bool op1_range (frange &r, tree type,
502 : : const irange &lhs, const frange &op2,
503 : : relation_trio = TRIO_VARYING) const final override;
504 : : bool op1_range (irange &r, tree type,
505 : : const frange &lhs, const irange &op2,
506 : : relation_trio = TRIO_VARYING) const final override;
507 : :
508 : : relation_kind lhs_op1_relation (const irange &lhs,
509 : : const irange &op1, const irange &op2,
510 : : relation_kind) const final override;
511 : : relation_kind lhs_op1_relation (const prange &lhs,
512 : : const prange &op1, const prange &op2,
513 : : relation_kind) const final override;
514 : : relation_kind lhs_op1_relation (const prange &lhs,
515 : : const irange &op1, const irange &op2,
516 : : relation_kind) const final override;
517 : : relation_kind lhs_op1_relation (const irange &lhs,
518 : : const prange &op1, const prange &op2,
519 : : relation_kind) const final override;
520 : : void update_bitmask (irange &r, const irange &lh,
521 : : const irange &rh) const final override;
522 : : private:
523 : : bool truncating_cast_p (const irange &inner, const irange &outer) const;
524 : : bool inside_domain_p (const wide_int &min, const wide_int &max,
525 : : const irange &outer) const;
526 : : void fold_pair (irange &r, unsigned index, const irange &inner,
527 : : const irange &outer) const;
528 : : };
529 : :
530 : :
531 : : class operator_view : public range_operator
532 : : {
533 : : public:
534 : : using range_operator::fold_range;
535 : : using range_operator::op1_range;
536 : : using range_operator::update_bitmask;
537 : : bool fold_range (irange &r, tree type,
538 : : const irange &op1, const irange &op2,
539 : : relation_trio rel = TRIO_VARYING) const override;
540 : : bool fold_range (prange &r, tree type,
541 : : const prange &op1, const prange &op2,
542 : : relation_trio rel = TRIO_VARYING) const final override;
543 : : bool fold_range (irange &r, tree type,
544 : : const prange &op1, const irange &op2,
545 : : relation_trio rel = TRIO_VARYING) const final override;
546 : : bool fold_range (prange &r, tree type,
547 : : const irange &op1, const prange &op2,
548 : : relation_trio rel = TRIO_VARYING) const final override;
549 : :
550 : : bool op1_range (irange &r, tree type,
551 : : const irange &lhs, const irange &op2,
552 : : relation_trio rel = TRIO_VARYING) const override;
553 : : bool op1_range (prange &r, tree type,
554 : : const prange &lhs, const prange &op2,
555 : : relation_trio rel = TRIO_VARYING) const final override;
556 : : bool op1_range (irange &r, tree type,
557 : : const prange &lhs, const irange &op2,
558 : : relation_trio rel = TRIO_VARYING) const final override;
559 : : bool op1_range (prange &r, tree type,
560 : : const irange &lhs, const prange &op2,
561 : : relation_trio rel = TRIO_VARYING) const final override;
562 : :
563 : : void update_bitmask (irange &r, const irange &lh,
564 : : const irange &) const final override;
565 : : private:
566 : : // VIEW_CONVERT_EXPR works much like a cast between integral values, so use
567 : : // the cast operator. Non-integrals are not handled as yet.
568 : : operator_cast m_cast;
569 : : };
570 : :
571 : : class operator_plus : public range_operator
572 : : {
573 : : public:
574 : : using range_operator::op1_range;
575 : : using range_operator::op2_range;
576 : : using range_operator::lhs_op1_relation;
577 : : using range_operator::lhs_op2_relation;
578 : : using range_operator::update_bitmask;
579 : : bool op1_range (irange &r, tree type,
580 : : const irange &lhs, const irange &op2,
581 : : relation_trio) const final override;
582 : : bool op1_range (frange &r, tree type,
583 : : const frange &lhs, const frange &op2,
584 : : relation_trio = TRIO_VARYING) const final override;
585 : :
586 : : bool op2_range (irange &r, tree type,
587 : : const irange &lhs, const irange &op1,
588 : : relation_trio) const final override;
589 : : bool op2_range (frange &r, tree type,
590 : : const frange &lhs, const frange &op1,
591 : : relation_trio = TRIO_VARYING) const final override;
592 : :
593 : : relation_kind lhs_op1_relation (const irange &lhs, const irange &op1,
594 : : const irange &op2,
595 : : relation_kind rel) const final override;
596 : : relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
597 : : const irange &op2,
598 : : relation_kind rel) const final override;
599 : : void update_bitmask (irange &r, const irange &lh,
600 : : const irange &rh) const final override;
601 : :
602 : : bool overflow_free_p (const irange &lh, const irange &rh,
603 : : relation_trio = TRIO_VARYING) const final override;
604 : : // Check compatibility of all operands.
605 : 62192132 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
606 : 62192132 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
607 : : private:
608 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
609 : : const wide_int &lh_ub, const wide_int &rh_lb,
610 : : const wide_int &rh_ub) const final override;
611 : : void rv_fold (frange &r, tree type,
612 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
613 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
614 : : relation_kind) const final override;
615 : : };
616 : :
617 : : class operator_abs : public range_operator
618 : : {
619 : : public:
620 : : using range_operator::fold_range;
621 : : using range_operator::op1_range;
622 : : using range_operator::update_bitmask;
623 : : bool fold_range (frange &r, tree type,
624 : : const frange &op1, const frange &,
625 : : relation_trio = TRIO_VARYING) const final override;
626 : :
627 : : bool op1_range (irange &r, tree type, const irange &lhs,
628 : : const irange &op2, relation_trio) const final override;
629 : : bool op1_range (frange &r, tree type,
630 : : const frange &lhs, const frange &op2,
631 : : relation_trio rel = TRIO_VARYING) const final override;
632 : : void update_bitmask (irange &r, const irange &lh,
633 : : const irange &rh) const final override;
634 : : // Check compatibility of LHS and op1.
635 : 1047349 : bool operand_check_p (tree t1, tree t2, tree) const final override
636 : 1047349 : { return range_compatible_p (t1, t2); }
637 : : private:
638 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
639 : : const wide_int &lh_ub, const wide_int &rh_lb,
640 : : const wide_int &rh_ub) const final override;
641 : :
642 : : };
643 : :
644 : : class operator_minus : public range_operator
645 : : {
646 : : public:
647 : : using range_operator::fold_range;
648 : : using range_operator::op1_range;
649 : : using range_operator::op2_range;
650 : : using range_operator::lhs_op1_relation;
651 : : using range_operator::op1_op2_relation_effect;
652 : : using range_operator::update_bitmask;
653 : : bool op1_range (irange &r, tree type,
654 : : const irange &lhs, const irange &op2,
655 : : relation_trio) const final override;
656 : : bool op1_range (frange &r, tree type,
657 : : const frange &lhs, const frange &op2,
658 : : relation_trio = TRIO_VARYING) const final override;
659 : :
660 : : bool op2_range (irange &r, tree type,
661 : : const irange &lhs, const irange &op1,
662 : : relation_trio) const final override;
663 : : bool op2_range (frange &r, tree type,
664 : : const frange &lhs,
665 : : const frange &op1,
666 : : relation_trio = TRIO_VARYING) const final override;
667 : :
668 : : relation_kind lhs_op1_relation (const irange &lhs,
669 : : const irange &op1, const irange &op2,
670 : : relation_kind rel) const final override;
671 : : bool op1_op2_relation_effect (irange &lhs_range, tree type,
672 : : const irange &op1_range,
673 : : const irange &op2_range,
674 : : relation_kind rel) const final override;
675 : : void update_bitmask (irange &r, const irange &lh,
676 : : const irange &rh) const final override;
677 : :
678 : : bool overflow_free_p (const irange &lh, const irange &rh,
679 : : relation_trio = TRIO_VARYING) const final override;
680 : : // Check compatibility of all operands.
681 : 20494514 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
682 : 20494514 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
683 : : private:
684 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
685 : : const wide_int &lh_ub, const wide_int &rh_lb,
686 : : const wide_int &rh_ub) const final override;
687 : : void rv_fold (frange &r, tree type,
688 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
689 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
690 : : relation_kind) const final override;
691 : : };
692 : :
693 : : class operator_negate : public range_operator
694 : : {
695 : : public:
696 : : using range_operator::fold_range;
697 : : using range_operator::op1_range;
698 : : bool fold_range (irange &r, tree type,
699 : : const irange &op1, const irange &op2,
700 : : relation_trio rel = TRIO_VARYING) const final override;
701 : : bool fold_range (frange &r, tree type,
702 : : const frange &op1, const frange &op2,
703 : : relation_trio = TRIO_VARYING) const final override;
704 : :
705 : : bool op1_range (irange &r, tree type,
706 : : const irange &lhs, const irange &op2,
707 : : relation_trio rel = TRIO_VARYING) const final override;
708 : : bool op1_range (frange &r, tree type,
709 : : const frange &lhs, const frange &op2,
710 : : relation_trio rel = TRIO_VARYING) const final override;
711 : : // Check compatibility of LHS and op1.
712 : 842472 : bool operand_check_p (tree t1, tree t2, tree) const final override
713 : 842472 : { return range_compatible_p (t1, t2); }
714 : : };
715 : :
716 : :
717 : : class cross_product_operator : public range_operator
718 : : {
719 : : public:
720 : : virtual bool wi_op_overflows (wide_int &r,
721 : : tree type,
722 : : const wide_int &,
723 : : const wide_int &) const = 0;
724 : : void wi_cross_product (irange &r, tree type,
725 : : const wide_int &lh_lb,
726 : : const wide_int &lh_ub,
727 : : const wide_int &rh_lb,
728 : : const wide_int &rh_ub) const;
729 : : };
730 : :
731 : : class operator_mult : public cross_product_operator
732 : : {
733 : : public:
734 : : using range_operator::op1_range;
735 : : using range_operator::op2_range;
736 : : using range_operator::update_bitmask;
737 : : bool op1_range (irange &r, tree type,
738 : : const irange &lhs, const irange &op2,
739 : : relation_trio) const final override;
740 : : bool op1_range (frange &r, tree type,
741 : : const frange &lhs, const frange &op2,
742 : : relation_trio = TRIO_VARYING) const final override;
743 : :
744 : : bool op2_range (irange &r, tree type,
745 : : const irange &lhs, const irange &op1,
746 : : relation_trio) const final override;
747 : : bool op2_range (frange &r, tree type,
748 : : const frange &lhs, const frange &op1,
749 : : relation_trio = TRIO_VARYING) const final override;
750 : :
751 : : void update_bitmask (irange &r, const irange &lh,
752 : : const irange &rh) const final override;
753 : :
754 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
755 : : const wide_int &lh_ub, const wide_int &rh_lb,
756 : : const wide_int &rh_ub) const final override;
757 : : bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
758 : : const wide_int &w1) const final override;
759 : :
760 : : void rv_fold (frange &r, tree type,
761 : : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
762 : : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
763 : : relation_kind kind) const final override;
764 : : bool overflow_free_p (const irange &lh, const irange &rh,
765 : : relation_trio = TRIO_VARYING) const final override;
766 : : // Check compatibility of all operands.
767 : 15081102 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
768 : 15081102 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
769 : : };
770 : :
771 : : class operator_addr_expr : public range_operator
772 : : {
773 : : public:
774 : : using range_operator::fold_range;
775 : : using range_operator::op1_range;
776 : : bool fold_range (irange &r, tree type,
777 : : const irange &op1, const irange &op2,
778 : : relation_trio rel = TRIO_VARYING) const final override;
779 : : bool op1_range (irange &r, tree type,
780 : : const irange &lhs, const irange &op2,
781 : : relation_trio rel = TRIO_VARYING) const final override;
782 : : bool op1_range (prange &r, tree type,
783 : : const prange &lhs, const prange &op2,
784 : : relation_trio rel = TRIO_VARYING) const final override;
785 : : };
786 : :
787 : : class operator_bitwise_not : public range_operator
788 : : {
789 : : public:
790 : : using range_operator::fold_range;
791 : : using range_operator::op1_range;
792 : : using range_operator::update_bitmask;
793 : : bool fold_range (irange &r, tree type,
794 : : const irange &lh, const irange &rh,
795 : : relation_trio rel = TRIO_VARYING) const final override;
796 : : bool op1_range (irange &r, tree type,
797 : : const irange &lhs, const irange &op2,
798 : : relation_trio rel = TRIO_VARYING) const final override;
799 : : void update_bitmask (irange &r, const irange &lh,
800 : : const irange &rh) const final override;
801 : : // Check compatibility of all operands.
802 : 547575 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
803 : 547575 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
804 : : };
805 : :
806 : : class operator_bitwise_and : public range_operator
807 : : {
808 : : public:
809 : : using range_operator::fold_range;
810 : : using range_operator::op1_range;
811 : : using range_operator::op2_range;
812 : : using range_operator::lhs_op1_relation;
813 : : using range_operator::update_bitmask;
814 : : bool fold_range (prange &r, tree type,
815 : : const prange &op1,
816 : : const prange &op2,
817 : : relation_trio) const final override;
818 : : bool op1_range (irange &r, tree type,
819 : : const irange &lhs, const irange &op2,
820 : : relation_trio rel = TRIO_VARYING) const override;
821 : : bool op2_range (irange &r, tree type,
822 : : const irange &lhs, const irange &op1,
823 : : relation_trio rel = TRIO_VARYING) const override;
824 : : relation_kind lhs_op1_relation (const irange &lhs,
825 : : const irange &op1, const irange &op2,
826 : : relation_kind) const override;
827 : : void update_bitmask (irange &r, const irange &lh,
828 : : const irange &rh) const override;
829 : : // Check compatibility of all operands.
830 : 11167867 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
831 : 11167867 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
832 : : protected:
833 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
834 : : const wide_int &lh_ub, const wide_int &rh_lb,
835 : : const wide_int &rh_ub) const override;
836 : : void simple_op1_range_solver (irange &r, tree type,
837 : : const irange &lhs,
838 : : const irange &op2) const;
839 : : };
840 : :
841 : : class operator_bitwise_or : public range_operator
842 : : {
843 : : public:
844 : : using range_operator::fold_range;
845 : : using range_operator::op1_range;
846 : : using range_operator::op2_range;
847 : : using range_operator::update_bitmask;
848 : :
849 : : bool fold_range (prange &r, tree type,
850 : : const prange &op1,
851 : : const prange &op2,
852 : : relation_trio) const final override;
853 : : bool op1_range (irange &r, tree type,
854 : : const irange &lhs, const irange &op2,
855 : : relation_trio rel = TRIO_VARYING) const override;
856 : : bool op2_range (irange &r, tree type,
857 : : const irange &lhs, const irange &op1,
858 : : relation_trio rel = TRIO_VARYING) const override;
859 : : void update_bitmask (irange &r, const irange &lh,
860 : : const irange &rh) const override;
861 : : // Check compatibility of all operands.
862 : 2959350 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
863 : 2959350 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
864 : : protected:
865 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
866 : : const wide_int &lh_ub, const wide_int &rh_lb,
867 : : const wide_int &rh_ub) const override;
868 : : };
869 : :
870 : : class operator_bitwise_xor : public range_operator
871 : : {
872 : : public:
873 : : using range_operator::fold_range;
874 : : using range_operator::op1_range;
875 : : using range_operator::op2_range;
876 : : using range_operator::op1_op2_relation_effect;
877 : : using range_operator::update_bitmask;
878 : : bool fold_range (irange &r, tree type,
879 : : const irange &lh, const irange &rh,
880 : : relation_trio rel = TRIO_VARYING) const final override;
881 : : bool op1_range (irange &r, tree type,
882 : : const irange &lhs, const irange &op2,
883 : : relation_trio rel = TRIO_VARYING) const final override;
884 : : bool op2_range (irange &r, tree type,
885 : : const irange &lhs, const irange &op1,
886 : : relation_trio rel = TRIO_VARYING) const final override;
887 : : bool op1_op2_relation_effect (irange &lhs_range,
888 : : tree type,
889 : : const irange &op1_range,
890 : : const irange &op2_range,
891 : : relation_kind rel) const final override;
892 : : void update_bitmask (irange &r, const irange &lh,
893 : : const irange &rh) const final override;
894 : : // Check compatibility of all operands.
895 : 373720 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
896 : 373720 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
897 : : private:
898 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
899 : : const wide_int &lh_ub, const wide_int &rh_lb,
900 : : const wide_int &rh_ub) const final override;
901 : : class operator_bitwise_and m_and;
902 : : class operator_bitwise_or m_or;
903 : : class operator_bitwise_not m_not;
904 : : };
905 : :
906 : :
907 : : class operator_min : public range_operator
908 : : {
909 : : public:
910 : : using range_operator::fold_range;
911 : : using range_operator::update_bitmask;
912 : : bool fold_range (prange &r, tree type,
913 : : const prange &op1,
914 : : const prange &op2,
915 : : relation_trio) const final override;
916 : : void update_bitmask (irange &r, const irange &lh,
917 : : const irange &rh) const override;
918 : : // Check compatibility of all operands.
919 : 1560655 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
920 : 1560655 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
921 : : protected:
922 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
923 : : const wide_int &lh_ub, const wide_int &rh_lb,
924 : : const wide_int &rh_ub) const override;
925 : : };
926 : :
927 : : class operator_max : public range_operator
928 : : {
929 : : public:
930 : : using range_operator::fold_range;
931 : : using range_operator::update_bitmask;
932 : : bool fold_range (prange &r, tree type,
933 : : const prange &op1,
934 : : const prange &op2,
935 : : relation_trio) const final override;
936 : : void update_bitmask (irange &r, const irange &lh,
937 : : const irange &rh) const override;
938 : : // Check compatibility of all operands.
939 : 769526 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
940 : 769526 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
941 : : protected:
942 : : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
943 : : const wide_int &lh_ub, const wide_int &rh_lb,
944 : : const wide_int &rh_ub) const override;
945 : : };
946 : : #endif // GCC_RANGE_OP_MIXED_H
|