]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/range-op-float.cc
Don't build readline/libreadline.a, when --with-system-readline is supplied
[thirdparty/gcc.git] / gcc / range-op-float.cc
1 /* Floating point range operators.
2 Copyright (C) 2022 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldyh@redhat.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "insn-codes.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "gimple.h"
29 #include "cfghooks.h"
30 #include "tree-pass.h"
31 #include "ssa.h"
32 #include "optabs-tree.h"
33 #include "gimple-pretty-print.h"
34 #include "diagnostic-core.h"
35 #include "flags.h"
36 #include "fold-const.h"
37 #include "stor-layout.h"
38 #include "calls.h"
39 #include "cfganal.h"
40 #include "gimple-iterator.h"
41 #include "gimple-fold.h"
42 #include "tree-eh.h"
43 #include "gimple-walk.h"
44 #include "tree-cfg.h"
45 #include "wide-int.h"
46 #include "value-relation.h"
47 #include "range-op.h"
48
49 // Default definitions for floating point operators.
50
51 bool
52 range_operator_float::fold_range (frange &r ATTRIBUTE_UNUSED,
53 tree type ATTRIBUTE_UNUSED,
54 const frange &lh ATTRIBUTE_UNUSED,
55 const frange &rh ATTRIBUTE_UNUSED,
56 relation_trio) const
57 {
58 return false;
59 }
60
61 bool
62 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
63 tree type ATTRIBUTE_UNUSED,
64 const frange &lh ATTRIBUTE_UNUSED,
65 const irange &rh ATTRIBUTE_UNUSED,
66 relation_trio) const
67 {
68 return false;
69 }
70
71 bool
72 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
73 tree type ATTRIBUTE_UNUSED,
74 const frange &lh ATTRIBUTE_UNUSED,
75 const frange &rh ATTRIBUTE_UNUSED,
76 relation_trio) const
77 {
78 return false;
79 }
80
81 bool
82 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
83 tree type ATTRIBUTE_UNUSED,
84 const frange &lhs ATTRIBUTE_UNUSED,
85 const frange &op2 ATTRIBUTE_UNUSED,
86 relation_trio) const
87 {
88 return false;
89 }
90
91 bool
92 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
93 tree type ATTRIBUTE_UNUSED,
94 const irange &lhs ATTRIBUTE_UNUSED,
95 const frange &op2 ATTRIBUTE_UNUSED,
96 relation_trio) const
97 {
98 return false;
99 }
100
101 bool
102 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
103 tree type ATTRIBUTE_UNUSED,
104 const frange &lhs ATTRIBUTE_UNUSED,
105 const frange &op1 ATTRIBUTE_UNUSED,
106 relation_trio) const
107 {
108 return false;
109 }
110
111 bool
112 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
113 tree type ATTRIBUTE_UNUSED,
114 const irange &lhs ATTRIBUTE_UNUSED,
115 const frange &op1 ATTRIBUTE_UNUSED,
116 relation_trio) const
117 {
118 return false;
119 }
120
121 relation_kind
122 range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
123 const frange &op1 ATTRIBUTE_UNUSED,
124 const frange &op2 ATTRIBUTE_UNUSED,
125 relation_kind) const
126 {
127 return VREL_VARYING;
128 }
129
130 relation_kind
131 range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
132 const frange &op1 ATTRIBUTE_UNUSED,
133 const frange &op2 ATTRIBUTE_UNUSED,
134 relation_kind) const
135 {
136 return VREL_VARYING;
137 }
138
139 relation_kind
140 range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
141 const frange &op1 ATTRIBUTE_UNUSED,
142 const frange &op2 ATTRIBUTE_UNUSED,
143 relation_kind) const
144 {
145 return VREL_VARYING;
146 }
147
148 relation_kind
149 range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
150 const frange &op1 ATTRIBUTE_UNUSED,
151 const frange &op2 ATTRIBUTE_UNUSED,
152 relation_kind) const
153 {
154 return VREL_VARYING;
155 }
156
157 relation_kind
158 range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
159 {
160 return VREL_VARYING;
161 }
162
163 relation_kind
164 range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
165 {
166 return VREL_VARYING;
167 }
168
169 // Return TRUE if OP1 and OP2 may be a NAN.
170
171 static inline bool
172 maybe_isnan (const frange &op1, const frange &op2)
173 {
174 return op1.maybe_isnan () || op2.maybe_isnan ();
175 }
176
177 // Floating version of relop_early_resolve that takes into account NAN
178 // and -ffinite-math-only.
179
180 inline bool
181 frelop_early_resolve (irange &r, tree type,
182 const frange &op1, const frange &op2,
183 relation_trio rel, relation_kind my_rel)
184 {
185 // If either operand is undefined, return VARYING.
186 if (empty_range_varying (r, type, op1, op2))
187 return true;
188
189 // We can fold relations from the oracle when we know both operands
190 // are free of NANs, or when -ffinite-math-only.
191 return (!maybe_isnan (op1, op2)
192 && relop_early_resolve (r, type, op1, op2, rel, my_rel));
193 }
194
195 // Crop R to [-INF, MAX] where MAX is the maximum representable number
196 // for TYPE.
197
198 static inline void
199 frange_drop_inf (frange &r, tree type)
200 {
201 REAL_VALUE_TYPE max = real_max_representable (type);
202 frange tmp (type, r.lower_bound (), max);
203 r.intersect (tmp);
204 }
205
206 // Crop R to [MIN, +INF] where MIN is the minimum representable number
207 // for TYPE.
208
209 static inline void
210 frange_drop_ninf (frange &r, tree type)
211 {
212 REAL_VALUE_TYPE min = real_min_representable (type);
213 frange tmp (type, min, r.upper_bound ());
214 r.intersect (tmp);
215 }
216
217 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
218
219 static inline void
220 frange_add_zeros (frange &r, tree type)
221 {
222 if (r.undefined_p () || r.known_isnan ())
223 return;
224
225 if (HONOR_SIGNED_ZEROS (type)
226 && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
227 {
228 frange zero;
229 zero.set_zero (type);
230 r.union_ (zero);
231 }
232 }
233
234 // Build a range that is <= VAL and store it in R. Return TRUE if
235 // further changes may be needed for R, or FALSE if R is in its final
236 // form.
237
238 static bool
239 build_le (frange &r, tree type, const frange &val)
240 {
241 gcc_checking_assert (!val.known_isnan ());
242
243 REAL_VALUE_TYPE ninf = frange_val_min (type);
244 r.set (type, ninf, val.upper_bound ());
245
246 // Add both zeros if there's the possibility of zero equality.
247 frange_add_zeros (r, type);
248
249 return true;
250 }
251
252 // Build a range that is < VAL and store it in R. Return TRUE if
253 // further changes may be needed for R, or FALSE if R is in its final
254 // form.
255
256 static bool
257 build_lt (frange &r, tree type, const frange &val)
258 {
259 gcc_checking_assert (!val.known_isnan ());
260
261 // < -INF is outside the range.
262 if (real_isinf (&val.upper_bound (), 1))
263 {
264 if (HONOR_NANS (type))
265 r.set_nan (type);
266 else
267 r.set_undefined ();
268 return false;
269 }
270 // We only support closed intervals.
271 REAL_VALUE_TYPE ninf = frange_val_min (type);
272 r.set (type, ninf, val.upper_bound ());
273 return true;
274 }
275
276 // Build a range that is >= VAL and store it in R. Return TRUE if
277 // further changes may be needed for R, or FALSE if R is in its final
278 // form.
279
280 static bool
281 build_ge (frange &r, tree type, const frange &val)
282 {
283 gcc_checking_assert (!val.known_isnan ());
284
285 REAL_VALUE_TYPE inf = frange_val_max (type);
286 r.set (type, val.lower_bound (), inf);
287
288 // Add both zeros if there's the possibility of zero equality.
289 frange_add_zeros (r, type);
290
291 return true;
292 }
293
294 // Build a range that is > VAL and store it in R. Return TRUE if
295 // further changes may be needed for R, or FALSE if R is in its final
296 // form.
297
298 static bool
299 build_gt (frange &r, tree type, const frange &val)
300 {
301 gcc_checking_assert (!val.known_isnan ());
302
303 // > +INF is outside the range.
304 if (real_isinf (&val.lower_bound (), 0))
305 {
306 if (HONOR_NANS (type))
307 r.set_nan (type);
308 else
309 r.set_undefined ();
310 return false;
311 }
312
313 // We only support closed intervals.
314 REAL_VALUE_TYPE inf = frange_val_max (type);
315 r.set (type, val.lower_bound (), inf);
316 return true;
317 }
318
319
320 class foperator_identity : public range_operator_float
321 {
322 using range_operator_float::fold_range;
323 using range_operator_float::op1_range;
324 public:
325 bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
326 const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
327 relation_trio = TRIO_VARYING) const final override
328 {
329 r = op1;
330 return true;
331 }
332 bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
333 const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
334 relation_trio = TRIO_VARYING) const final override
335 {
336 r = lhs;
337 return true;
338 }
339 public:
340 } fop_identity;
341
342 class foperator_equal : public range_operator_float
343 {
344 using range_operator_float::fold_range;
345 using range_operator_float::op1_range;
346 using range_operator_float::op2_range;
347 using range_operator_float::op1_op2_relation;
348 public:
349 bool fold_range (irange &r, tree type,
350 const frange &op1, const frange &op2,
351 relation_trio = TRIO_VARYING) const final override;
352 relation_kind op1_op2_relation (const irange &lhs) const final override
353 {
354 return equal_op1_op2_relation (lhs);
355 }
356 bool op1_range (frange &r, tree type,
357 const irange &lhs, const frange &op2,
358 relation_trio = TRIO_VARYING) const final override;
359 bool op2_range (frange &r, tree type,
360 const irange &lhs, const frange &op1,
361 relation_trio rel = TRIO_VARYING) const final override
362 {
363 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
364 }
365 } fop_equal;
366
367 bool
368 foperator_equal::fold_range (irange &r, tree type,
369 const frange &op1, const frange &op2,
370 relation_trio rel) const
371 {
372 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
373 return true;
374
375 if (op1.known_isnan () || op2.known_isnan ())
376 r = range_false (type);
377 // We can be sure the values are always equal or not if both ranges
378 // consist of a single value, and then compare them.
379 else if (op1.singleton_p () && op2.singleton_p ())
380 {
381 if (op1 == op2)
382 r = range_true (type);
383 else
384 r = range_false (type);
385 }
386 else if (!maybe_isnan (op1, op2))
387 {
388 // If ranges do not intersect, we know the range is not equal,
389 // otherwise we don't know anything for sure.
390 frange tmp = op1;
391 tmp.intersect (op2);
392 if (tmp.undefined_p ())
393 r = range_false (type);
394 else
395 r = range_true_and_false (type);
396 }
397 else
398 r = range_true_and_false (type);
399 return true;
400 }
401
402 bool
403 foperator_equal::op1_range (frange &r, tree type,
404 const irange &lhs,
405 const frange &op2,
406 relation_trio trio) const
407 {
408 relation_kind rel = trio.op1_op2 ();
409 switch (get_bool_state (r, lhs, type))
410 {
411 case BRS_TRUE:
412 // The TRUE side of x == NAN is unreachable.
413 if (op2.known_isnan ())
414 r.set_undefined ();
415 else
416 {
417 // If it's true, the result is the same as OP2.
418 r = op2;
419 // Add both zeros if there's the possibility of zero equality.
420 frange_add_zeros (r, type);
421 // The TRUE side of op1 == op2 implies op1 is !NAN.
422 r.clear_nan ();
423 }
424 break;
425
426 case BRS_FALSE:
427 // The FALSE side of op1 == op1 implies op1 is a NAN.
428 if (rel == VREL_EQ)
429 r.set_nan (type);
430 // On the FALSE side of x == NAN, we know nothing about x.
431 else if (op2.known_isnan ())
432 r.set_varying (type);
433 // If the result is false, the only time we know anything is
434 // if OP2 is a constant.
435 else if (op2.singleton_p ()
436 || (!op2.maybe_isnan () && op2.zero_p ()))
437 {
438 REAL_VALUE_TYPE tmp = op2.lower_bound ();
439 r.set (type, tmp, tmp, VR_ANTI_RANGE);
440 }
441 else
442 r.set_varying (type);
443 break;
444
445 default:
446 break;
447 }
448 return true;
449 }
450
451 class foperator_not_equal : public range_operator_float
452 {
453 using range_operator_float::fold_range;
454 using range_operator_float::op1_range;
455 using range_operator_float::op1_op2_relation;
456 public:
457 bool fold_range (irange &r, tree type,
458 const frange &op1, const frange &op2,
459 relation_trio rel = TRIO_VARYING) const final override;
460 relation_kind op1_op2_relation (const irange &lhs) const final override
461 {
462 return not_equal_op1_op2_relation (lhs);
463 }
464 bool op1_range (frange &r, tree type,
465 const irange &lhs, const frange &op2,
466 relation_trio = TRIO_VARYING) const final override;
467 } fop_not_equal;
468
469 bool
470 foperator_not_equal::fold_range (irange &r, tree type,
471 const frange &op1, const frange &op2,
472 relation_trio rel) const
473 {
474 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE))
475 return true;
476
477 // x != NAN is always TRUE.
478 if (op1.known_isnan () || op2.known_isnan ())
479 r = range_true (type);
480 // We can be sure the values are always equal or not if both ranges
481 // consist of a single value, and then compare them.
482 else if (op1.singleton_p () && op2.singleton_p ())
483 {
484 if (op1 != op2)
485 r = range_true (type);
486 else
487 r = range_false (type);
488 }
489 else if (!maybe_isnan (op1, op2))
490 {
491 // If ranges do not intersect, we know the range is not equal,
492 // otherwise we don't know anything for sure.
493 frange tmp = op1;
494 tmp.intersect (op2);
495 if (tmp.undefined_p ())
496 r = range_true (type);
497 else
498 r = range_true_and_false (type);
499 }
500 else
501 r = range_true_and_false (type);
502 return true;
503 }
504
505 bool
506 foperator_not_equal::op1_range (frange &r, tree type,
507 const irange &lhs,
508 const frange &op2,
509 relation_trio trio) const
510 {
511 relation_kind rel = trio.op1_op2 ();
512 switch (get_bool_state (r, lhs, type))
513 {
514 case BRS_TRUE:
515 // If the result is true, the only time we know anything is if
516 // OP2 is a constant.
517 if (op2.singleton_p ())
518 {
519 // This is correct even if op1 is NAN, because the following
520 // range would be ~[tmp, tmp] with the NAN property set to
521 // maybe (VARYING).
522 REAL_VALUE_TYPE tmp = op2.lower_bound ();
523 r.set (type, tmp, tmp, VR_ANTI_RANGE);
524 }
525 // The TRUE side of op1 != op1 implies op1 is NAN.
526 else if (rel == VREL_EQ)
527 r.set_nan (type);
528 else
529 r.set_varying (type);
530 break;
531
532 case BRS_FALSE:
533 // The FALSE side of x != NAN is impossible.
534 if (op2.known_isnan ())
535 r.set_undefined ();
536 else
537 {
538 // If it's false, the result is the same as OP2.
539 r = op2;
540 // Add both zeros if there's the possibility of zero equality.
541 frange_add_zeros (r, type);
542 // The FALSE side of op1 != op2 implies op1 is !NAN.
543 r.clear_nan ();
544 }
545 break;
546
547 default:
548 break;
549 }
550 return true;
551 }
552
553 class foperator_lt : public range_operator_float
554 {
555 using range_operator_float::fold_range;
556 using range_operator_float::op1_range;
557 using range_operator_float::op2_range;
558 using range_operator_float::op1_op2_relation;
559 public:
560 bool fold_range (irange &r, tree type,
561 const frange &op1, const frange &op2,
562 relation_trio = TRIO_VARYING) const final override;
563 relation_kind op1_op2_relation (const irange &lhs) const final override
564 {
565 return lt_op1_op2_relation (lhs);
566 }
567 bool op1_range (frange &r, tree type,
568 const irange &lhs, const frange &op2,
569 relation_trio = TRIO_VARYING) const final override;
570 bool op2_range (frange &r, tree type,
571 const irange &lhs, const frange &op1,
572 relation_trio = TRIO_VARYING) const final override;
573 } fop_lt;
574
575 bool
576 foperator_lt::fold_range (irange &r, tree type,
577 const frange &op1, const frange &op2,
578 relation_trio rel) const
579 {
580 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT))
581 return true;
582
583 if (op1.known_isnan () || op2.known_isnan ())
584 r = range_false (type);
585 else if (!maybe_isnan (op1, op2))
586 {
587 if (real_less (&op1.upper_bound (), &op2.lower_bound ()))
588 r = range_true (type);
589 else if (!real_less (&op1.lower_bound (), &op2.upper_bound ()))
590 r = range_false (type);
591 else
592 r = range_true_and_false (type);
593 }
594 else
595 r = range_true_and_false (type);
596 return true;
597 }
598
599 bool
600 foperator_lt::op1_range (frange &r,
601 tree type,
602 const irange &lhs,
603 const frange &op2,
604 relation_trio) const
605 {
606 switch (get_bool_state (r, lhs, type))
607 {
608 case BRS_TRUE:
609 // The TRUE side of x < NAN is unreachable.
610 if (op2.known_isnan ())
611 r.set_undefined ();
612 else if (build_lt (r, type, op2))
613 {
614 r.clear_nan ();
615 // x < y implies x is not +INF.
616 frange_drop_inf (r, type);
617 }
618 break;
619
620 case BRS_FALSE:
621 // On the FALSE side of x < NAN, we know nothing about x.
622 if (op2.known_isnan ())
623 r.set_varying (type);
624 else
625 build_ge (r, type, op2);
626 break;
627
628 default:
629 break;
630 }
631 return true;
632 }
633
634 bool
635 foperator_lt::op2_range (frange &r,
636 tree type,
637 const irange &lhs,
638 const frange &op1,
639 relation_trio) const
640 {
641 switch (get_bool_state (r, lhs, type))
642 {
643 case BRS_TRUE:
644 // The TRUE side of NAN < x is unreachable.
645 if (op1.known_isnan ())
646 r.set_undefined ();
647 else if (build_gt (r, type, op1))
648 {
649 r.clear_nan ();
650 // x < y implies y is not -INF.
651 frange_drop_ninf (r, type);
652 }
653 break;
654
655 case BRS_FALSE:
656 // On the FALSE side of NAN < x, we know nothing about x.
657 if (op1.known_isnan ())
658 r.set_varying (type);
659 else
660 build_le (r, type, op1);
661 break;
662
663 default:
664 break;
665 }
666 return true;
667 }
668
669 class foperator_le : public range_operator_float
670 {
671 using range_operator_float::fold_range;
672 using range_operator_float::op1_range;
673 using range_operator_float::op2_range;
674 using range_operator_float::op1_op2_relation;
675 public:
676 bool fold_range (irange &r, tree type,
677 const frange &op1, const frange &op2,
678 relation_trio rel = TRIO_VARYING) const final override;
679 relation_kind op1_op2_relation (const irange &lhs) const final override
680 {
681 return le_op1_op2_relation (lhs);
682 }
683 bool op1_range (frange &r, tree type,
684 const irange &lhs, const frange &op2,
685 relation_trio rel = TRIO_VARYING) const final override;
686 bool op2_range (frange &r, tree type,
687 const irange &lhs, const frange &op1,
688 relation_trio rel = TRIO_VARYING) const final override;
689 } fop_le;
690
691 bool
692 foperator_le::fold_range (irange &r, tree type,
693 const frange &op1, const frange &op2,
694 relation_trio rel) const
695 {
696 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
697 return true;
698
699 if (op1.known_isnan () || op2.known_isnan ())
700 r = range_false (type);
701 else if (!maybe_isnan (op1, op2))
702 {
703 if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
704 r = range_true (type);
705 else if (!real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
706 r = range_false (type);
707 else
708 r = range_true_and_false (type);
709 }
710 else
711 r = range_true_and_false (type);
712 return true;
713 }
714
715 bool
716 foperator_le::op1_range (frange &r,
717 tree type,
718 const irange &lhs,
719 const frange &op2,
720 relation_trio) const
721 {
722 switch (get_bool_state (r, lhs, type))
723 {
724 case BRS_TRUE:
725 // The TRUE side of x <= NAN is unreachable.
726 if (op2.known_isnan ())
727 r.set_undefined ();
728 else if (build_le (r, type, op2))
729 r.clear_nan ();
730 break;
731
732 case BRS_FALSE:
733 // On the FALSE side of x <= NAN, we know nothing about x.
734 if (op2.known_isnan ())
735 r.set_varying (type);
736 else
737 build_gt (r, type, op2);
738 break;
739
740 default:
741 break;
742 }
743 return true;
744 }
745
746 bool
747 foperator_le::op2_range (frange &r,
748 tree type,
749 const irange &lhs,
750 const frange &op1,
751 relation_trio) const
752 {
753 switch (get_bool_state (r, lhs, type))
754 {
755 case BRS_TRUE:
756 // The TRUE side of NAN <= x is unreachable.
757 if (op1.known_isnan ())
758 r.set_undefined ();
759 else if (build_ge (r, type, op1))
760 r.clear_nan ();
761 break;
762
763 case BRS_FALSE:
764 // On the FALSE side of NAN <= x, we know nothing about x.
765 if (op1.known_isnan ())
766 r.set_varying (type);
767 else
768 build_lt (r, type, op1);
769 break;
770
771 default:
772 break;
773 }
774 return true;
775 }
776
777 class foperator_gt : public range_operator_float
778 {
779 using range_operator_float::fold_range;
780 using range_operator_float::op1_range;
781 using range_operator_float::op2_range;
782 using range_operator_float::op1_op2_relation;
783 public:
784 bool fold_range (irange &r, tree type,
785 const frange &op1, const frange &op2,
786 relation_trio = TRIO_VARYING) const final override;
787 relation_kind op1_op2_relation (const irange &lhs) const final override
788 {
789 return gt_op1_op2_relation (lhs);
790 }
791 bool op1_range (frange &r, tree type,
792 const irange &lhs, const frange &op2,
793 relation_trio = TRIO_VARYING) const final override;
794 bool op2_range (frange &r, tree type,
795 const irange &lhs, const frange &op1,
796 relation_trio = TRIO_VARYING) const final override;
797 } fop_gt;
798
799 bool
800 foperator_gt::fold_range (irange &r, tree type,
801 const frange &op1, const frange &op2,
802 relation_trio rel) const
803 {
804 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT))
805 return true;
806
807 if (op1.known_isnan () || op2.known_isnan ())
808 r = range_false (type);
809 else if (!maybe_isnan (op1, op2))
810 {
811 if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
812 r = range_true (type);
813 else if (!real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
814 r = range_false (type);
815 else
816 r = range_true_and_false (type);
817 }
818 else
819 r = range_true_and_false (type);
820 return true;
821 }
822
823 bool
824 foperator_gt::op1_range (frange &r,
825 tree type,
826 const irange &lhs,
827 const frange &op2,
828 relation_trio) const
829 {
830 switch (get_bool_state (r, lhs, type))
831 {
832 case BRS_TRUE:
833 // The TRUE side of x > NAN is unreachable.
834 if (op2.known_isnan ())
835 r.set_undefined ();
836 else if (build_gt (r, type, op2))
837 {
838 r.clear_nan ();
839 // x > y implies x is not -INF.
840 frange_drop_ninf (r, type);
841 }
842 break;
843
844 case BRS_FALSE:
845 // On the FALSE side of x > NAN, we know nothing about x.
846 if (op2.known_isnan ())
847 r.set_varying (type);
848 else
849 build_le (r, type, op2);
850 break;
851
852 default:
853 break;
854 }
855 return true;
856 }
857
858 bool
859 foperator_gt::op2_range (frange &r,
860 tree type,
861 const irange &lhs,
862 const frange &op1,
863 relation_trio) const
864 {
865 switch (get_bool_state (r, lhs, type))
866 {
867 case BRS_TRUE:
868 // The TRUE side of NAN > x is unreachable.
869 if (op1.known_isnan ())
870 r.set_undefined ();
871 else if (build_lt (r, type, op1))
872 {
873 r.clear_nan ();
874 // x > y implies y is not +INF.
875 frange_drop_inf (r, type);
876 }
877 break;
878
879 case BRS_FALSE:
880 // On The FALSE side of NAN > x, we know nothing about x.
881 if (op1.known_isnan ())
882 r.set_varying (type);
883 else
884 build_ge (r, type, op1);
885 break;
886
887 default:
888 break;
889 }
890 return true;
891 }
892
893 class foperator_ge : public range_operator_float
894 {
895 using range_operator_float::fold_range;
896 using range_operator_float::op1_range;
897 using range_operator_float::op2_range;
898 using range_operator_float::op1_op2_relation;
899 public:
900 bool fold_range (irange &r, tree type,
901 const frange &op1, const frange &op2,
902 relation_trio = TRIO_VARYING) const final override;
903 relation_kind op1_op2_relation (const irange &lhs) const final override
904 {
905 return ge_op1_op2_relation (lhs);
906 }
907 bool op1_range (frange &r, tree type,
908 const irange &lhs, const frange &op2,
909 relation_trio = TRIO_VARYING) const final override;
910 bool op2_range (frange &r, tree type,
911 const irange &lhs, const frange &op1,
912 relation_trio = TRIO_VARYING) const final override;
913 } fop_ge;
914
915 bool
916 foperator_ge::fold_range (irange &r, tree type,
917 const frange &op1, const frange &op2,
918 relation_trio rel) const
919 {
920 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
921 return true;
922
923 if (op1.known_isnan () || op2.known_isnan ())
924 r = range_false (type);
925 else if (!maybe_isnan (op1, op2))
926 {
927 if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
928 r = range_true (type);
929 else if (!real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
930 r = range_false (type);
931 else
932 r = range_true_and_false (type);
933 }
934 else
935 r = range_true_and_false (type);
936 return true;
937 }
938
939 bool
940 foperator_ge::op1_range (frange &r,
941 tree type,
942 const irange &lhs,
943 const frange &op2,
944 relation_trio) const
945 {
946 switch (get_bool_state (r, lhs, type))
947 {
948 case BRS_TRUE:
949 // The TRUE side of x >= NAN is unreachable.
950 if (op2.known_isnan ())
951 r.set_undefined ();
952 else if (build_ge (r, type, op2))
953 r.clear_nan ();
954 break;
955
956 case BRS_FALSE:
957 // On the FALSE side of x >= NAN, we know nothing about x.
958 if (op2.known_isnan ())
959 r.set_varying (type);
960 else
961 build_lt (r, type, op2);
962 break;
963
964 default:
965 break;
966 }
967 return true;
968 }
969
970 bool
971 foperator_ge::op2_range (frange &r, tree type,
972 const irange &lhs,
973 const frange &op1,
974 relation_trio) const
975 {
976 switch (get_bool_state (r, lhs, type))
977 {
978 case BRS_TRUE:
979 // The TRUE side of NAN >= x is unreachable.
980 if (op1.known_isnan ())
981 r.set_undefined ();
982 else if (build_le (r, type, op1))
983 r.clear_nan ();
984 break;
985
986 case BRS_FALSE:
987 // On the FALSE side of NAN >= x, we know nothing about x.
988 if (op1.known_isnan ())
989 r.set_varying (type);
990 else
991 build_gt (r, type, op1);
992 break;
993
994 default:
995 break;
996 }
997 return true;
998 }
999
1000 // UNORDERED_EXPR comparison.
1001
1002 class foperator_unordered : public range_operator_float
1003 {
1004 using range_operator_float::fold_range;
1005 using range_operator_float::op1_range;
1006 using range_operator_float::op2_range;
1007 public:
1008 bool fold_range (irange &r, tree type,
1009 const frange &op1, const frange &op2,
1010 relation_trio = TRIO_VARYING) const final override;
1011 bool op1_range (frange &r, tree type,
1012 const irange &lhs, const frange &op2,
1013 relation_trio = TRIO_VARYING) const final override;
1014 bool op2_range (frange &r, tree type,
1015 const irange &lhs, const frange &op1,
1016 relation_trio rel = TRIO_VARYING) const final override
1017 {
1018 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1019 }
1020 } fop_unordered;
1021
1022 bool
1023 foperator_unordered::fold_range (irange &r, tree type,
1024 const frange &op1, const frange &op2,
1025 relation_trio) const
1026 {
1027 // UNORDERED is TRUE if either operand is a NAN.
1028 if (op1.known_isnan () || op2.known_isnan ())
1029 r = range_true (type);
1030 // UNORDERED is FALSE if neither operand is a NAN.
1031 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1032 r = range_false (type);
1033 else
1034 r = range_true_and_false (type);
1035 return true;
1036 }
1037
1038 bool
1039 foperator_unordered::op1_range (frange &r, tree type,
1040 const irange &lhs,
1041 const frange &op2,
1042 relation_trio trio) const
1043 {
1044 relation_kind rel = trio.op1_op2 ();
1045 switch (get_bool_state (r, lhs, type))
1046 {
1047 case BRS_TRUE:
1048 // Since at least one operand must be NAN, if one of them is
1049 // not, the other must be.
1050 if (rel == VREL_EQ || !op2.maybe_isnan ())
1051 r.set_nan (type);
1052 else
1053 r.set_varying (type);
1054 break;
1055
1056 case BRS_FALSE:
1057 // A false UNORDERED means both operands are !NAN, so it's
1058 // impossible for op2 to be a NAN.
1059 if (op2.known_isnan ())
1060 r.set_undefined ();
1061 else
1062 {
1063 r.set_varying (type);
1064 r.clear_nan ();
1065 }
1066 break;
1067
1068 default:
1069 break;
1070 }
1071 return true;
1072 }
1073
1074 // ORDERED_EXPR comparison.
1075
1076 class foperator_ordered : public range_operator_float
1077 {
1078 using range_operator_float::fold_range;
1079 using range_operator_float::op1_range;
1080 using range_operator_float::op2_range;
1081 public:
1082 bool fold_range (irange &r, tree type,
1083 const frange &op1, const frange &op2,
1084 relation_trio = TRIO_VARYING) const final override;
1085 bool op1_range (frange &r, tree type,
1086 const irange &lhs, const frange &op2,
1087 relation_trio = TRIO_VARYING) const final override;
1088 bool op2_range (frange &r, tree type,
1089 const irange &lhs, const frange &op1,
1090 relation_trio rel = TRIO_VARYING) const final override
1091 {
1092 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1093 }
1094 } fop_ordered;
1095
1096 bool
1097 foperator_ordered::fold_range (irange &r, tree type,
1098 const frange &op1, const frange &op2,
1099 relation_trio) const
1100 {
1101 if (op1.known_isnan () || op2.known_isnan ())
1102 r = range_false (type);
1103 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1104 r = range_true (type);
1105 else
1106 r = range_true_and_false (type);
1107 return true;
1108 }
1109
1110 bool
1111 foperator_ordered::op1_range (frange &r, tree type,
1112 const irange &lhs,
1113 const frange &op2,
1114 relation_trio trio) const
1115 {
1116 relation_kind rel = trio.op1_op2 ();
1117 switch (get_bool_state (r, lhs, type))
1118 {
1119 case BRS_TRUE:
1120 // The TRUE side of ORDERED means both operands are !NAN, so
1121 // it's impossible for op2 to be a NAN.
1122 if (op2.known_isnan ())
1123 r.set_undefined ();
1124 else
1125 {
1126 r.set_varying (type);
1127 r.clear_nan ();
1128 }
1129 break;
1130
1131 case BRS_FALSE:
1132 // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1133 if (rel == VREL_EQ)
1134 r.set_nan (type);
1135 else
1136 r.set_varying (type);
1137 break;
1138
1139 default:
1140 break;
1141 }
1142 return true;
1143 }
1144
1145 class foperator_negate : public range_operator_float
1146 {
1147 using range_operator_float::fold_range;
1148 using range_operator_float::op1_range;
1149 public:
1150 bool fold_range (frange &r, tree type,
1151 const frange &op1, const frange &op2,
1152 relation_trio = TRIO_VARYING) const final override
1153 {
1154 if (empty_range_varying (r, type, op1, op2))
1155 return true;
1156 if (op1.known_isnan ())
1157 {
1158 bool sign;
1159 if (op1.nan_signbit_p (sign))
1160 r.set_nan (type, !sign);
1161 else
1162 r.set_nan (type);
1163 return true;
1164 }
1165
1166 REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1167 REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1168 lh_lb = real_value_negate (&lh_lb);
1169 lh_ub = real_value_negate (&lh_ub);
1170 r.set (type, lh_ub, lh_lb);
1171 if (op1.maybe_isnan ())
1172 {
1173 bool sign;
1174 if (op1.nan_signbit_p (sign))
1175 r.update_nan (!sign);
1176 else
1177 r.update_nan ();
1178 }
1179 else
1180 r.clear_nan ();
1181 return true;
1182 }
1183 bool op1_range (frange &r, tree type,
1184 const frange &lhs, const frange &op2,
1185 relation_trio rel = TRIO_VARYING) const final override
1186 {
1187 return fold_range (r, type, lhs, op2, rel);
1188 }
1189 } fop_negate;
1190
1191 class foperator_abs : public range_operator_float
1192 {
1193 using range_operator_float::fold_range;
1194 using range_operator_float::op1_range;
1195 public:
1196 bool fold_range (frange &r, tree type,
1197 const frange &op1, const frange &,
1198 relation_trio = TRIO_VARYING) const final override;
1199 bool op1_range (frange &r, tree type,
1200 const frange &lhs, const frange &op2,
1201 relation_trio rel = TRIO_VARYING) const final override;
1202 } fop_abs;
1203
1204 bool
1205 foperator_abs::fold_range (frange &r, tree type,
1206 const frange &op1, const frange &op2,
1207 relation_trio) const
1208 {
1209 if (empty_range_varying (r, type, op1, op2))
1210 return true;
1211 if (op1.known_isnan ())
1212 {
1213 r.set_nan (type, /*sign=*/false);
1214 return true;
1215 }
1216
1217 const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1218 const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1219 // Handle the easy case where everything is positive.
1220 if (real_compare (GE_EXPR, &lh_lb, &dconst0)
1221 && !real_iszero (&lh_lb, /*sign=*/true)
1222 && !op1.maybe_isnan (/*sign=*/true))
1223 {
1224 r = op1;
1225 return true;
1226 }
1227
1228 REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
1229 REAL_VALUE_TYPE max = real_value_abs (&lh_ub);
1230 // If the range contains zero then we know that the minimum value in the
1231 // range will be zero.
1232 if (real_compare (LE_EXPR, &lh_lb, &dconst0)
1233 && real_compare (GE_EXPR, &lh_ub, &dconst0))
1234 {
1235 if (real_compare (GT_EXPR, &min, &max))
1236 max = min;
1237 min = dconst0;
1238 }
1239 else
1240 {
1241 // If the range was reversed, swap MIN and MAX.
1242 if (real_compare (GT_EXPR, &min, &max))
1243 std::swap (min, max);
1244 }
1245
1246 r.set (type, min, max);
1247 if (op1.maybe_isnan ())
1248 r.update_nan (/*sign=*/false);
1249 else
1250 r.clear_nan ();
1251 return true;
1252 }
1253
1254 bool
1255 foperator_abs::op1_range (frange &r, tree type,
1256 const frange &lhs, const frange &op2,
1257 relation_trio) const
1258 {
1259 if (empty_range_varying (r, type, lhs, op2))
1260 return true;
1261 if (lhs.known_isnan ())
1262 {
1263 r.set_nan (type);
1264 return true;
1265 }
1266
1267 // Start with the positives because negatives are an impossible result.
1268 frange positives (type, dconst0, frange_val_max (type));
1269 positives.update_nan (/*sign=*/false);
1270 positives.intersect (lhs);
1271 r = positives;
1272 // Then add the negative of each pair:
1273 // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1274 r.union_ (frange (type,
1275 real_value_negate (&positives.upper_bound ()),
1276 real_value_negate (&positives.lower_bound ())));
1277 return true;
1278 }
1279
1280 class foperator_unordered_lt : public range_operator_float
1281 {
1282 using range_operator_float::fold_range;
1283 using range_operator_float::op1_range;
1284 using range_operator_float::op2_range;
1285 public:
1286 bool fold_range (irange &r, tree type,
1287 const frange &op1, const frange &op2,
1288 relation_trio rel = TRIO_VARYING) const final override
1289 {
1290 if (op1.known_isnan () || op2.known_isnan ())
1291 {
1292 r = range_true (type);
1293 return true;
1294 }
1295 if (!fop_lt.fold_range (r, type, op1, op2, rel))
1296 return false;
1297 // The result is the same as the ordered version when the
1298 // comparison is true or when the operands cannot be NANs.
1299 if (!maybe_isnan (op1, op2) || r == range_true (type))
1300 return true;
1301 else
1302 {
1303 r = range_true_and_false (type);
1304 return true;
1305 }
1306 }
1307 bool op1_range (frange &r, tree type,
1308 const irange &lhs,
1309 const frange &op2,
1310 relation_trio trio) const final override;
1311 bool op2_range (frange &r, tree type,
1312 const irange &lhs,
1313 const frange &op1,
1314 relation_trio trio) const final override;
1315 } fop_unordered_lt;
1316
1317 bool
1318 foperator_unordered_lt::op1_range (frange &r, tree type,
1319 const irange &lhs,
1320 const frange &op2,
1321 relation_trio) const
1322 {
1323 switch (get_bool_state (r, lhs, type))
1324 {
1325 case BRS_TRUE:
1326 build_lt (r, type, op2);
1327 break;
1328
1329 case BRS_FALSE:
1330 // A false UNORDERED_LT means both operands are !NAN, so it's
1331 // impossible for op2 to be a NAN.
1332 if (op2.known_isnan ())
1333 r.set_undefined ();
1334 else if (build_ge (r, type, op2))
1335 r.clear_nan ();
1336 break;
1337
1338 default:
1339 break;
1340 }
1341 return true;
1342 }
1343
1344 bool
1345 foperator_unordered_lt::op2_range (frange &r, tree type,
1346 const irange &lhs,
1347 const frange &op1,
1348 relation_trio) const
1349 {
1350 switch (get_bool_state (r, lhs, type))
1351 {
1352 case BRS_TRUE:
1353 build_gt (r, type, op1);
1354 break;
1355
1356 case BRS_FALSE:
1357 // A false UNORDERED_LT means both operands are !NAN, so it's
1358 // impossible for op1 to be a NAN.
1359 if (op1.known_isnan ())
1360 r.set_undefined ();
1361 else if (build_le (r, type, op1))
1362 r.clear_nan ();
1363 break;
1364
1365 default:
1366 break;
1367 }
1368 return true;
1369 }
1370
1371 class foperator_unordered_le : public range_operator_float
1372 {
1373 using range_operator_float::fold_range;
1374 using range_operator_float::op1_range;
1375 using range_operator_float::op2_range;
1376 public:
1377 bool fold_range (irange &r, tree type,
1378 const frange &op1, const frange &op2,
1379 relation_trio rel = TRIO_VARYING) const final override
1380 {
1381 if (op1.known_isnan () || op2.known_isnan ())
1382 {
1383 r = range_true (type);
1384 return true;
1385 }
1386 if (!fop_le.fold_range (r, type, op1, op2, rel))
1387 return false;
1388 // The result is the same as the ordered version when the
1389 // comparison is true or when the operands cannot be NANs.
1390 if (!maybe_isnan (op1, op2) || r == range_true (type))
1391 return true;
1392 else
1393 {
1394 r = range_true_and_false (type);
1395 return true;
1396 }
1397 }
1398 bool op1_range (frange &r, tree type,
1399 const irange &lhs, const frange &op2,
1400 relation_trio = TRIO_VARYING) const final override;
1401 bool op2_range (frange &r, tree type,
1402 const irange &lhs, const frange &op1,
1403 relation_trio = TRIO_VARYING) const final override;
1404 } fop_unordered_le;
1405
1406 bool
1407 foperator_unordered_le::op1_range (frange &r, tree type,
1408 const irange &lhs, const frange &op2,
1409 relation_trio) const
1410 {
1411 switch (get_bool_state (r, lhs, type))
1412 {
1413 case BRS_TRUE:
1414 build_le (r, type, op2);
1415 break;
1416
1417 case BRS_FALSE:
1418 // A false UNORDERED_LE means both operands are !NAN, so it's
1419 // impossible for op2 to be a NAN.
1420 if (op2.known_isnan ())
1421 r.set_undefined ();
1422 else if (build_gt (r, type, op2))
1423 r.clear_nan ();
1424 break;
1425
1426 default:
1427 break;
1428 }
1429 return true;
1430 }
1431
1432 bool
1433 foperator_unordered_le::op2_range (frange &r,
1434 tree type,
1435 const irange &lhs,
1436 const frange &op1,
1437 relation_trio) const
1438 {
1439 switch (get_bool_state (r, lhs, type))
1440 {
1441 case BRS_TRUE:
1442 build_ge (r, type, op1);
1443 break;
1444
1445 case BRS_FALSE:
1446 // A false UNORDERED_LE means both operands are !NAN, so it's
1447 // impossible for op1 to be a NAN.
1448 if (op1.known_isnan ())
1449 r.set_undefined ();
1450 else if (build_lt (r, type, op1))
1451 r.clear_nan ();
1452 break;
1453
1454 default:
1455 break;
1456 }
1457 return true;
1458 }
1459
1460 class foperator_unordered_gt : public range_operator_float
1461 {
1462 using range_operator_float::fold_range;
1463 using range_operator_float::op1_range;
1464 using range_operator_float::op2_range;
1465 public:
1466 bool fold_range (irange &r, tree type,
1467 const frange &op1, const frange &op2,
1468 relation_trio rel = TRIO_VARYING) const final override
1469 {
1470 if (op1.known_isnan () || op2.known_isnan ())
1471 {
1472 r = range_true (type);
1473 return true;
1474 }
1475 if (!fop_gt.fold_range (r, type, op1, op2, rel))
1476 return false;
1477 // The result is the same as the ordered version when the
1478 // comparison is true or when the operands cannot be NANs.
1479 if (!maybe_isnan (op1, op2) || r == range_true (type))
1480 return true;
1481 else
1482 {
1483 r = range_true_and_false (type);
1484 return true;
1485 }
1486 }
1487 bool op1_range (frange &r, tree type,
1488 const irange &lhs, const frange &op2,
1489 relation_trio = TRIO_VARYING) const final override;
1490 bool op2_range (frange &r, tree type,
1491 const irange &lhs, const frange &op1,
1492 relation_trio = TRIO_VARYING) const final override;
1493 } fop_unordered_gt;
1494
1495 bool
1496 foperator_unordered_gt::op1_range (frange &r,
1497 tree type,
1498 const irange &lhs,
1499 const frange &op2,
1500 relation_trio) const
1501 {
1502 switch (get_bool_state (r, lhs, type))
1503 {
1504 case BRS_TRUE:
1505 build_gt (r, type, op2);
1506 break;
1507
1508 case BRS_FALSE:
1509 // A false UNORDERED_GT means both operands are !NAN, so it's
1510 // impossible for op2 to be a NAN.
1511 if (op2.known_isnan ())
1512 r.set_undefined ();
1513 else if (build_le (r, type, op2))
1514 r.clear_nan ();
1515 break;
1516
1517 default:
1518 break;
1519 }
1520 return true;
1521 }
1522
1523 bool
1524 foperator_unordered_gt::op2_range (frange &r,
1525 tree type,
1526 const irange &lhs,
1527 const frange &op1,
1528 relation_trio) const
1529 {
1530 switch (get_bool_state (r, lhs, type))
1531 {
1532 case BRS_TRUE:
1533 build_lt (r, type, op1);
1534 break;
1535
1536 case BRS_FALSE:
1537 // A false UNORDERED_GT means both operands are !NAN, so it's
1538 // impossible for op1 to be a NAN.
1539 if (op1.known_isnan ())
1540 r.set_undefined ();
1541 else if (build_ge (r, type, op1))
1542 r.clear_nan ();
1543 break;
1544
1545 default:
1546 break;
1547 }
1548 return true;
1549 }
1550
1551 class foperator_unordered_ge : public range_operator_float
1552 {
1553 using range_operator_float::fold_range;
1554 using range_operator_float::op1_range;
1555 using range_operator_float::op2_range;
1556 public:
1557 bool fold_range (irange &r, tree type,
1558 const frange &op1, const frange &op2,
1559 relation_trio rel = TRIO_VARYING) const final override
1560 {
1561 if (op1.known_isnan () || op2.known_isnan ())
1562 {
1563 r = range_true (type);
1564 return true;
1565 }
1566 if (!fop_ge.fold_range (r, type, op1, op2, rel))
1567 return false;
1568 // The result is the same as the ordered version when the
1569 // comparison is true or when the operands cannot be NANs.
1570 if (!maybe_isnan (op1, op2) || r == range_true (type))
1571 return true;
1572 else
1573 {
1574 r = range_true_and_false (type);
1575 return true;
1576 }
1577 }
1578 bool op1_range (frange &r, tree type,
1579 const irange &lhs, const frange &op2,
1580 relation_trio = TRIO_VARYING) const final override;
1581 bool op2_range (frange &r, tree type,
1582 const irange &lhs, const frange &op1,
1583 relation_trio = TRIO_VARYING) const final override;
1584 } fop_unordered_ge;
1585
1586 bool
1587 foperator_unordered_ge::op1_range (frange &r,
1588 tree type,
1589 const irange &lhs,
1590 const frange &op2,
1591 relation_trio) const
1592 {
1593 switch (get_bool_state (r, lhs, type))
1594 {
1595 case BRS_TRUE:
1596 build_ge (r, type, op2);
1597 break;
1598
1599 case BRS_FALSE:
1600 // A false UNORDERED_GE means both operands are !NAN, so it's
1601 // impossible for op2 to be a NAN.
1602 if (op2.known_isnan ())
1603 r.set_undefined ();
1604 else if (build_lt (r, type, op2))
1605 r.clear_nan ();
1606 break;
1607
1608 default:
1609 break;
1610 }
1611 return true;
1612 }
1613
1614 bool
1615 foperator_unordered_ge::op2_range (frange &r, tree type,
1616 const irange &lhs,
1617 const frange &op1,
1618 relation_trio) const
1619 {
1620 switch (get_bool_state (r, lhs, type))
1621 {
1622 case BRS_TRUE:
1623 build_le (r, type, op1);
1624 break;
1625
1626 case BRS_FALSE:
1627 // A false UNORDERED_GE means both operands are !NAN, so it's
1628 // impossible for op1 to be a NAN.
1629 if (op1.known_isnan ())
1630 r.set_undefined ();
1631 else if (build_gt (r, type, op1))
1632 r.clear_nan ();
1633 break;
1634
1635 default:
1636 break;
1637 }
1638 return true;
1639 }
1640
1641 class foperator_unordered_equal : public range_operator_float
1642 {
1643 using range_operator_float::fold_range;
1644 using range_operator_float::op1_range;
1645 using range_operator_float::op2_range;
1646 public:
1647 bool fold_range (irange &r, tree type,
1648 const frange &op1, const frange &op2,
1649 relation_trio rel = TRIO_VARYING) const final override
1650 {
1651 if (op1.known_isnan () || op2.known_isnan ())
1652 {
1653 r = range_true (type);
1654 return true;
1655 }
1656 if (!fop_equal.fold_range (r, type, op1, op2, rel))
1657 return false;
1658 // The result is the same as the ordered version when the
1659 // comparison is true or when the operands cannot be NANs.
1660 if (!maybe_isnan (op1, op2) || r == range_true (type))
1661 return true;
1662 else
1663 {
1664 r = range_true_and_false (type);
1665 return true;
1666 }
1667 }
1668 bool op1_range (frange &r, tree type,
1669 const irange &lhs, const frange &op2,
1670 relation_trio = TRIO_VARYING) const final override;
1671 bool op2_range (frange &r, tree type,
1672 const irange &lhs, const frange &op1,
1673 relation_trio rel = TRIO_VARYING) const final override
1674 {
1675 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1676 }
1677 } fop_unordered_equal;
1678
1679 bool
1680 foperator_unordered_equal::op1_range (frange &r, tree type,
1681 const irange &lhs,
1682 const frange &op2,
1683 relation_trio) const
1684 {
1685 switch (get_bool_state (r, lhs, type))
1686 {
1687 case BRS_TRUE:
1688 // If it's true, the result is the same as OP2 plus a NAN.
1689 r = op2;
1690 // Add both zeros if there's the possibility of zero equality.
1691 frange_add_zeros (r, type);
1692 // Add the posibility of a NAN.
1693 r.update_nan ();
1694 break;
1695
1696 case BRS_FALSE:
1697 // A false UNORDERED_EQ means both operands are !NAN, so it's
1698 // impossible for op2 to be a NAN.
1699 if (op2.known_isnan ())
1700 r.set_undefined ();
1701 else
1702 {
1703 // The false side indictates !NAN and not equal. We can at least
1704 // represent !NAN.
1705 r.set_varying (type);
1706 r.clear_nan ();
1707 }
1708 break;
1709
1710 default:
1711 break;
1712 }
1713 return true;
1714 }
1715
1716 // Instantiate a range_op_table for floating point operations.
1717 static floating_op_table global_floating_table;
1718
1719 // Pointer to the float table so the dispatch code can access it.
1720 floating_op_table *floating_tree_table = &global_floating_table;
1721
1722 floating_op_table::floating_op_table ()
1723 {
1724 set (SSA_NAME, fop_identity);
1725 set (PAREN_EXPR, fop_identity);
1726 set (OBJ_TYPE_REF, fop_identity);
1727 set (REAL_CST, fop_identity);
1728
1729 // All the relational operators are expected to work, because the
1730 // calculation of ranges on outgoing edges expect the handlers to be
1731 // present.
1732 set (EQ_EXPR, fop_equal);
1733 set (NE_EXPR, fop_not_equal);
1734 set (LT_EXPR, fop_lt);
1735 set (LE_EXPR, fop_le);
1736 set (GT_EXPR, fop_gt);
1737 set (GE_EXPR, fop_ge);
1738 set (UNLE_EXPR, fop_unordered_le);
1739 set (UNLT_EXPR, fop_unordered_lt);
1740 set (UNGE_EXPR, fop_unordered_ge);
1741 set (UNGT_EXPR, fop_unordered_gt);
1742 set (UNEQ_EXPR, fop_unordered_equal);
1743 set (ORDERED_EXPR, fop_ordered);
1744 set (UNORDERED_EXPR, fop_unordered);
1745
1746 set (ABS_EXPR, fop_abs);
1747 set (NEGATE_EXPR, fop_negate);
1748 }
1749
1750 // Return a pointer to the range_operator_float instance, if there is
1751 // one associated with tree_code CODE.
1752
1753 range_operator_float *
1754 floating_op_table::operator[] (enum tree_code code)
1755 {
1756 return m_range_tree[code];
1757 }
1758
1759 // Add OP to the handler table for CODE.
1760
1761 void
1762 floating_op_table::set (enum tree_code code, range_operator_float &op)
1763 {
1764 gcc_checking_assert (m_range_tree[code] == NULL);
1765 m_range_tree[code] = &op;
1766 }
1767
1768 #if CHECKING_P
1769 #include "selftest.h"
1770
1771 namespace selftest
1772 {
1773
1774 // Build an frange from string endpoints.
1775
1776 inline frange
1777 frange_float (const char *lb, const char *ub, tree type = float_type_node)
1778 {
1779 REAL_VALUE_TYPE min, max;
1780 gcc_assert (real_from_string (&min, lb) == 0);
1781 gcc_assert (real_from_string (&max, ub) == 0);
1782 return frange (type, min, max);
1783 }
1784
1785 void
1786 range_op_float_tests ()
1787 {
1788 frange r, r0, r1;
1789 frange trange (float_type_node);
1790
1791 // negate([-5, +10]) => [-10, 5]
1792 r0 = frange_float ("-5", "10");
1793 fop_negate.fold_range (r, float_type_node, r0, trange);
1794 ASSERT_EQ (r, frange_float ("-10", "5"));
1795
1796 // negate([0, 1] -NAN) => [-1, -0] +NAN
1797 r0 = frange_float ("0", "1");
1798 r0.update_nan (true);
1799 fop_negate.fold_range (r, float_type_node, r0, trange);
1800 r1 = frange_float ("-1", "-0");
1801 r1.update_nan (false);
1802 ASSERT_EQ (r, r1);
1803 }
1804
1805 } // namespace selftest
1806
1807 #endif // CHECKING_P