1/* Header file for mixed range operator class.
2 Copyright (C) 2017-2024 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>
4 and Aldy Hernandez <aldyh@redhat.com>.
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18You should have received a copy of the GNU General Public License
19along 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
25void update_known_bitmask (irange &, tree_code, const irange &, const irange &);
26bool 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
33inline bool
34wi_includes_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
35{
36 signop sign = TYPE_SIGN (type);
37 return wi::le_p (x: wmin, y: 0, sgn: sign) && wi::ge_p (x: wmax, y: 0, sgn: sign);
38}
39
40// Return TRUE if [WMIN, WMAX] is the singleton 0.
41
42inline bool
43wi_zero_p (tree type, const wide_int &wmin, const wide_int &wmax)
44{
45 unsigned prec = TYPE_PRECISION (type);
46 return wmin == wmax && wi::eq_p (x: wmin, y: wi::zero (precision: prec));
47}
48
49
50enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL };
51bool_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
58inline bool
59empty_range_varying (vrange &r, tree type,
60 const vrange &op1, const vrange & op2)
61{
62 if (op1.undefined_p () || op2.undefined_p ())
63 {
64 r.set_varying (type);
65 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
76inline bool
77relop_early_resolve (irange &r, tree type, const vrange &op1,
78 const vrange &op2, relation_trio trio,
79 relation_kind my_rel)
80{
81 relation_kind rel = trio.op1_op2 ();
82 // If known relation is a complete subset of this relation, always true.
83 if (relation_union (r1: rel, r2: my_rel) == my_rel)
84 {
85 r = range_true (type);
86 return true;
87 }
88
89 // If known relation has no subset of this relation, always false.
90 if (relation_intersect (r1: rel, r2: my_rel) == VREL_UNDEFINED)
91 {
92 r = range_false (type);
93 return true;
94 }
95
96 // If either operand is undefined, return VARYING.
97 if (empty_range_varying (r, type, op1, op2))
98 return true;
99
100 return false;
101}
102
103// ----------------------------------------------------------------------
104// Mixed Mode Operators.
105// ----------------------------------------------------------------------
106
107class operator_equal : public range_operator
108{
109public:
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 bool fold_range (irange &r, tree type,
115 const irange &op1, const irange &op2,
116 relation_trio = TRIO_VARYING) const final override;
117 bool fold_range (irange &r, tree type,
118 const frange &op1, const frange &op2,
119 relation_trio = TRIO_VARYING) const final override;
120
121 bool op1_range (irange &r, tree type,
122 const irange &lhs, const irange &val,
123 relation_trio = TRIO_VARYING) const final override;
124 bool op1_range (frange &r, tree type,
125 const irange &lhs, const frange &op2,
126 relation_trio = TRIO_VARYING) const final override;
127
128 bool op2_range (irange &r, tree type,
129 const irange &lhs, const irange &val,
130 relation_trio = TRIO_VARYING) const final override;
131 bool op2_range (frange &r, tree type,
132 const irange &lhs, const frange &op1,
133 relation_trio rel = TRIO_VARYING) const final override;
134
135 relation_kind op1_op2_relation (const irange &lhs, const irange &,
136 const irange &) const final override;
137 relation_kind op1_op2_relation (const irange &lhs, const frange &,
138 const frange &) const final override;
139 void update_bitmask (irange &r, const irange &lh,
140 const irange &rh) const final override;
141 // Check op1 and op2 for compatibility.
142 bool operand_check_p (tree, tree t1, tree t2) const final override
143 { return range_compatible_p (type1: t1, type2: t2); }
144};
145
146class operator_not_equal : public range_operator
147{
148public:
149 using range_operator::fold_range;
150 using range_operator::op1_range;
151 using range_operator::op2_range;
152 using range_operator::op1_op2_relation;
153 bool fold_range (irange &r, tree type,
154 const irange &op1, const irange &op2,
155 relation_trio = TRIO_VARYING) const final override;
156 bool fold_range (irange &r, tree type,
157 const frange &op1, const frange &op2,
158 relation_trio rel = TRIO_VARYING) const final override;
159
160 bool op1_range (irange &r, tree type,
161 const irange &lhs, const irange &op2,
162 relation_trio = TRIO_VARYING) const final override;
163 bool op1_range (frange &r, tree type,
164 const irange &lhs, const frange &op2,
165 relation_trio = TRIO_VARYING) const final override;
166
167 bool op2_range (irange &r, tree type,
168 const irange &lhs, const irange &op1,
169 relation_trio = TRIO_VARYING) const final override;
170 bool op2_range (frange &r, tree type,
171 const irange &lhs, const frange &op1,
172 relation_trio = TRIO_VARYING) const final override;
173
174 relation_kind op1_op2_relation (const irange &lhs, const irange &,
175 const irange &) const final override;
176 relation_kind op1_op2_relation (const irange &lhs, const frange &,
177 const frange &) const final override;
178 void update_bitmask (irange &r, const irange &lh,
179 const irange &rh) const final override;
180 // Check op1 and op2 for compatibility.
181 bool operand_check_p (tree, tree t1, tree t2) const final override
182 { return range_compatible_p (type1: t1, type2: t2); }
183};
184
185class operator_lt : public range_operator
186{
187public:
188 using range_operator::fold_range;
189 using range_operator::op1_range;
190 using range_operator::op2_range;
191 using range_operator::op1_op2_relation;
192 bool fold_range (irange &r, tree type,
193 const irange &op1, const irange &op2,
194 relation_trio = TRIO_VARYING) const final override;
195 bool fold_range (irange &r, tree type,
196 const frange &op1, const frange &op2,
197 relation_trio = TRIO_VARYING) const final override;
198 bool op1_range (irange &r, tree type,
199 const irange &lhs, const irange &op2,
200 relation_trio = TRIO_VARYING) const final override;
201 bool op1_range (frange &r, tree type,
202 const irange &lhs, const frange &op2,
203 relation_trio = TRIO_VARYING) const final override;
204 bool op2_range (irange &r, tree type,
205 const irange &lhs, const irange &op1,
206 relation_trio = TRIO_VARYING) const final override;
207 bool op2_range (frange &r, tree type,
208 const irange &lhs, const frange &op1,
209 relation_trio = TRIO_VARYING) const final override;
210 relation_kind op1_op2_relation (const irange &lhs, const irange &,
211 const irange &) const final override;
212 relation_kind op1_op2_relation (const irange &lhs, const frange &,
213 const frange &) const final override;
214 void update_bitmask (irange &r, const irange &lh,
215 const irange &rh) const final override;
216 // Check op1 and op2 for compatibility.
217 bool operand_check_p (tree, tree t1, tree t2) const final override
218 { return range_compatible_p (type1: t1, type2: t2); }
219};
220
221class operator_le : public range_operator
222{
223public:
224 using range_operator::fold_range;
225 using range_operator::op1_range;
226 using range_operator::op2_range;
227 using range_operator::op1_op2_relation;
228 bool fold_range (irange &r, tree type,
229 const irange &op1, const irange &op2,
230 relation_trio = TRIO_VARYING) const final override;
231 bool fold_range (irange &r, tree type,
232 const frange &op1, const frange &op2,
233 relation_trio rel = TRIO_VARYING) const final override;
234
235 bool op1_range (irange &r, tree type,
236 const irange &lhs, const irange &op2,
237 relation_trio = TRIO_VARYING) const final override;
238 bool op1_range (frange &r, tree type,
239 const irange &lhs, const frange &op2,
240 relation_trio rel = TRIO_VARYING) const final override;
241
242 bool op2_range (irange &r, tree type,
243 const irange &lhs, const irange &op1,
244 relation_trio = TRIO_VARYING) const final override;
245 bool op2_range (frange &r, tree type,
246 const irange &lhs, const frange &op1,
247 relation_trio rel = TRIO_VARYING) const final override;
248
249 relation_kind op1_op2_relation (const irange &lhs, const irange &,
250 const irange &) const final override;
251 relation_kind op1_op2_relation (const irange &lhs, const frange &,
252 const frange &) const final override;
253 void update_bitmask (irange &r, const irange &lh,
254 const irange &rh) const final override;
255 // Check op1 and op2 for compatibility.
256 bool operand_check_p (tree, tree t1, tree t2) const final override
257 { return range_compatible_p (type1: t1, type2: t2); }
258};
259
260class operator_gt : public range_operator
261{
262public:
263 using range_operator::fold_range;
264 using range_operator::op1_range;
265 using range_operator::op2_range;
266 using range_operator::op1_op2_relation;
267 bool fold_range (irange &r, tree type,
268 const irange &op1, const irange &op2,
269 relation_trio = TRIO_VARYING) const final override;
270 bool fold_range (irange &r, tree type,
271 const frange &op1, const frange &op2,
272 relation_trio = TRIO_VARYING) const final override;
273
274 bool op1_range (irange &r, tree type,
275 const irange &lhs, const irange &op2,
276 relation_trio = TRIO_VARYING) const final override;
277 bool op1_range (frange &r, tree type,
278 const irange &lhs, const frange &op2,
279 relation_trio = TRIO_VARYING) const final override;
280
281 bool op2_range (irange &r, tree type,
282 const irange &lhs, const irange &op1,
283 relation_trio = TRIO_VARYING) const final override;
284 bool op2_range (frange &r, tree type,
285 const irange &lhs, const frange &op1,
286 relation_trio = TRIO_VARYING) const final override;
287 relation_kind op1_op2_relation (const irange &lhs, const irange &,
288 const irange &) const final override;
289 relation_kind op1_op2_relation (const irange &lhs, const frange &,
290 const frange &) const final override;
291 void update_bitmask (irange &r, const irange &lh,
292 const irange &rh) const final override;
293 // Check op1 and op2 for compatibility.
294 bool operand_check_p (tree, tree t1, tree t2) const final override
295 { return range_compatible_p (type1: t1, type2: t2); }
296};
297
298class operator_ge : public range_operator
299{
300public:
301 using range_operator::fold_range;
302 using range_operator::op1_range;
303 using range_operator::op2_range;
304 using range_operator::op1_op2_relation;
305 bool fold_range (irange &r, tree type,
306 const irange &op1, const irange &op2,
307 relation_trio = TRIO_VARYING) const final override;
308 bool fold_range (irange &r, tree type,
309 const frange &op1, const frange &op2,
310 relation_trio = TRIO_VARYING) const final override;
311
312 bool op1_range (irange &r, tree type,
313 const irange &lhs, const irange &op2,
314 relation_trio = TRIO_VARYING) const final override;
315 bool op1_range (frange &r, tree type,
316 const irange &lhs, const frange &op2,
317 relation_trio = TRIO_VARYING) const final override;
318
319 bool op2_range (irange &r, tree type,
320 const irange &lhs, const irange &op1,
321 relation_trio = TRIO_VARYING) const final override;
322 bool op2_range (frange &r, tree type,
323 const irange &lhs, const frange &op1,
324 relation_trio = TRIO_VARYING) const final override;
325
326 relation_kind op1_op2_relation (const irange &lhs, const irange &,
327 const irange &) const final override;
328 relation_kind op1_op2_relation (const irange &lhs, const frange &,
329 const frange &) const final override;
330 void update_bitmask (irange &r, const irange &lh,
331 const irange &rh) const final override;
332 // Check op1 and op2 for compatibility.
333 bool operand_check_p (tree, tree t1, tree t2) const final override
334 { return range_compatible_p (type1: t1, type2: t2); }
335};
336
337class operator_identity : public range_operator
338{
339public:
340 using range_operator::fold_range;
341 using range_operator::op1_range;
342 using range_operator::lhs_op1_relation;
343 bool fold_range (irange &r, tree type,
344 const irange &op1, const irange &op2,
345 relation_trio rel = TRIO_VARYING) const final override;
346 bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
347 const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
348 relation_trio = TRIO_VARYING) const final override;
349 bool op1_range (irange &r, tree type,
350 const irange &lhs, const irange &op2,
351 relation_trio rel = TRIO_VARYING) const final override;
352 bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
353 const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
354 relation_trio = TRIO_VARYING) const final override;
355 relation_kind lhs_op1_relation (const irange &lhs,
356 const irange &op1, const irange &op2,
357 relation_kind rel) const final override;
358};
359
360class operator_cst : public range_operator
361{
362public:
363 using range_operator::fold_range;
364 bool fold_range (irange &r, tree type,
365 const irange &op1, const irange &op2,
366 relation_trio rel = TRIO_VARYING) const final override;
367 bool fold_range (frange &r, tree type,
368 const frange &op1, const frange &op2,
369 relation_trio = TRIO_VARYING) const final override;
370};
371
372
373class operator_cast: public range_operator
374{
375public:
376 using range_operator::fold_range;
377 using range_operator::op1_range;
378 using range_operator::lhs_op1_relation;
379 bool fold_range (irange &r, tree type,
380 const irange &op1, const irange &op2,
381 relation_trio rel = TRIO_VARYING) const final override;
382 bool op1_range (irange &r, tree type,
383 const irange &lhs, const irange &op2,
384 relation_trio rel = TRIO_VARYING) const final override;
385 relation_kind lhs_op1_relation (const irange &lhs,
386 const irange &op1, const irange &op2,
387 relation_kind) const final override;
388 void update_bitmask (irange &r, const irange &lh,
389 const irange &rh) const final override;
390private:
391 bool truncating_cast_p (const irange &inner, const irange &outer) const;
392 bool inside_domain_p (const wide_int &min, const wide_int &max,
393 const irange &outer) const;
394 void fold_pair (irange &r, unsigned index, const irange &inner,
395 const irange &outer) const;
396};
397
398class operator_plus : public range_operator
399{
400public:
401 using range_operator::op1_range;
402 using range_operator::op2_range;
403 using range_operator::lhs_op1_relation;
404 using range_operator::lhs_op2_relation;
405 bool op1_range (irange &r, tree type,
406 const irange &lhs, const irange &op2,
407 relation_trio) const final override;
408 bool op1_range (frange &r, tree type,
409 const frange &lhs, const frange &op2,
410 relation_trio = TRIO_VARYING) const final override;
411
412 bool op2_range (irange &r, tree type,
413 const irange &lhs, const irange &op1,
414 relation_trio) const final override;
415 bool op2_range (frange &r, tree type,
416 const frange &lhs, const frange &op1,
417 relation_trio = TRIO_VARYING) const final override;
418
419 relation_kind lhs_op1_relation (const irange &lhs, const irange &op1,
420 const irange &op2,
421 relation_kind rel) const final override;
422 relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
423 const irange &op2,
424 relation_kind rel) const final override;
425 void update_bitmask (irange &r, const irange &lh,
426 const irange &rh) const final override;
427
428 virtual bool overflow_free_p (const irange &lh, const irange &rh,
429 relation_trio = TRIO_VARYING) const;
430 // Check compatibility of all operands.
431 bool operand_check_p (tree t1, tree t2, tree t3) const final override
432 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
433private:
434 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
435 const wide_int &lh_ub, const wide_int &rh_lb,
436 const wide_int &rh_ub) const final override;
437 void rv_fold (frange &r, tree type,
438 const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
439 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
440 relation_kind) const final override;
441};
442
443class operator_abs : public range_operator
444{
445 public:
446 using range_operator::fold_range;
447 using range_operator::op1_range;
448 bool fold_range (frange &r, tree type,
449 const frange &op1, const frange &,
450 relation_trio = TRIO_VARYING) const final override;
451
452 bool op1_range (irange &r, tree type, const irange &lhs,
453 const irange &op2, relation_trio) const final override;
454 bool op1_range (frange &r, tree type,
455 const frange &lhs, const frange &op2,
456 relation_trio rel = TRIO_VARYING) const final override;
457 void update_bitmask (irange &r, const irange &lh,
458 const irange &rh) const final override;
459 // Check compatibility of LHS and op1.
460 bool operand_check_p (tree t1, tree t2, tree) const final override
461 { return range_compatible_p (type1: t1, type2: t2); }
462private:
463 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
464 const wide_int &lh_ub, const wide_int &rh_lb,
465 const wide_int &rh_ub) const final override;
466
467};
468
469class operator_minus : public range_operator
470{
471public:
472 using range_operator::fold_range;
473 using range_operator::op1_range;
474 using range_operator::op2_range;
475 using range_operator::lhs_op1_relation;
476 bool op1_range (irange &r, tree type,
477 const irange &lhs, const irange &op2,
478 relation_trio) const final override;
479 bool op1_range (frange &r, tree type,
480 const frange &lhs, const frange &op2,
481 relation_trio = TRIO_VARYING) const final override;
482
483 bool op2_range (irange &r, tree type,
484 const irange &lhs, const irange &op1,
485 relation_trio) const final override;
486 bool op2_range (frange &r, tree type,
487 const frange &lhs,
488 const frange &op1,
489 relation_trio = TRIO_VARYING) const final override;
490
491 relation_kind lhs_op1_relation (const irange &lhs,
492 const irange &op1, const irange &op2,
493 relation_kind rel) const final override;
494 bool op1_op2_relation_effect (irange &lhs_range, tree type,
495 const irange &op1_range,
496 const irange &op2_range,
497 relation_kind rel) const final override;
498 void update_bitmask (irange &r, const irange &lh,
499 const irange &rh) const final override;
500
501 virtual bool overflow_free_p (const irange &lh, const irange &rh,
502 relation_trio = TRIO_VARYING) const;
503 // Check compatibility of all operands.
504 bool operand_check_p (tree t1, tree t2, tree t3) const final override
505 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
506private:
507 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
508 const wide_int &lh_ub, const wide_int &rh_lb,
509 const wide_int &rh_ub) const final override;
510 void rv_fold (frange &r, tree type,
511 const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
512 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
513 relation_kind) const final override;
514};
515
516class operator_negate : public range_operator
517{
518 public:
519 using range_operator::fold_range;
520 using range_operator::op1_range;
521 bool fold_range (irange &r, tree type,
522 const irange &op1, const irange &op2,
523 relation_trio rel = TRIO_VARYING) const final override;
524 bool fold_range (frange &r, tree type,
525 const frange &op1, const frange &op2,
526 relation_trio = TRIO_VARYING) const final override;
527
528 bool op1_range (irange &r, tree type,
529 const irange &lhs, const irange &op2,
530 relation_trio rel = TRIO_VARYING) const final override;
531 bool op1_range (frange &r, tree type,
532 const frange &lhs, const frange &op2,
533 relation_trio rel = TRIO_VARYING) const final override;
534 // Check compatibility of LHS and op1.
535 bool operand_check_p (tree t1, tree t2, tree) const final override
536 { return range_compatible_p (type1: t1, type2: t2); }
537};
538
539
540class cross_product_operator : public range_operator
541{
542public:
543 virtual bool wi_op_overflows (wide_int &r,
544 tree type,
545 const wide_int &,
546 const wide_int &) const = 0;
547 void wi_cross_product (irange &r, tree type,
548 const wide_int &lh_lb,
549 const wide_int &lh_ub,
550 const wide_int &rh_lb,
551 const wide_int &rh_ub) const;
552};
553
554class operator_mult : public cross_product_operator
555{
556public:
557 using range_operator::op1_range;
558 using range_operator::op2_range;
559 bool op1_range (irange &r, tree type,
560 const irange &lhs, const irange &op2,
561 relation_trio) const final override;
562 bool op1_range (frange &r, tree type,
563 const frange &lhs, const frange &op2,
564 relation_trio = TRIO_VARYING) const final override;
565
566 bool op2_range (irange &r, tree type,
567 const irange &lhs, const irange &op1,
568 relation_trio) const final override;
569 bool op2_range (frange &r, tree type,
570 const frange &lhs, const frange &op1,
571 relation_trio = TRIO_VARYING) const final override;
572
573 void update_bitmask (irange &r, const irange &lh,
574 const irange &rh) const final override;
575
576 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
577 const wide_int &lh_ub, const wide_int &rh_lb,
578 const wide_int &rh_ub) const final override;
579 bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
580 const wide_int &w1) const final override;
581
582 void rv_fold (frange &r, tree type,
583 const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
584 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
585 relation_kind kind) const final override;
586 virtual bool overflow_free_p (const irange &lh, const irange &rh,
587 relation_trio = TRIO_VARYING) const;
588 // Check compatibility of all operands.
589 bool operand_check_p (tree t1, tree t2, tree t3) const final override
590 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
591};
592
593class operator_addr_expr : public range_operator
594{
595public:
596 using range_operator::fold_range;
597 using range_operator::op1_range;
598 bool fold_range (irange &r, tree type,
599 const irange &op1, const irange &op2,
600 relation_trio rel = TRIO_VARYING) const final override;
601 bool op1_range (irange &r, tree type,
602 const irange &lhs, const irange &op2,
603 relation_trio rel = TRIO_VARYING) const final override;
604};
605
606class operator_bitwise_not : public range_operator
607{
608public:
609 using range_operator::fold_range;
610 using range_operator::op1_range;
611 bool fold_range (irange &r, tree type,
612 const irange &lh, const irange &rh,
613 relation_trio rel = TRIO_VARYING) const final override;
614 bool op1_range (irange &r, tree type,
615 const irange &lhs, const irange &op2,
616 relation_trio rel = TRIO_VARYING) const final override;
617 void update_bitmask (irange &r, const irange &lh,
618 const irange &rh) const final override;
619 // Check compatibility of all operands.
620 bool operand_check_p (tree t1, tree t2, tree t3) const final override
621 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
622};
623
624class operator_bitwise_xor : public range_operator
625{
626public:
627 using range_operator::op1_range;
628 using range_operator::op2_range;
629 bool op1_range (irange &r, tree type,
630 const irange &lhs, const irange &op2,
631 relation_trio rel = TRIO_VARYING) const final override;
632 bool op2_range (irange &r, tree type,
633 const irange &lhs, const irange &op1,
634 relation_trio rel = TRIO_VARYING) const final override;
635 bool op1_op2_relation_effect (irange &lhs_range,
636 tree type,
637 const irange &op1_range,
638 const irange &op2_range,
639 relation_kind rel) const final override;
640 void update_bitmask (irange &r, const irange &lh,
641 const irange &rh) const final override;
642 // Check compatibility of all operands.
643 bool operand_check_p (tree t1, tree t2, tree t3) const final override
644 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
645private:
646 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
647 const wide_int &lh_ub, const wide_int &rh_lb,
648 const wide_int &rh_ub) const final override;
649};
650
651class operator_bitwise_and : public range_operator
652{
653public:
654 using range_operator::op1_range;
655 using range_operator::op2_range;
656 using range_operator::lhs_op1_relation;
657 bool op1_range (irange &r, tree type,
658 const irange &lhs, const irange &op2,
659 relation_trio rel = TRIO_VARYING) const override;
660 bool op2_range (irange &r, tree type,
661 const irange &lhs, const irange &op1,
662 relation_trio rel = TRIO_VARYING) const override;
663 relation_kind lhs_op1_relation (const irange &lhs,
664 const irange &op1, const irange &op2,
665 relation_kind) const override;
666 void update_bitmask (irange &r, const irange &lh,
667 const irange &rh) const override;
668 // Check compatibility of all operands.
669 bool operand_check_p (tree t1, tree t2, tree t3) const final override
670 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
671protected:
672 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
673 const wide_int &lh_ub, const wide_int &rh_lb,
674 const wide_int &rh_ub) const override;
675 void simple_op1_range_solver (irange &r, tree type,
676 const irange &lhs,
677 const irange &op2) const;
678};
679
680class operator_bitwise_or : public range_operator
681{
682public:
683 using range_operator::op1_range;
684 using range_operator::op2_range;
685 bool op1_range (irange &r, tree type,
686 const irange &lhs, const irange &op2,
687 relation_trio rel = TRIO_VARYING) const override;
688 bool op2_range (irange &r, tree type,
689 const irange &lhs, const irange &op1,
690 relation_trio rel = TRIO_VARYING) const override;
691 void update_bitmask (irange &r, const irange &lh,
692 const irange &rh) const override;
693 // Check compatibility of all operands.
694 bool operand_check_p (tree t1, tree t2, tree t3) const final override
695 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
696protected:
697 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
698 const wide_int &lh_ub, const wide_int &rh_lb,
699 const wide_int &rh_ub) const override;
700};
701
702class operator_min : public range_operator
703{
704public:
705 void update_bitmask (irange &r, const irange &lh,
706 const irange &rh) const override;
707 // Check compatibility of all operands.
708 bool operand_check_p (tree t1, tree t2, tree t3) const final override
709 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
710protected:
711 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
712 const wide_int &lh_ub, const wide_int &rh_lb,
713 const wide_int &rh_ub) const override;
714};
715
716class operator_max : public range_operator
717{
718public:
719 void update_bitmask (irange &r, const irange &lh,
720 const irange &rh) const override;
721 // Check compatibility of all operands.
722 bool operand_check_p (tree t1, tree t2, tree t3) const final override
723 { return range_compatible_p (type1: t1, type2: t2) && range_compatible_p (type1: t1, type2: t3); }
724protected:
725 void wi_fold (irange &r, tree type, const wide_int &lh_lb,
726 const wide_int &lh_ub, const wide_int &rh_lb,
727 const wide_int &rh_ub) const override;
728};
729#endif // GCC_RANGE_OP_MIXED_H
730

source code of gcc/range-op-mixed.h