Line data Source code
1 : /* Header file for mixed range operator class.
2 : Copyright (C) 2017-2026 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 19789658 : wi_includes_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
35 : {
36 19789658 : signop sign = TYPE_SIGN (type);
37 19789658 : 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 2260737 : wi_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
44 : {
45 2260737 : unsigned prec = TYPE_PRECISION (type);
46 2630836 : 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 332717625 : empty_range_varying (vrange &r, tree type,
60 : const vrange &op1, const vrange & op2)
61 : {
62 332610705 : if (op1.undefined_p () || op2.undefined_p ())
63 : {
64 6363731 : r.set_varying (type);
65 6242476 : 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 91962612 : relop_early_resolve (irange &r, tree type, const vrange &op1,
78 : const vrange &op2, relation_trio trio,
79 : relation_kind my_rel)
80 : {
81 91962612 : relation_kind rel = trio.op1_op2 ();
82 : // If known relation is a complete subset of this relation, always true.
83 91962612 : if (relation_union (rel, my_rel) == my_rel)
84 : {
85 58163 : r = range_true (type);
86 58163 : return true;
87 : }
88 :
89 : // If known relation has no subset of this relation, always false.
90 91904449 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
91 : {
92 69361 : r = range_false (type);
93 69361 : return true;
94 : }
95 :
96 : // If either operand is undefined, return VARYING.
97 91835088 : if (empty_range_varying (r, type, op1, op2))
98 121255 : 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 45021373 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
155 45021373 : { 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 68249840 : bool operand_check_p (tree t0, tree t1, tree t2) const final override
206 68249840 : { 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 20667774 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
254 20667774 : { 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 16040697 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
305 16040697 : { 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 34510756 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
355 34510756 : { 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 9568037 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
406 9568037 : { 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 69735608 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
606 69735608 : { 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 1163244 : bool operand_check_p (tree t1, tree t2, tree) const final override
636 1163244 : { 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;
652 : using range_operator::op1_op2_relation_effect;
653 : using range_operator::update_bitmask;
654 : bool op1_range (irange &r, tree type,
655 : const irange &lhs, const irange &op2,
656 : relation_trio) const final override;
657 : bool op1_range (frange &r, tree type,
658 : const frange &lhs, const frange &op2,
659 : relation_trio = TRIO_VARYING) const final override;
660 :
661 : bool op2_range (irange &r, tree type,
662 : const irange &lhs, const irange &op1,
663 : relation_trio) const final override;
664 : bool op2_range (frange &r, tree type,
665 : const frange &lhs,
666 : const frange &op1,
667 : relation_trio = TRIO_VARYING) const final override;
668 :
669 : relation_kind lhs_op1_relation (const irange &lhs,
670 : const irange &op1, const irange &op2,
671 : relation_kind rel) const final override;
672 : relation_kind op1_op2_relation (const irange &lhs, const irange &,
673 : const irange &) const final override;
674 : bool op1_op2_relation_effect (irange &lhs_range, tree type,
675 : const irange &op1_range,
676 : const irange &op2_range,
677 : relation_kind rel) const final override;
678 : void update_bitmask (irange &r, const irange &lh,
679 : const irange &rh) const final override;
680 :
681 : bool overflow_free_p (const irange &lh, const irange &rh,
682 : relation_trio = TRIO_VARYING) const final override;
683 : // Check compatibility of all operands.
684 27716700 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
685 27716700 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
686 : private:
687 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
688 : const wide_int &lh_ub, const wide_int &rh_lb,
689 : const wide_int &rh_ub) const final override;
690 : void rv_fold (frange &r, tree type,
691 : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
692 : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
693 : relation_kind) const final override;
694 : };
695 :
696 : class operator_negate : public range_operator
697 : {
698 : public:
699 : using range_operator::fold_range;
700 : using range_operator::op1_range;
701 : bool fold_range (irange &r, tree type,
702 : const irange &op1, const irange &op2,
703 : relation_trio rel = TRIO_VARYING) const final override;
704 : bool fold_range (frange &r, tree type,
705 : const frange &op1, const frange &op2,
706 : relation_trio = TRIO_VARYING) const final override;
707 :
708 : bool op1_range (irange &r, tree type,
709 : const irange &lhs, const irange &op2,
710 : relation_trio rel = TRIO_VARYING) const final override;
711 : bool op1_range (frange &r, tree type,
712 : const frange &lhs, const frange &op2,
713 : relation_trio rel = TRIO_VARYING) const final override;
714 : // Check compatibility of LHS and op1.
715 855932 : bool operand_check_p (tree t1, tree t2, tree) const final override
716 855932 : { return range_compatible_p (t1, t2); }
717 : };
718 :
719 :
720 : class cross_product_operator : public range_operator
721 : {
722 : public:
723 : virtual bool wi_op_overflows (wide_int &r,
724 : tree type,
725 : const wide_int &,
726 : const wide_int &) const = 0;
727 : void wi_cross_product (irange &r, tree type,
728 : const wide_int &lh_lb,
729 : const wide_int &lh_ub,
730 : const wide_int &rh_lb,
731 : const wide_int &rh_ub) const;
732 : };
733 :
734 : class operator_mult : public cross_product_operator
735 : {
736 : public:
737 : using range_operator::op1_range;
738 : using range_operator::op2_range;
739 : using range_operator::update_bitmask;
740 : using range_operator::op1_op2_relation_effect;
741 : bool op1_range (irange &r, tree type,
742 : const irange &lhs, const irange &op2,
743 : relation_trio) const final override;
744 : bool op1_range (frange &r, tree type,
745 : const frange &lhs, const frange &op2,
746 : relation_trio = TRIO_VARYING) const final override;
747 :
748 : bool op2_range (irange &r, tree type,
749 : const irange &lhs, const irange &op1,
750 : relation_trio) const final override;
751 : bool op2_range (frange &r, tree type,
752 : const frange &lhs, const frange &op1,
753 : relation_trio = TRIO_VARYING) const final override;
754 :
755 : void update_bitmask (irange &r, const irange &lh,
756 : const irange &rh) const final override;
757 :
758 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
759 : const wide_int &lh_ub, const wide_int &rh_lb,
760 : const wide_int &rh_ub) const final override;
761 : bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
762 : const wide_int &w1) const final override;
763 : bool op1_op2_relation_effect (irange &lhs_range, tree type,
764 : const irange &op1_range,
765 : const irange &op2_range,
766 : relation_kind rel) const final override;
767 :
768 : void rv_fold (frange &r, tree type,
769 : const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
770 : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
771 : relation_kind kind) const final override;
772 : bool overflow_free_p (const irange &lh, const irange &rh,
773 : relation_trio = TRIO_VARYING) const final override;
774 : // Check compatibility of all operands.
775 17673181 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
776 17673181 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
777 : };
778 :
779 : class operator_addr_expr : public range_operator
780 : {
781 : public:
782 : using range_operator::fold_range;
783 : using range_operator::op1_range;
784 : bool fold_range (irange &r, tree type,
785 : const irange &op1, const irange &op2,
786 : relation_trio rel = TRIO_VARYING) const final override;
787 : bool op1_range (irange &r, tree type,
788 : const irange &lhs, const irange &op2,
789 : relation_trio rel = TRIO_VARYING) const final override;
790 : bool op1_range (prange &r, tree type,
791 : const prange &lhs, const prange &op2,
792 : relation_trio rel = TRIO_VARYING) const final override;
793 : };
794 :
795 : class operator_bitwise_not : public range_operator
796 : {
797 : public:
798 : using range_operator::fold_range;
799 : using range_operator::op1_range;
800 : using range_operator::update_bitmask;
801 : bool fold_range (irange &r, tree type,
802 : const irange &lh, const irange &rh,
803 : relation_trio rel = TRIO_VARYING) const final override;
804 : bool op1_range (irange &r, tree type,
805 : const irange &lhs, const irange &op2,
806 : relation_trio rel = TRIO_VARYING) const final override;
807 : void update_bitmask (irange &r, const irange &lh,
808 : const irange &rh) const final override;
809 : // Check compatibility of all operands.
810 576146 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
811 576146 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
812 : };
813 :
814 : class operator_bitwise_and : public range_operator
815 : {
816 : public:
817 : using range_operator::fold_range;
818 : using range_operator::op1_range;
819 : using range_operator::op2_range;
820 : using range_operator::lhs_op1_relation;
821 : using range_operator::update_bitmask;
822 : bool fold_range (prange &r, tree type,
823 : const prange &op1,
824 : const prange &op2,
825 : relation_trio) const final override;
826 : bool op1_range (irange &r, tree type,
827 : const irange &lhs, const irange &op2,
828 : relation_trio rel = TRIO_VARYING) const override;
829 : bool op2_range (irange &r, tree type,
830 : const irange &lhs, const irange &op1,
831 : relation_trio rel = TRIO_VARYING) const override;
832 : relation_kind lhs_op1_relation (const irange &lhs,
833 : const irange &op1, const irange &op2,
834 : relation_kind) const override;
835 : void update_bitmask (irange &r, const irange &lh,
836 : const irange &rh) const override;
837 : // Check compatibility of all operands.
838 11659396 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
839 11659396 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
840 : protected:
841 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
842 : const wide_int &lh_ub, const wide_int &rh_lb,
843 : const wide_int &rh_ub) const override;
844 : void simple_op1_range_solver (irange &r, tree type,
845 : const irange &lhs,
846 : const irange &op2) const;
847 : };
848 :
849 : class operator_bitwise_or : public range_operator
850 : {
851 : public:
852 : using range_operator::fold_range;
853 : using range_operator::op1_range;
854 : using range_operator::op2_range;
855 : using range_operator::lhs_op1_relation;
856 : using range_operator::op1_op2_relation_effect;
857 : using range_operator::update_bitmask;
858 : relation_kind lhs_op1_relation (const irange &lhs,
859 : const irange &op1, const irange &op2,
860 : relation_kind) const final override;
861 :
862 : bool fold_range (prange &r, tree type,
863 : const prange &op1,
864 : const prange &op2,
865 : relation_trio) const final override;
866 : bool op1_range (irange &r, tree type,
867 : const irange &lhs, const irange &op2,
868 : relation_trio rel = TRIO_VARYING) const override;
869 : bool op2_range (irange &r, tree type,
870 : const irange &lhs, const irange &op1,
871 : relation_trio rel = TRIO_VARYING) const override;
872 : bool op1_op2_relation_effect (irange &lhs_range,
873 : tree type,
874 : const irange &op1_range,
875 : const irange &op2_range,
876 : relation_kind rel) const final override;
877 : void update_bitmask (irange &r, const irange &lh,
878 : const irange &rh) const override;
879 : // Check compatibility of all operands.
880 3162167 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
881 3162167 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
882 : protected:
883 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
884 : const wide_int &lh_ub, const wide_int &rh_lb,
885 : const wide_int &rh_ub) const override;
886 : };
887 :
888 : class operator_bitwise_xor : public range_operator
889 : {
890 : public:
891 : using range_operator::fold_range;
892 : using range_operator::op1_range;
893 : using range_operator::op2_range;
894 : using range_operator::op1_op2_relation_effect;
895 : using range_operator::update_bitmask;
896 : bool fold_range (irange &r, tree type,
897 : const irange &lh, const irange &rh,
898 : relation_trio rel = TRIO_VARYING) const final override;
899 : bool op1_range (irange &r, tree type,
900 : const irange &lhs, const irange &op2,
901 : relation_trio rel = TRIO_VARYING) const final override;
902 : bool op2_range (irange &r, tree type,
903 : const irange &lhs, const irange &op1,
904 : relation_trio rel = TRIO_VARYING) const final override;
905 : bool op1_op2_relation_effect (irange &lhs_range,
906 : tree type,
907 : const irange &op1_range,
908 : const irange &op2_range,
909 : relation_kind rel) const final override;
910 : void update_bitmask (irange &r, const irange &lh,
911 : const irange &rh) const final override;
912 : // Check compatibility of all operands.
913 427119 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
914 427119 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
915 : private:
916 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
917 : const wide_int &lh_ub, const wide_int &rh_lb,
918 : const wide_int &rh_ub) const final override;
919 : class operator_bitwise_and m_and;
920 : class operator_bitwise_or m_or;
921 : class operator_bitwise_not m_not;
922 : };
923 :
924 :
925 : class operator_min : public range_operator
926 : {
927 : public:
928 : using range_operator::fold_range;
929 : using range_operator::lhs_op1_relation;
930 : using range_operator::lhs_op2_relation;
931 : using range_operator::update_bitmask;
932 : relation_kind lhs_op1_relation (const irange &lhs,
933 : const irange &op1, const irange &op2,
934 : relation_kind) const final override;
935 : relation_kind lhs_op2_relation (const irange &lhs,
936 : const irange &op1, const irange &op2,
937 : relation_kind) const final override;
938 : bool fold_range (prange &r, tree type,
939 : const prange &op1,
940 : const prange &op2,
941 : relation_trio) const final override;
942 : void update_bitmask (irange &r, const irange &lh,
943 : const irange &rh) const override;
944 : // Check compatibility of all operands.
945 1951586 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
946 1951586 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
947 : protected:
948 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
949 : const wide_int &lh_ub, const wide_int &rh_lb,
950 : const wide_int &rh_ub) const override;
951 : };
952 :
953 : class operator_max : public range_operator
954 : {
955 : public:
956 : using range_operator::fold_range;
957 : using range_operator::lhs_op1_relation;
958 : using range_operator::lhs_op2_relation;
959 : using range_operator::update_bitmask;
960 : relation_kind lhs_op1_relation (const irange &lhs,
961 : const irange &op1, const irange &op2,
962 : relation_kind) const final override;
963 : relation_kind lhs_op2_relation (const irange &lhs,
964 : const irange &op1, const irange &op2,
965 : relation_kind) const final override;
966 : bool fold_range (prange &r, tree type,
967 : const prange &op1,
968 : const prange &op2,
969 : relation_trio) const final override;
970 : void update_bitmask (irange &r, const irange &lh,
971 : const irange &rh) const override;
972 : // Check compatibility of all operands.
973 1141707 : bool operand_check_p (tree t1, tree t2, tree t3) const final override
974 1141707 : { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
975 : protected:
976 : void wi_fold (irange &r, tree type, const wide_int &lh_lb,
977 : const wide_int &lh_ub, const wide_int &rh_lb,
978 : const wide_int &rh_ub) const override;
979 : };
980 : #endif // GCC_RANGE_OP_MIXED_H
|