]> git.ipfire.org Git - people/ms/gcc.git/blob - gcc/range-op-float.cc
c++: namespace-scoped friend in local class [PR69410]
[people/ms/gcc.git] / gcc / range-op-float.cc
1 /* Floating point range operators.
2 Copyright (C) 2022-2023 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, tree type,
53 const frange &op1, const frange &op2,
54 relation_trio trio) const
55 {
56 if (empty_range_varying (r, type, op1, op2))
57 return true;
58 if (op1.known_isnan () || op2.known_isnan ())
59 {
60 r.set_nan (op1.type ());
61 return true;
62 }
63
64 REAL_VALUE_TYPE lb, ub;
65 bool maybe_nan;
66 rv_fold (lb, ub, maybe_nan, type,
67 op1.lower_bound (), op1.upper_bound (),
68 op2.lower_bound (), op2.upper_bound (), trio.op1_op2 ());
69
70 // Handle possible NANs by saturating to the appropriate INF if only
71 // one end is a NAN. If both ends are a NAN, just return a NAN.
72 bool lb_nan = real_isnan (&lb);
73 bool ub_nan = real_isnan (&ub);
74 if (lb_nan && ub_nan)
75 {
76 r.set_nan (type);
77 return true;
78 }
79 if (lb_nan)
80 lb = dconstninf;
81 else if (ub_nan)
82 ub = dconstinf;
83
84 r.set (type, lb, ub);
85
86 if (lb_nan || ub_nan || maybe_nan
87 || op1.maybe_isnan ()
88 || op2.maybe_isnan ())
89 // Keep the default NAN (with a varying sign) set by the setter.
90 ;
91 else
92 r.clear_nan ();
93
94 // If the result has overflowed and flag_trapping_math, folding this
95 // operation could elide an overflow or division by zero exception.
96 // Avoid returning a singleton +-INF, to keep the propagators (DOM
97 // and substitute_and_fold_engine) from folding. See PR107608.
98 if (flag_trapping_math
99 && MODE_HAS_INFINITIES (TYPE_MODE (type))
100 && r.known_isinf () && !op1.known_isinf () && !op2.known_isinf ())
101 {
102 REAL_VALUE_TYPE inf = r.lower_bound ();
103 if (real_isneg (&inf))
104 {
105 REAL_VALUE_TYPE min = real_min_representable (type);
106 r.set (type, inf, min);
107 }
108 else
109 {
110 REAL_VALUE_TYPE max = real_max_representable (type);
111 r.set (type, max, inf);
112 }
113 }
114
115 return true;
116 }
117
118 // For a given operation, fold two sets of ranges into [lb, ub].
119 // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
120 // UB, the final range has the possiblity of a NAN.
121 void
122 range_operator_float::rv_fold (REAL_VALUE_TYPE &lb,
123 REAL_VALUE_TYPE &ub,
124 bool &maybe_nan,
125 tree type ATTRIBUTE_UNUSED,
126 const REAL_VALUE_TYPE &lh_lb ATTRIBUTE_UNUSED,
127 const REAL_VALUE_TYPE &lh_ub ATTRIBUTE_UNUSED,
128 const REAL_VALUE_TYPE &rh_lb ATTRIBUTE_UNUSED,
129 const REAL_VALUE_TYPE &rh_ub ATTRIBUTE_UNUSED,
130 relation_kind) const
131 {
132 lb = dconstninf;
133 ub = dconstinf;
134 maybe_nan = true;
135 }
136
137 bool
138 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
139 tree type ATTRIBUTE_UNUSED,
140 const frange &lh ATTRIBUTE_UNUSED,
141 const irange &rh ATTRIBUTE_UNUSED,
142 relation_trio) const
143 {
144 return false;
145 }
146
147 bool
148 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
149 tree type ATTRIBUTE_UNUSED,
150 const frange &lh ATTRIBUTE_UNUSED,
151 const frange &rh ATTRIBUTE_UNUSED,
152 relation_trio) const
153 {
154 return false;
155 }
156
157 bool
158 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
159 tree type ATTRIBUTE_UNUSED,
160 const frange &lhs ATTRIBUTE_UNUSED,
161 const frange &op2 ATTRIBUTE_UNUSED,
162 relation_trio) const
163 {
164 return false;
165 }
166
167 bool
168 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
169 tree type ATTRIBUTE_UNUSED,
170 const irange &lhs ATTRIBUTE_UNUSED,
171 const frange &op2 ATTRIBUTE_UNUSED,
172 relation_trio) const
173 {
174 return false;
175 }
176
177 bool
178 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
179 tree type ATTRIBUTE_UNUSED,
180 const frange &lhs ATTRIBUTE_UNUSED,
181 const frange &op1 ATTRIBUTE_UNUSED,
182 relation_trio) const
183 {
184 return false;
185 }
186
187 bool
188 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
189 tree type ATTRIBUTE_UNUSED,
190 const irange &lhs ATTRIBUTE_UNUSED,
191 const frange &op1 ATTRIBUTE_UNUSED,
192 relation_trio) const
193 {
194 return false;
195 }
196
197 relation_kind
198 range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
199 const frange &op1 ATTRIBUTE_UNUSED,
200 const frange &op2 ATTRIBUTE_UNUSED,
201 relation_kind) const
202 {
203 return VREL_VARYING;
204 }
205
206 relation_kind
207 range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
208 const frange &op1 ATTRIBUTE_UNUSED,
209 const frange &op2 ATTRIBUTE_UNUSED,
210 relation_kind) const
211 {
212 return VREL_VARYING;
213 }
214
215 relation_kind
216 range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
217 const frange &op1 ATTRIBUTE_UNUSED,
218 const frange &op2 ATTRIBUTE_UNUSED,
219 relation_kind) const
220 {
221 return VREL_VARYING;
222 }
223
224 relation_kind
225 range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
226 const frange &op1 ATTRIBUTE_UNUSED,
227 const frange &op2 ATTRIBUTE_UNUSED,
228 relation_kind) const
229 {
230 return VREL_VARYING;
231 }
232
233 relation_kind
234 range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
235 {
236 return VREL_VARYING;
237 }
238
239 relation_kind
240 range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
241 {
242 return VREL_VARYING;
243 }
244
245 // Return TRUE if OP1 and OP2 may be a NAN.
246
247 static inline bool
248 maybe_isnan (const frange &op1, const frange &op2)
249 {
250 return op1.maybe_isnan () || op2.maybe_isnan ();
251 }
252
253 // Floating version of relop_early_resolve that takes into account NAN
254 // and -ffinite-math-only.
255
256 inline bool
257 frelop_early_resolve (irange &r, tree type,
258 const frange &op1, const frange &op2,
259 relation_trio rel, relation_kind my_rel)
260 {
261 // If either operand is undefined, return VARYING.
262 if (empty_range_varying (r, type, op1, op2))
263 return true;
264
265 // We can fold relations from the oracle when we know both operands
266 // are free of NANs, or when -ffinite-math-only.
267 return (!maybe_isnan (op1, op2)
268 && relop_early_resolve (r, type, op1, op2, rel, my_rel));
269 }
270
271 // Set VALUE to its next real value, or INF if the operation overflows.
272
273 inline void
274 frange_nextafter (enum machine_mode mode,
275 REAL_VALUE_TYPE &value,
276 const REAL_VALUE_TYPE &inf)
277 {
278 if (MODE_COMPOSITE_P (mode)
279 && (real_isdenormal (&value, mode) || real_iszero (&value)))
280 {
281 // IBM extended denormals only have DFmode precision.
282 REAL_VALUE_TYPE tmp, tmp2;
283 real_convert (&tmp2, DFmode, &value);
284 real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
285 real_convert (&value, mode, &tmp);
286 }
287 else
288 {
289 REAL_VALUE_TYPE tmp;
290 real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
291 value = tmp;
292 }
293 }
294
295 // Like real_arithmetic, but round the result to INF if the operation
296 // produced inexact results.
297 //
298 // ?? There is still one problematic case, i387. With
299 // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
300 // XFmode (long_double_type_node), so that case is OK. But without
301 // -mfpmath=sse, all the SF/DFmode computations are in XFmode
302 // precision (64-bit mantissa) and only occassionally rounded to
303 // SF/DFmode (when storing into memory from the 387 stack). Maybe
304 // this is ok as well though it is just occassionally more precise. ??
305
306 static void
307 frange_arithmetic (enum tree_code code, tree type,
308 REAL_VALUE_TYPE &result,
309 const REAL_VALUE_TYPE &op1,
310 const REAL_VALUE_TYPE &op2,
311 const REAL_VALUE_TYPE &inf)
312 {
313 REAL_VALUE_TYPE value;
314 enum machine_mode mode = TYPE_MODE (type);
315 bool mode_composite = MODE_COMPOSITE_P (mode);
316
317 bool inexact = real_arithmetic (&value, code, &op1, &op2);
318 real_convert (&result, mode, &value);
319
320 // Be extra careful if there may be discrepancies between the
321 // compile and runtime results.
322 bool round = false;
323 if (mode_composite)
324 round = true;
325 else
326 {
327 bool low = real_isneg (&inf);
328 round = (low ? !real_less (&result, &value)
329 : !real_less (&value, &result));
330 if (real_isinf (&result, !low)
331 && !real_isinf (&value)
332 && !flag_rounding_math)
333 {
334 // Use just [+INF, +INF] rather than [MAX, +INF]
335 // even if value is larger than MAX and rounds to
336 // nearest to +INF. Similarly just [-INF, -INF]
337 // rather than [-INF, +MAX] even if value is smaller
338 // than -MAX and rounds to nearest to -INF.
339 // Unless INEXACT is true, in that case we need some
340 // extra buffer.
341 if (!inexact)
342 round = false;
343 else
344 {
345 REAL_VALUE_TYPE tmp = result, tmp2;
346 frange_nextafter (mode, tmp, inf);
347 // TMP is at this point the maximum representable
348 // number.
349 real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp);
350 if (real_isneg (&tmp2) != low
351 && (REAL_EXP (&tmp2) - REAL_EXP (&tmp)
352 >= 2 - REAL_MODE_FORMAT (mode)->p))
353 round = false;
354 }
355 }
356 }
357 if (round && (inexact || !real_identical (&result, &value)))
358 {
359 if (mode_composite
360 && (real_isdenormal (&result, mode) || real_iszero (&result)))
361 {
362 // IBM extended denormals only have DFmode precision.
363 REAL_VALUE_TYPE tmp, tmp2;
364 real_convert (&tmp2, DFmode, &value);
365 real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
366 real_convert (&result, mode, &tmp);
367 }
368 else
369 frange_nextafter (mode, result, inf);
370 }
371 if (mode_composite)
372 switch (code)
373 {
374 case PLUS_EXPR:
375 case MINUS_EXPR:
376 // ibm-ldouble-format documents 1ulp for + and -.
377 frange_nextafter (mode, result, inf);
378 break;
379 case MULT_EXPR:
380 // ibm-ldouble-format documents 2ulps for *.
381 frange_nextafter (mode, result, inf);
382 frange_nextafter (mode, result, inf);
383 break;
384 case RDIV_EXPR:
385 // ibm-ldouble-format documents 3ulps for /.
386 frange_nextafter (mode, result, inf);
387 frange_nextafter (mode, result, inf);
388 frange_nextafter (mode, result, inf);
389 break;
390 default:
391 break;
392 }
393 }
394
395 // Crop R to [-INF, MAX] where MAX is the maximum representable number
396 // for TYPE.
397
398 static inline void
399 frange_drop_inf (frange &r, tree type)
400 {
401 REAL_VALUE_TYPE max = real_max_representable (type);
402 frange tmp (type, r.lower_bound (), max);
403 r.intersect (tmp);
404 }
405
406 // Crop R to [MIN, +INF] where MIN is the minimum representable number
407 // for TYPE.
408
409 static inline void
410 frange_drop_ninf (frange &r, tree type)
411 {
412 REAL_VALUE_TYPE min = real_min_representable (type);
413 frange tmp (type, min, r.upper_bound ());
414 r.intersect (tmp);
415 }
416
417 // Crop R to [MIN, MAX] where MAX is the maximum representable number
418 // for TYPE and MIN the minimum representable number for TYPE.
419
420 static inline void
421 frange_drop_infs (frange &r, tree type)
422 {
423 REAL_VALUE_TYPE max = real_max_representable (type);
424 REAL_VALUE_TYPE min = real_min_representable (type);
425 frange tmp (type, min, max);
426 r.intersect (tmp);
427 }
428
429 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
430
431 static inline void
432 frange_add_zeros (frange &r, tree type)
433 {
434 if (r.undefined_p () || r.known_isnan ())
435 return;
436
437 if (HONOR_SIGNED_ZEROS (type)
438 && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
439 {
440 frange zero;
441 zero.set_zero (type);
442 r.union_ (zero);
443 }
444 }
445
446 // Build a range that is <= VAL and store it in R. Return TRUE if
447 // further changes may be needed for R, or FALSE if R is in its final
448 // form.
449
450 static bool
451 build_le (frange &r, tree type, const frange &val)
452 {
453 gcc_checking_assert (!val.known_isnan ());
454
455 REAL_VALUE_TYPE ninf = frange_val_min (type);
456 r.set (type, ninf, val.upper_bound ());
457
458 // Add both zeros if there's the possibility of zero equality.
459 frange_add_zeros (r, type);
460
461 return true;
462 }
463
464 // Build a range that is < VAL and store it in R. Return TRUE if
465 // further changes may be needed for R, or FALSE if R is in its final
466 // form.
467
468 static bool
469 build_lt (frange &r, tree type, const frange &val)
470 {
471 gcc_checking_assert (!val.known_isnan ());
472
473 // < -INF is outside the range.
474 if (real_isinf (&val.upper_bound (), 1))
475 {
476 if (HONOR_NANS (type))
477 r.set_nan (type);
478 else
479 r.set_undefined ();
480 return false;
481 }
482
483 REAL_VALUE_TYPE ninf = frange_val_min (type);
484 REAL_VALUE_TYPE prev = val.upper_bound ();
485 machine_mode mode = TYPE_MODE (type);
486 // Default to the conservatively correct closed ranges for
487 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
488 // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
489 // will crop the range appropriately.
490 if (!MODE_COMPOSITE_P (mode))
491 frange_nextafter (mode, prev, ninf);
492 r.set (type, ninf, prev);
493 return true;
494 }
495
496 // Build a range that is >= VAL and store it in R. Return TRUE if
497 // further changes may be needed for R, or FALSE if R is in its final
498 // form.
499
500 static bool
501 build_ge (frange &r, tree type, const frange &val)
502 {
503 gcc_checking_assert (!val.known_isnan ());
504
505 REAL_VALUE_TYPE inf = frange_val_max (type);
506 r.set (type, val.lower_bound (), inf);
507
508 // Add both zeros if there's the possibility of zero equality.
509 frange_add_zeros (r, type);
510
511 return true;
512 }
513
514 // Build a range that is > VAL and store it in R. Return TRUE if
515 // further changes may be needed for R, or FALSE if R is in its final
516 // form.
517
518 static bool
519 build_gt (frange &r, tree type, const frange &val)
520 {
521 gcc_checking_assert (!val.known_isnan ());
522
523 // > +INF is outside the range.
524 if (real_isinf (&val.lower_bound (), 0))
525 {
526 if (HONOR_NANS (type))
527 r.set_nan (type);
528 else
529 r.set_undefined ();
530 return false;
531 }
532
533 REAL_VALUE_TYPE inf = frange_val_max (type);
534 REAL_VALUE_TYPE next = val.lower_bound ();
535 machine_mode mode = TYPE_MODE (type);
536 // Default to the conservatively correct closed ranges for
537 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
538 // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
539 // will crop the range appropriately.
540 if (!MODE_COMPOSITE_P (mode))
541 frange_nextafter (mode, next, inf);
542 r.set (type, next, inf);
543 return true;
544 }
545
546
547 class foperator_identity : public range_operator_float
548 {
549 using range_operator_float::fold_range;
550 using range_operator_float::op1_range;
551 public:
552 bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
553 const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
554 relation_trio = TRIO_VARYING) const final override
555 {
556 r = op1;
557 return true;
558 }
559 bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
560 const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
561 relation_trio = TRIO_VARYING) const final override
562 {
563 r = lhs;
564 return true;
565 }
566 public:
567 } fop_identity;
568
569 class foperator_equal : public range_operator_float
570 {
571 using range_operator_float::fold_range;
572 using range_operator_float::op1_range;
573 using range_operator_float::op2_range;
574 using range_operator_float::op1_op2_relation;
575 public:
576 bool fold_range (irange &r, tree type,
577 const frange &op1, const frange &op2,
578 relation_trio = TRIO_VARYING) const final override;
579 relation_kind op1_op2_relation (const irange &lhs) const final override
580 {
581 return equal_op1_op2_relation (lhs);
582 }
583 bool op1_range (frange &r, tree type,
584 const irange &lhs, const frange &op2,
585 relation_trio = TRIO_VARYING) const final override;
586 bool op2_range (frange &r, tree type,
587 const irange &lhs, const frange &op1,
588 relation_trio rel = TRIO_VARYING) const final override
589 {
590 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
591 }
592 } fop_equal;
593
594 bool
595 foperator_equal::fold_range (irange &r, tree type,
596 const frange &op1, const frange &op2,
597 relation_trio rel) const
598 {
599 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
600 return true;
601
602 if (op1.known_isnan () || op2.known_isnan ())
603 r = range_false (type);
604 // We can be sure the values are always equal or not if both ranges
605 // consist of a single value, and then compare them.
606 else if (op1.singleton_p () && op2.singleton_p ())
607 {
608 if (op1 == op2)
609 r = range_true (type);
610 // If one operand is -0.0 and other 0.0, they are still equal.
611 else if (real_iszero (&op1.lower_bound ())
612 && real_iszero (&op2.lower_bound ()))
613 r = range_true (type);
614 else
615 r = range_false (type);
616 }
617 else if (!maybe_isnan (op1, op2))
618 {
619 // If ranges do not intersect, we know the range is not equal,
620 // otherwise we don't know anything for sure.
621 frange tmp = op1;
622 tmp.intersect (op2);
623 if (tmp.undefined_p ())
624 {
625 // If one range is [whatever, -0.0] and another
626 // [0.0, whatever2], we don't know anything either,
627 // because -0.0 == 0.0.
628 if ((real_iszero (&op1.upper_bound ())
629 && real_iszero (&op2.lower_bound ()))
630 || (real_iszero (&op1.lower_bound ())
631 && real_iszero (&op2.upper_bound ())))
632 r = range_true_and_false (type);
633 else
634 r = range_false (type);
635 }
636 else
637 r = range_true_and_false (type);
638 }
639 else
640 r = range_true_and_false (type);
641 return true;
642 }
643
644 bool
645 foperator_equal::op1_range (frange &r, tree type,
646 const irange &lhs,
647 const frange &op2,
648 relation_trio trio) const
649 {
650 relation_kind rel = trio.op1_op2 ();
651 switch (get_bool_state (r, lhs, type))
652 {
653 case BRS_TRUE:
654 // The TRUE side of x == NAN is unreachable.
655 if (op2.known_isnan ())
656 r.set_undefined ();
657 else
658 {
659 // If it's true, the result is the same as OP2.
660 r = op2;
661 // Add both zeros if there's the possibility of zero equality.
662 frange_add_zeros (r, type);
663 // The TRUE side of op1 == op2 implies op1 is !NAN.
664 r.clear_nan ();
665 }
666 break;
667
668 case BRS_FALSE:
669 // The FALSE side of op1 == op1 implies op1 is a NAN.
670 if (rel == VREL_EQ)
671 r.set_nan (type);
672 // On the FALSE side of x == NAN, we know nothing about x.
673 else if (op2.known_isnan ())
674 r.set_varying (type);
675 // If the result is false, the only time we know anything is
676 // if OP2 is a constant.
677 else if (op2.singleton_p ()
678 || (!op2.maybe_isnan () && op2.zero_p ()))
679 {
680 REAL_VALUE_TYPE tmp = op2.lower_bound ();
681 r.set (type, tmp, tmp, VR_ANTI_RANGE);
682 }
683 else
684 r.set_varying (type);
685 break;
686
687 default:
688 break;
689 }
690 return true;
691 }
692
693 class foperator_not_equal : public range_operator_float
694 {
695 using range_operator_float::fold_range;
696 using range_operator_float::op1_range;
697 using range_operator_float::op1_op2_relation;
698 public:
699 bool fold_range (irange &r, tree type,
700 const frange &op1, const frange &op2,
701 relation_trio rel = TRIO_VARYING) const final override;
702 relation_kind op1_op2_relation (const irange &lhs) const final override
703 {
704 return not_equal_op1_op2_relation (lhs);
705 }
706 bool op1_range (frange &r, tree type,
707 const irange &lhs, const frange &op2,
708 relation_trio = TRIO_VARYING) const final override;
709 } fop_not_equal;
710
711 bool
712 foperator_not_equal::fold_range (irange &r, tree type,
713 const frange &op1, const frange &op2,
714 relation_trio rel) const
715 {
716 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE))
717 return true;
718
719 // x != NAN is always TRUE.
720 if (op1.known_isnan () || op2.known_isnan ())
721 r = range_true (type);
722 // We can be sure the values are always equal or not if both ranges
723 // consist of a single value, and then compare them.
724 else if (op1.singleton_p () && op2.singleton_p ())
725 {
726 if (op1 == op2)
727 r = range_false (type);
728 // If one operand is -0.0 and other 0.0, they are still equal.
729 else if (real_iszero (&op1.lower_bound ())
730 && real_iszero (&op2.lower_bound ()))
731 r = range_false (type);
732 else
733 r = range_true (type);
734 }
735 else if (!maybe_isnan (op1, op2))
736 {
737 // If ranges do not intersect, we know the range is not equal,
738 // otherwise we don't know anything for sure.
739 frange tmp = op1;
740 tmp.intersect (op2);
741 if (tmp.undefined_p ())
742 {
743 // If one range is [whatever, -0.0] and another
744 // [0.0, whatever2], we don't know anything either,
745 // because -0.0 == 0.0.
746 if ((real_iszero (&op1.upper_bound ())
747 && real_iszero (&op2.lower_bound ()))
748 || (real_iszero (&op1.lower_bound ())
749 && real_iszero (&op2.upper_bound ())))
750 r = range_true_and_false (type);
751 else
752 r = range_true (type);
753 }
754 else
755 r = range_true_and_false (type);
756 }
757 else
758 r = range_true_and_false (type);
759 return true;
760 }
761
762 bool
763 foperator_not_equal::op1_range (frange &r, tree type,
764 const irange &lhs,
765 const frange &op2,
766 relation_trio trio) const
767 {
768 relation_kind rel = trio.op1_op2 ();
769 switch (get_bool_state (r, lhs, type))
770 {
771 case BRS_TRUE:
772 // If the result is true, the only time we know anything is if
773 // OP2 is a constant.
774 if (op2.singleton_p ())
775 {
776 // This is correct even if op1 is NAN, because the following
777 // range would be ~[tmp, tmp] with the NAN property set to
778 // maybe (VARYING).
779 REAL_VALUE_TYPE tmp = op2.lower_bound ();
780 r.set (type, tmp, tmp, VR_ANTI_RANGE);
781 }
782 // The TRUE side of op1 != op1 implies op1 is NAN.
783 else if (rel == VREL_EQ)
784 r.set_nan (type);
785 else
786 r.set_varying (type);
787 break;
788
789 case BRS_FALSE:
790 // The FALSE side of x != NAN is impossible.
791 if (op2.known_isnan ())
792 r.set_undefined ();
793 else
794 {
795 // If it's false, the result is the same as OP2.
796 r = op2;
797 // Add both zeros if there's the possibility of zero equality.
798 frange_add_zeros (r, type);
799 // The FALSE side of op1 != op2 implies op1 is !NAN.
800 r.clear_nan ();
801 }
802 break;
803
804 default:
805 break;
806 }
807 return true;
808 }
809
810 class foperator_lt : public range_operator_float
811 {
812 using range_operator_float::fold_range;
813 using range_operator_float::op1_range;
814 using range_operator_float::op2_range;
815 using range_operator_float::op1_op2_relation;
816 public:
817 bool fold_range (irange &r, tree type,
818 const frange &op1, const frange &op2,
819 relation_trio = TRIO_VARYING) const final override;
820 relation_kind op1_op2_relation (const irange &lhs) const final override
821 {
822 return lt_op1_op2_relation (lhs);
823 }
824 bool op1_range (frange &r, tree type,
825 const irange &lhs, const frange &op2,
826 relation_trio = TRIO_VARYING) const final override;
827 bool op2_range (frange &r, tree type,
828 const irange &lhs, const frange &op1,
829 relation_trio = TRIO_VARYING) const final override;
830 } fop_lt;
831
832 bool
833 foperator_lt::fold_range (irange &r, tree type,
834 const frange &op1, const frange &op2,
835 relation_trio rel) const
836 {
837 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT))
838 return true;
839
840 if (op1.known_isnan () || op2.known_isnan ())
841 r = range_false (type);
842 else if (!maybe_isnan (op1, op2))
843 {
844 if (real_less (&op1.upper_bound (), &op2.lower_bound ()))
845 r = range_true (type);
846 else if (!real_less (&op1.lower_bound (), &op2.upper_bound ()))
847 r = range_false (type);
848 else
849 r = range_true_and_false (type);
850 }
851 else
852 r = range_true_and_false (type);
853 return true;
854 }
855
856 bool
857 foperator_lt::op1_range (frange &r,
858 tree type,
859 const irange &lhs,
860 const frange &op2,
861 relation_trio) const
862 {
863 switch (get_bool_state (r, lhs, type))
864 {
865 case BRS_TRUE:
866 // The TRUE side of x < NAN is unreachable.
867 if (op2.known_isnan ())
868 r.set_undefined ();
869 else if (op2.undefined_p ())
870 return false;
871 else if (build_lt (r, type, op2))
872 {
873 r.clear_nan ();
874 // x < y implies x is not +INF.
875 frange_drop_inf (r, type);
876 }
877 break;
878
879 case BRS_FALSE:
880 // On the FALSE side of x < NAN, we know nothing about x.
881 if (op2.known_isnan ())
882 r.set_varying (type);
883 else
884 build_ge (r, type, op2);
885 break;
886
887 default:
888 break;
889 }
890 return true;
891 }
892
893 bool
894 foperator_lt::op2_range (frange &r,
895 tree type,
896 const irange &lhs,
897 const frange &op1,
898 relation_trio) const
899 {
900 switch (get_bool_state (r, lhs, type))
901 {
902 case BRS_TRUE:
903 // The TRUE side of NAN < x is unreachable.
904 if (op1.known_isnan ())
905 r.set_undefined ();
906 else if (op1.undefined_p ())
907 return false;
908 else if (build_gt (r, type, op1))
909 {
910 r.clear_nan ();
911 // x < y implies y is not -INF.
912 frange_drop_ninf (r, type);
913 }
914 break;
915
916 case BRS_FALSE:
917 // On the FALSE side of NAN < x, we know nothing about x.
918 if (op1.known_isnan ())
919 r.set_varying (type);
920 else
921 build_le (r, type, op1);
922 break;
923
924 default:
925 break;
926 }
927 return true;
928 }
929
930 class foperator_le : public range_operator_float
931 {
932 using range_operator_float::fold_range;
933 using range_operator_float::op1_range;
934 using range_operator_float::op2_range;
935 using range_operator_float::op1_op2_relation;
936 public:
937 bool fold_range (irange &r, tree type,
938 const frange &op1, const frange &op2,
939 relation_trio rel = TRIO_VARYING) const final override;
940 relation_kind op1_op2_relation (const irange &lhs) const final override
941 {
942 return le_op1_op2_relation (lhs);
943 }
944 bool op1_range (frange &r, tree type,
945 const irange &lhs, const frange &op2,
946 relation_trio rel = TRIO_VARYING) const final override;
947 bool op2_range (frange &r, tree type,
948 const irange &lhs, const frange &op1,
949 relation_trio rel = TRIO_VARYING) const final override;
950 } fop_le;
951
952 bool
953 foperator_le::fold_range (irange &r, tree type,
954 const frange &op1, const frange &op2,
955 relation_trio rel) const
956 {
957 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
958 return true;
959
960 if (op1.known_isnan () || op2.known_isnan ())
961 r = range_false (type);
962 else if (!maybe_isnan (op1, op2))
963 {
964 if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
965 r = range_true (type);
966 else if (!real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
967 r = range_false (type);
968 else
969 r = range_true_and_false (type);
970 }
971 else
972 r = range_true_and_false (type);
973 return true;
974 }
975
976 bool
977 foperator_le::op1_range (frange &r,
978 tree type,
979 const irange &lhs,
980 const frange &op2,
981 relation_trio) const
982 {
983 switch (get_bool_state (r, lhs, type))
984 {
985 case BRS_TRUE:
986 // The TRUE side of x <= NAN is unreachable.
987 if (op2.known_isnan ())
988 r.set_undefined ();
989 else if (op2.undefined_p ())
990 return false;
991 else if (build_le (r, type, op2))
992 r.clear_nan ();
993 break;
994
995 case BRS_FALSE:
996 // On the FALSE side of x <= NAN, we know nothing about x.
997 if (op2.known_isnan ())
998 r.set_varying (type);
999 else
1000 build_gt (r, type, op2);
1001 break;
1002
1003 default:
1004 break;
1005 }
1006 return true;
1007 }
1008
1009 bool
1010 foperator_le::op2_range (frange &r,
1011 tree type,
1012 const irange &lhs,
1013 const frange &op1,
1014 relation_trio) const
1015 {
1016 switch (get_bool_state (r, lhs, type))
1017 {
1018 case BRS_TRUE:
1019 // The TRUE side of NAN <= x is unreachable.
1020 if (op1.known_isnan ())
1021 r.set_undefined ();
1022 else if (op1.undefined_p ())
1023 return false;
1024 else if (build_ge (r, type, op1))
1025 r.clear_nan ();
1026 break;
1027
1028 case BRS_FALSE:
1029 // On the FALSE side of NAN <= x, we know nothing about x.
1030 if (op1.known_isnan ())
1031 r.set_varying (type);
1032 else if (op1.undefined_p ())
1033 return false;
1034 else
1035 build_lt (r, type, op1);
1036 break;
1037
1038 default:
1039 break;
1040 }
1041 return true;
1042 }
1043
1044 class foperator_gt : public range_operator_float
1045 {
1046 using range_operator_float::fold_range;
1047 using range_operator_float::op1_range;
1048 using range_operator_float::op2_range;
1049 using range_operator_float::op1_op2_relation;
1050 public:
1051 bool fold_range (irange &r, tree type,
1052 const frange &op1, const frange &op2,
1053 relation_trio = TRIO_VARYING) const final override;
1054 relation_kind op1_op2_relation (const irange &lhs) const final override
1055 {
1056 return gt_op1_op2_relation (lhs);
1057 }
1058 bool op1_range (frange &r, tree type,
1059 const irange &lhs, const frange &op2,
1060 relation_trio = TRIO_VARYING) const final override;
1061 bool op2_range (frange &r, tree type,
1062 const irange &lhs, const frange &op1,
1063 relation_trio = TRIO_VARYING) const final override;
1064 } fop_gt;
1065
1066 bool
1067 foperator_gt::fold_range (irange &r, tree type,
1068 const frange &op1, const frange &op2,
1069 relation_trio rel) const
1070 {
1071 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT))
1072 return true;
1073
1074 if (op1.known_isnan () || op2.known_isnan ())
1075 r = range_false (type);
1076 else if (!maybe_isnan (op1, op2))
1077 {
1078 if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1079 r = range_true (type);
1080 else if (!real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1081 r = range_false (type);
1082 else
1083 r = range_true_and_false (type);
1084 }
1085 else
1086 r = range_true_and_false (type);
1087 return true;
1088 }
1089
1090 bool
1091 foperator_gt::op1_range (frange &r,
1092 tree type,
1093 const irange &lhs,
1094 const frange &op2,
1095 relation_trio) const
1096 {
1097 switch (get_bool_state (r, lhs, type))
1098 {
1099 case BRS_TRUE:
1100 // The TRUE side of x > NAN is unreachable.
1101 if (op2.known_isnan ())
1102 r.set_undefined ();
1103 else if (op2.undefined_p ())
1104 return false;
1105 else if (build_gt (r, type, op2))
1106 {
1107 r.clear_nan ();
1108 // x > y implies x is not -INF.
1109 frange_drop_ninf (r, type);
1110 }
1111 break;
1112
1113 case BRS_FALSE:
1114 // On the FALSE side of x > NAN, we know nothing about x.
1115 if (op2.known_isnan ())
1116 r.set_varying (type);
1117 else if (op2.undefined_p ())
1118 return false;
1119 else
1120 build_le (r, type, op2);
1121 break;
1122
1123 default:
1124 break;
1125 }
1126 return true;
1127 }
1128
1129 bool
1130 foperator_gt::op2_range (frange &r,
1131 tree type,
1132 const irange &lhs,
1133 const frange &op1,
1134 relation_trio) const
1135 {
1136 switch (get_bool_state (r, lhs, type))
1137 {
1138 case BRS_TRUE:
1139 // The TRUE side of NAN > x is unreachable.
1140 if (op1.known_isnan ())
1141 r.set_undefined ();
1142 else if (op1.undefined_p ())
1143 return false;
1144 else if (build_lt (r, type, op1))
1145 {
1146 r.clear_nan ();
1147 // x > y implies y is not +INF.
1148 frange_drop_inf (r, type);
1149 }
1150 break;
1151
1152 case BRS_FALSE:
1153 // On The FALSE side of NAN > x, we know nothing about x.
1154 if (op1.known_isnan ())
1155 r.set_varying (type);
1156 else if (op1.undefined_p ())
1157 return false;
1158 else
1159 build_ge (r, type, op1);
1160 break;
1161
1162 default:
1163 break;
1164 }
1165 return true;
1166 }
1167
1168 class foperator_ge : public range_operator_float
1169 {
1170 using range_operator_float::fold_range;
1171 using range_operator_float::op1_range;
1172 using range_operator_float::op2_range;
1173 using range_operator_float::op1_op2_relation;
1174 public:
1175 bool fold_range (irange &r, tree type,
1176 const frange &op1, const frange &op2,
1177 relation_trio = TRIO_VARYING) const final override;
1178 relation_kind op1_op2_relation (const irange &lhs) const final override
1179 {
1180 return ge_op1_op2_relation (lhs);
1181 }
1182 bool op1_range (frange &r, tree type,
1183 const irange &lhs, const frange &op2,
1184 relation_trio = TRIO_VARYING) const final override;
1185 bool op2_range (frange &r, tree type,
1186 const irange &lhs, const frange &op1,
1187 relation_trio = TRIO_VARYING) const final override;
1188 } fop_ge;
1189
1190 bool
1191 foperator_ge::fold_range (irange &r, tree type,
1192 const frange &op1, const frange &op2,
1193 relation_trio rel) const
1194 {
1195 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
1196 return true;
1197
1198 if (op1.known_isnan () || op2.known_isnan ())
1199 r = range_false (type);
1200 else if (!maybe_isnan (op1, op2))
1201 {
1202 if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1203 r = range_true (type);
1204 else if (!real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1205 r = range_false (type);
1206 else
1207 r = range_true_and_false (type);
1208 }
1209 else
1210 r = range_true_and_false (type);
1211 return true;
1212 }
1213
1214 bool
1215 foperator_ge::op1_range (frange &r,
1216 tree type,
1217 const irange &lhs,
1218 const frange &op2,
1219 relation_trio) const
1220 {
1221 switch (get_bool_state (r, lhs, type))
1222 {
1223 case BRS_TRUE:
1224 // The TRUE side of x >= NAN is unreachable.
1225 if (op2.known_isnan ())
1226 r.set_undefined ();
1227 else if (op2.undefined_p ())
1228 return false;
1229 else if (build_ge (r, type, op2))
1230 r.clear_nan ();
1231 break;
1232
1233 case BRS_FALSE:
1234 // On the FALSE side of x >= NAN, we know nothing about x.
1235 if (op2.known_isnan ())
1236 r.set_varying (type);
1237 else if (op2.undefined_p ())
1238 return false;
1239 else
1240 build_lt (r, type, op2);
1241 break;
1242
1243 default:
1244 break;
1245 }
1246 return true;
1247 }
1248
1249 bool
1250 foperator_ge::op2_range (frange &r, tree type,
1251 const irange &lhs,
1252 const frange &op1,
1253 relation_trio) const
1254 {
1255 switch (get_bool_state (r, lhs, type))
1256 {
1257 case BRS_TRUE:
1258 // The TRUE side of NAN >= x is unreachable.
1259 if (op1.known_isnan ())
1260 r.set_undefined ();
1261 else if (op1.undefined_p ())
1262 return false;
1263 else if (build_le (r, type, op1))
1264 r.clear_nan ();
1265 break;
1266
1267 case BRS_FALSE:
1268 // On the FALSE side of NAN >= x, we know nothing about x.
1269 if (op1.known_isnan ())
1270 r.set_varying (type);
1271 else if (op1.undefined_p ())
1272 return false;
1273 else
1274 build_gt (r, type, op1);
1275 break;
1276
1277 default:
1278 break;
1279 }
1280 return true;
1281 }
1282
1283 // UNORDERED_EXPR comparison.
1284
1285 class foperator_unordered : public range_operator_float
1286 {
1287 using range_operator_float::fold_range;
1288 using range_operator_float::op1_range;
1289 using range_operator_float::op2_range;
1290 public:
1291 bool fold_range (irange &r, tree type,
1292 const frange &op1, const frange &op2,
1293 relation_trio = TRIO_VARYING) const final override;
1294 bool op1_range (frange &r, tree type,
1295 const irange &lhs, const frange &op2,
1296 relation_trio = TRIO_VARYING) const final override;
1297 bool op2_range (frange &r, tree type,
1298 const irange &lhs, const frange &op1,
1299 relation_trio rel = TRIO_VARYING) const final override
1300 {
1301 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1302 }
1303 } fop_unordered;
1304
1305 bool
1306 foperator_unordered::fold_range (irange &r, tree type,
1307 const frange &op1, const frange &op2,
1308 relation_trio) const
1309 {
1310 // UNORDERED is TRUE if either operand is a NAN.
1311 if (op1.known_isnan () || op2.known_isnan ())
1312 r = range_true (type);
1313 // UNORDERED is FALSE if neither operand is a NAN.
1314 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1315 r = range_false (type);
1316 else
1317 r = range_true_and_false (type);
1318 return true;
1319 }
1320
1321 bool
1322 foperator_unordered::op1_range (frange &r, tree type,
1323 const irange &lhs,
1324 const frange &op2,
1325 relation_trio trio) const
1326 {
1327 relation_kind rel = trio.op1_op2 ();
1328 switch (get_bool_state (r, lhs, type))
1329 {
1330 case BRS_TRUE:
1331 // Since at least one operand must be NAN, if one of them is
1332 // not, the other must be.
1333 if (rel == VREL_EQ || !op2.maybe_isnan ())
1334 r.set_nan (type);
1335 else
1336 r.set_varying (type);
1337 break;
1338
1339 case BRS_FALSE:
1340 // A false UNORDERED means both operands are !NAN, so it's
1341 // impossible for op2 to be a NAN.
1342 if (op2.known_isnan ())
1343 r.set_undefined ();
1344 else
1345 {
1346 r.set_varying (type);
1347 r.clear_nan ();
1348 }
1349 break;
1350
1351 default:
1352 break;
1353 }
1354 return true;
1355 }
1356
1357 // ORDERED_EXPR comparison.
1358
1359 class foperator_ordered : public range_operator_float
1360 {
1361 using range_operator_float::fold_range;
1362 using range_operator_float::op1_range;
1363 using range_operator_float::op2_range;
1364 public:
1365 bool fold_range (irange &r, tree type,
1366 const frange &op1, const frange &op2,
1367 relation_trio = TRIO_VARYING) const final override;
1368 bool op1_range (frange &r, tree type,
1369 const irange &lhs, const frange &op2,
1370 relation_trio = TRIO_VARYING) const final override;
1371 bool op2_range (frange &r, tree type,
1372 const irange &lhs, const frange &op1,
1373 relation_trio rel = TRIO_VARYING) const final override
1374 {
1375 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1376 }
1377 } fop_ordered;
1378
1379 bool
1380 foperator_ordered::fold_range (irange &r, tree type,
1381 const frange &op1, const frange &op2,
1382 relation_trio) const
1383 {
1384 if (op1.known_isnan () || op2.known_isnan ())
1385 r = range_false (type);
1386 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1387 r = range_true (type);
1388 else
1389 r = range_true_and_false (type);
1390 return true;
1391 }
1392
1393 bool
1394 foperator_ordered::op1_range (frange &r, tree type,
1395 const irange &lhs,
1396 const frange &op2,
1397 relation_trio trio) const
1398 {
1399 relation_kind rel = trio.op1_op2 ();
1400 switch (get_bool_state (r, lhs, type))
1401 {
1402 case BRS_TRUE:
1403 // The TRUE side of ORDERED means both operands are !NAN, so
1404 // it's impossible for op2 to be a NAN.
1405 if (op2.known_isnan ())
1406 r.set_undefined ();
1407 else
1408 {
1409 r.set_varying (type);
1410 r.clear_nan ();
1411 }
1412 break;
1413
1414 case BRS_FALSE:
1415 // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1416 if (rel == VREL_EQ)
1417 r.set_nan (type);
1418 else
1419 r.set_varying (type);
1420 break;
1421
1422 default:
1423 break;
1424 }
1425 return true;
1426 }
1427
1428 class foperator_negate : public range_operator_float
1429 {
1430 using range_operator_float::fold_range;
1431 using range_operator_float::op1_range;
1432 public:
1433 bool fold_range (frange &r, tree type,
1434 const frange &op1, const frange &op2,
1435 relation_trio = TRIO_VARYING) const final override
1436 {
1437 if (empty_range_varying (r, type, op1, op2))
1438 return true;
1439 if (op1.known_isnan ())
1440 {
1441 bool sign;
1442 if (op1.nan_signbit_p (sign))
1443 r.set_nan (type, !sign);
1444 else
1445 r.set_nan (type);
1446 return true;
1447 }
1448
1449 REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1450 REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1451 lh_lb = real_value_negate (&lh_lb);
1452 lh_ub = real_value_negate (&lh_ub);
1453 r.set (type, lh_ub, lh_lb);
1454 if (op1.maybe_isnan ())
1455 {
1456 bool sign;
1457 if (op1.nan_signbit_p (sign))
1458 r.update_nan (!sign);
1459 else
1460 r.update_nan ();
1461 }
1462 else
1463 r.clear_nan ();
1464 return true;
1465 }
1466 bool op1_range (frange &r, tree type,
1467 const frange &lhs, const frange &op2,
1468 relation_trio rel = TRIO_VARYING) const final override
1469 {
1470 return fold_range (r, type, lhs, op2, rel);
1471 }
1472 } fop_negate;
1473
1474 class foperator_abs : public range_operator_float
1475 {
1476 using range_operator_float::fold_range;
1477 using range_operator_float::op1_range;
1478 public:
1479 bool fold_range (frange &r, tree type,
1480 const frange &op1, const frange &,
1481 relation_trio = TRIO_VARYING) const final override;
1482 bool op1_range (frange &r, tree type,
1483 const frange &lhs, const frange &op2,
1484 relation_trio rel = TRIO_VARYING) const final override;
1485 } fop_abs;
1486
1487 bool
1488 foperator_abs::fold_range (frange &r, tree type,
1489 const frange &op1, const frange &op2,
1490 relation_trio) const
1491 {
1492 if (empty_range_varying (r, type, op1, op2))
1493 return true;
1494 if (op1.known_isnan ())
1495 {
1496 r.set_nan (type, /*sign=*/false);
1497 return true;
1498 }
1499
1500 const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1501 const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1502 // Handle the easy case where everything is positive.
1503 if (real_compare (GE_EXPR, &lh_lb, &dconst0)
1504 && !real_iszero (&lh_lb, /*sign=*/true)
1505 && !op1.maybe_isnan (/*sign=*/true))
1506 {
1507 r = op1;
1508 return true;
1509 }
1510
1511 REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
1512 REAL_VALUE_TYPE max = real_value_abs (&lh_ub);
1513 // If the range contains zero then we know that the minimum value in the
1514 // range will be zero.
1515 if (real_compare (LE_EXPR, &lh_lb, &dconst0)
1516 && real_compare (GE_EXPR, &lh_ub, &dconst0))
1517 {
1518 if (real_compare (GT_EXPR, &min, &max))
1519 max = min;
1520 min = dconst0;
1521 }
1522 else
1523 {
1524 // If the range was reversed, swap MIN and MAX.
1525 if (real_compare (GT_EXPR, &min, &max))
1526 std::swap (min, max);
1527 }
1528
1529 r.set (type, min, max);
1530 if (op1.maybe_isnan ())
1531 r.update_nan (/*sign=*/false);
1532 else
1533 r.clear_nan ();
1534 return true;
1535 }
1536
1537 bool
1538 foperator_abs::op1_range (frange &r, tree type,
1539 const frange &lhs, const frange &op2,
1540 relation_trio) const
1541 {
1542 if (empty_range_varying (r, type, lhs, op2))
1543 return true;
1544 if (lhs.known_isnan ())
1545 {
1546 r.set_nan (type);
1547 return true;
1548 }
1549
1550 // Start with the positives because negatives are an impossible result.
1551 frange positives (type, dconst0, frange_val_max (type));
1552 positives.update_nan (/*sign=*/false);
1553 positives.intersect (lhs);
1554 r = positives;
1555 // Add -NAN if relevant.
1556 if (r.maybe_isnan ())
1557 {
1558 frange neg_nan;
1559 neg_nan.set_nan (type, true);
1560 r.union_ (neg_nan);
1561 }
1562 if (r.known_isnan () || r.undefined_p ())
1563 return true;
1564 // Then add the negative of each pair:
1565 // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1566 frange negatives (type, real_value_negate (&positives.upper_bound ()),
1567 real_value_negate (&positives.lower_bound ()));
1568 negatives.clear_nan ();
1569 r.union_ (negatives);
1570 return true;
1571 }
1572
1573 class foperator_unordered_lt : public range_operator_float
1574 {
1575 using range_operator_float::fold_range;
1576 using range_operator_float::op1_range;
1577 using range_operator_float::op2_range;
1578 public:
1579 bool fold_range (irange &r, tree type,
1580 const frange &op1, const frange &op2,
1581 relation_trio rel = TRIO_VARYING) const final override
1582 {
1583 if (op1.known_isnan () || op2.known_isnan ())
1584 {
1585 r = range_true (type);
1586 return true;
1587 }
1588 if (!fop_lt.fold_range (r, type, op1, op2, rel))
1589 return false;
1590 // The result is the same as the ordered version when the
1591 // comparison is true or when the operands cannot be NANs.
1592 if (!maybe_isnan (op1, op2) || r == range_true (type))
1593 return true;
1594 else
1595 {
1596 r = range_true_and_false (type);
1597 return true;
1598 }
1599 }
1600 bool op1_range (frange &r, tree type,
1601 const irange &lhs,
1602 const frange &op2,
1603 relation_trio trio) const final override;
1604 bool op2_range (frange &r, tree type,
1605 const irange &lhs,
1606 const frange &op1,
1607 relation_trio trio) const final override;
1608 } fop_unordered_lt;
1609
1610 bool
1611 foperator_unordered_lt::op1_range (frange &r, tree type,
1612 const irange &lhs,
1613 const frange &op2,
1614 relation_trio) const
1615 {
1616 switch (get_bool_state (r, lhs, type))
1617 {
1618 case BRS_TRUE:
1619 if (op2.known_isnan ())
1620 r.set_varying (type);
1621 else if (op2.undefined_p ())
1622 return false;
1623 else
1624 build_lt (r, type, op2);
1625 break;
1626
1627 case BRS_FALSE:
1628 // A false UNORDERED_LT means both operands are !NAN, so it's
1629 // impossible for op2 to be a NAN.
1630 if (op2.known_isnan ())
1631 r.set_undefined ();
1632 else if (op2.undefined_p ())
1633 return false;
1634 else if (build_ge (r, type, op2))
1635 r.clear_nan ();
1636 break;
1637
1638 default:
1639 break;
1640 }
1641 return true;
1642 }
1643
1644 bool
1645 foperator_unordered_lt::op2_range (frange &r, tree type,
1646 const irange &lhs,
1647 const frange &op1,
1648 relation_trio) const
1649 {
1650 switch (get_bool_state (r, lhs, type))
1651 {
1652 case BRS_TRUE:
1653 if (op1.known_isnan ())
1654 r.set_varying (type);
1655 else if (op1.undefined_p ())
1656 return false;
1657 else
1658 build_gt (r, type, op1);
1659 break;
1660
1661 case BRS_FALSE:
1662 // A false UNORDERED_LT means both operands are !NAN, so it's
1663 // impossible for op1 to be a NAN.
1664 if (op1.known_isnan ())
1665 r.set_undefined ();
1666 else if (op1.undefined_p ())
1667 return false;
1668 else if (build_le (r, type, op1))
1669 r.clear_nan ();
1670 break;
1671
1672 default:
1673 break;
1674 }
1675 return true;
1676 }
1677
1678 class foperator_unordered_le : public range_operator_float
1679 {
1680 using range_operator_float::fold_range;
1681 using range_operator_float::op1_range;
1682 using range_operator_float::op2_range;
1683 public:
1684 bool fold_range (irange &r, tree type,
1685 const frange &op1, const frange &op2,
1686 relation_trio rel = TRIO_VARYING) const final override
1687 {
1688 if (op1.known_isnan () || op2.known_isnan ())
1689 {
1690 r = range_true (type);
1691 return true;
1692 }
1693 if (!fop_le.fold_range (r, type, op1, op2, rel))
1694 return false;
1695 // The result is the same as the ordered version when the
1696 // comparison is true or when the operands cannot be NANs.
1697 if (!maybe_isnan (op1, op2) || r == range_true (type))
1698 return true;
1699 else
1700 {
1701 r = range_true_and_false (type);
1702 return true;
1703 }
1704 }
1705 bool op1_range (frange &r, tree type,
1706 const irange &lhs, const frange &op2,
1707 relation_trio = TRIO_VARYING) const final override;
1708 bool op2_range (frange &r, tree type,
1709 const irange &lhs, const frange &op1,
1710 relation_trio = TRIO_VARYING) const final override;
1711 } fop_unordered_le;
1712
1713 bool
1714 foperator_unordered_le::op1_range (frange &r, tree type,
1715 const irange &lhs, const frange &op2,
1716 relation_trio) const
1717 {
1718 switch (get_bool_state (r, lhs, type))
1719 {
1720 case BRS_TRUE:
1721 if (op2.known_isnan ())
1722 r.set_varying (type);
1723 else if (op2.undefined_p ())
1724 return false;
1725 else
1726 build_le (r, type, op2);
1727 break;
1728
1729 case BRS_FALSE:
1730 // A false UNORDERED_LE means both operands are !NAN, so it's
1731 // impossible for op2 to be a NAN.
1732 if (op2.known_isnan ())
1733 r.set_undefined ();
1734 else if (build_gt (r, type, op2))
1735 r.clear_nan ();
1736 break;
1737
1738 default:
1739 break;
1740 }
1741 return true;
1742 }
1743
1744 bool
1745 foperator_unordered_le::op2_range (frange &r,
1746 tree type,
1747 const irange &lhs,
1748 const frange &op1,
1749 relation_trio) const
1750 {
1751 switch (get_bool_state (r, lhs, type))
1752 {
1753 case BRS_TRUE:
1754 if (op1.known_isnan ())
1755 r.set_varying (type);
1756 else if (op1.undefined_p ())
1757 return false;
1758 else
1759 build_ge (r, type, op1);
1760 break;
1761
1762 case BRS_FALSE:
1763 // A false UNORDERED_LE means both operands are !NAN, so it's
1764 // impossible for op1 to be a NAN.
1765 if (op1.known_isnan ())
1766 r.set_undefined ();
1767 else if (op1.undefined_p ())
1768 return false;
1769 else if (build_lt (r, type, op1))
1770 r.clear_nan ();
1771 break;
1772
1773 default:
1774 break;
1775 }
1776 return true;
1777 }
1778
1779 class foperator_unordered_gt : public range_operator_float
1780 {
1781 using range_operator_float::fold_range;
1782 using range_operator_float::op1_range;
1783 using range_operator_float::op2_range;
1784 public:
1785 bool fold_range (irange &r, tree type,
1786 const frange &op1, const frange &op2,
1787 relation_trio rel = TRIO_VARYING) const final override
1788 {
1789 if (op1.known_isnan () || op2.known_isnan ())
1790 {
1791 r = range_true (type);
1792 return true;
1793 }
1794 if (!fop_gt.fold_range (r, type, op1, op2, rel))
1795 return false;
1796 // The result is the same as the ordered version when the
1797 // comparison is true or when the operands cannot be NANs.
1798 if (!maybe_isnan (op1, op2) || r == range_true (type))
1799 return true;
1800 else
1801 {
1802 r = range_true_and_false (type);
1803 return true;
1804 }
1805 }
1806 bool op1_range (frange &r, tree type,
1807 const irange &lhs, const frange &op2,
1808 relation_trio = TRIO_VARYING) const final override;
1809 bool op2_range (frange &r, tree type,
1810 const irange &lhs, const frange &op1,
1811 relation_trio = TRIO_VARYING) const final override;
1812 } fop_unordered_gt;
1813
1814 bool
1815 foperator_unordered_gt::op1_range (frange &r,
1816 tree type,
1817 const irange &lhs,
1818 const frange &op2,
1819 relation_trio) const
1820 {
1821 switch (get_bool_state (r, lhs, type))
1822 {
1823 case BRS_TRUE:
1824 if (op2.known_isnan ())
1825 r.set_varying (type);
1826 else if (op2.undefined_p ())
1827 return false;
1828 else
1829 build_gt (r, type, op2);
1830 break;
1831
1832 case BRS_FALSE:
1833 // A false UNORDERED_GT means both operands are !NAN, so it's
1834 // impossible for op2 to be a NAN.
1835 if (op2.known_isnan ())
1836 r.set_undefined ();
1837 else if (op2.undefined_p ())
1838 return false;
1839 else if (build_le (r, type, op2))
1840 r.clear_nan ();
1841 break;
1842
1843 default:
1844 break;
1845 }
1846 return true;
1847 }
1848
1849 bool
1850 foperator_unordered_gt::op2_range (frange &r,
1851 tree type,
1852 const irange &lhs,
1853 const frange &op1,
1854 relation_trio) const
1855 {
1856 switch (get_bool_state (r, lhs, type))
1857 {
1858 case BRS_TRUE:
1859 if (op1.known_isnan ())
1860 r.set_varying (type);
1861 else if (op1.undefined_p ())
1862 return false;
1863 else
1864 build_lt (r, type, op1);
1865 break;
1866
1867 case BRS_FALSE:
1868 // A false UNORDERED_GT means both operands are !NAN, so it's
1869 // impossible for op1 to be a NAN.
1870 if (op1.known_isnan ())
1871 r.set_undefined ();
1872 else if (op1.undefined_p ())
1873 return false;
1874 else if (build_ge (r, type, op1))
1875 r.clear_nan ();
1876 break;
1877
1878 default:
1879 break;
1880 }
1881 return true;
1882 }
1883
1884 class foperator_unordered_ge : public range_operator_float
1885 {
1886 using range_operator_float::fold_range;
1887 using range_operator_float::op1_range;
1888 using range_operator_float::op2_range;
1889 public:
1890 bool fold_range (irange &r, tree type,
1891 const frange &op1, const frange &op2,
1892 relation_trio rel = TRIO_VARYING) const final override
1893 {
1894 if (op1.known_isnan () || op2.known_isnan ())
1895 {
1896 r = range_true (type);
1897 return true;
1898 }
1899 if (!fop_ge.fold_range (r, type, op1, op2, rel))
1900 return false;
1901 // The result is the same as the ordered version when the
1902 // comparison is true or when the operands cannot be NANs.
1903 if (!maybe_isnan (op1, op2) || r == range_true (type))
1904 return true;
1905 else
1906 {
1907 r = range_true_and_false (type);
1908 return true;
1909 }
1910 }
1911 bool op1_range (frange &r, tree type,
1912 const irange &lhs, const frange &op2,
1913 relation_trio = TRIO_VARYING) const final override;
1914 bool op2_range (frange &r, tree type,
1915 const irange &lhs, const frange &op1,
1916 relation_trio = TRIO_VARYING) const final override;
1917 } fop_unordered_ge;
1918
1919 bool
1920 foperator_unordered_ge::op1_range (frange &r,
1921 tree type,
1922 const irange &lhs,
1923 const frange &op2,
1924 relation_trio) const
1925 {
1926 switch (get_bool_state (r, lhs, type))
1927 {
1928 case BRS_TRUE:
1929 if (op2.known_isnan ())
1930 r.set_varying (type);
1931 else if (op2.undefined_p ())
1932 return false;
1933 else
1934 build_ge (r, type, op2);
1935 break;
1936
1937 case BRS_FALSE:
1938 // A false UNORDERED_GE means both operands are !NAN, so it's
1939 // impossible for op2 to be a NAN.
1940 if (op2.known_isnan ())
1941 r.set_undefined ();
1942 else if (op2.undefined_p ())
1943 return false;
1944 else if (build_lt (r, type, op2))
1945 r.clear_nan ();
1946 break;
1947
1948 default:
1949 break;
1950 }
1951 return true;
1952 }
1953
1954 bool
1955 foperator_unordered_ge::op2_range (frange &r, tree type,
1956 const irange &lhs,
1957 const frange &op1,
1958 relation_trio) const
1959 {
1960 switch (get_bool_state (r, lhs, type))
1961 {
1962 case BRS_TRUE:
1963 if (op1.known_isnan ())
1964 r.set_varying (type);
1965 else if (op1.undefined_p ())
1966 return false;
1967 else
1968 build_le (r, type, op1);
1969 break;
1970
1971 case BRS_FALSE:
1972 // A false UNORDERED_GE means both operands are !NAN, so it's
1973 // impossible for op1 to be a NAN.
1974 if (op1.known_isnan ())
1975 r.set_undefined ();
1976 else if (op1.undefined_p ())
1977 return false;
1978 else if (build_gt (r, type, op1))
1979 r.clear_nan ();
1980 break;
1981
1982 default:
1983 break;
1984 }
1985 return true;
1986 }
1987
1988 class foperator_unordered_equal : public range_operator_float
1989 {
1990 using range_operator_float::fold_range;
1991 using range_operator_float::op1_range;
1992 using range_operator_float::op2_range;
1993 public:
1994 bool fold_range (irange &r, tree type,
1995 const frange &op1, const frange &op2,
1996 relation_trio rel = TRIO_VARYING) const final override
1997 {
1998 if (op1.known_isnan () || op2.known_isnan ())
1999 {
2000 r = range_true (type);
2001 return true;
2002 }
2003 if (!fop_equal.fold_range (r, type, op1, op2, rel))
2004 return false;
2005 // The result is the same as the ordered version when the
2006 // comparison is true or when the operands cannot be NANs.
2007 if (!maybe_isnan (op1, op2) || r == range_true (type))
2008 return true;
2009 else
2010 {
2011 r = range_true_and_false (type);
2012 return true;
2013 }
2014 }
2015 bool op1_range (frange &r, tree type,
2016 const irange &lhs, const frange &op2,
2017 relation_trio = TRIO_VARYING) const final override;
2018 bool op2_range (frange &r, tree type,
2019 const irange &lhs, const frange &op1,
2020 relation_trio rel = TRIO_VARYING) const final override
2021 {
2022 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2023 }
2024 } fop_unordered_equal;
2025
2026 bool
2027 foperator_unordered_equal::op1_range (frange &r, tree type,
2028 const irange &lhs,
2029 const frange &op2,
2030 relation_trio) const
2031 {
2032 switch (get_bool_state (r, lhs, type))
2033 {
2034 case BRS_TRUE:
2035 // If it's true, the result is the same as OP2 plus a NAN.
2036 r = op2;
2037 // Add both zeros if there's the possibility of zero equality.
2038 frange_add_zeros (r, type);
2039 // Add the posibility of a NAN.
2040 r.update_nan ();
2041 break;
2042
2043 case BRS_FALSE:
2044 // A false UNORDERED_EQ means both operands are !NAN, so it's
2045 // impossible for op2 to be a NAN.
2046 if (op2.known_isnan ())
2047 r.set_undefined ();
2048 else
2049 {
2050 // The false side indictates !NAN and not equal. We can at least
2051 // represent !NAN.
2052 r.set_varying (type);
2053 r.clear_nan ();
2054 }
2055 break;
2056
2057 default:
2058 break;
2059 }
2060 return true;
2061 }
2062
2063 // Final tweaks for float binary op op1_range/op2_range.
2064 // Return TRUE if the operation is performed and a valid range is available.
2065
2066 static bool
2067 float_binary_op_range_finish (bool ret, frange &r, tree type,
2068 const frange &lhs, bool div_op2 = false)
2069 {
2070 if (!ret)
2071 return false;
2072
2073 // If we get a known NAN from reverse op, it means either that
2074 // the other operand was known NAN (in that case we know nothing),
2075 // or the reverse operation introduced a known NAN.
2076 // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
2077 // 0 / 0 is known NAN. Just punt in that case.
2078 // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
2079 // Or if lhs is a known NAN, we also don't know anything.
2080 if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
2081 {
2082 r.set_varying (type);
2083 return true;
2084 }
2085
2086 // If lhs isn't NAN, then neither operand could be NAN,
2087 // even if the reverse operation does introduce a maybe_nan.
2088 if (!lhs.maybe_isnan ())
2089 {
2090 r.clear_nan ();
2091 if (div_op2
2092 ? !(real_compare (LE_EXPR, &lhs.lower_bound (), &dconst0)
2093 && real_compare (GE_EXPR, &lhs.upper_bound (), &dconst0))
2094 : !(real_isinf (&lhs.lower_bound ())
2095 || real_isinf (&lhs.upper_bound ())))
2096 // For reverse + or - or * or op1 of /, if result is finite, then
2097 // r must be finite too, as X + INF or X - INF or X * INF or
2098 // INF / X is always +-INF or NAN. For op2 of /, if result is
2099 // non-zero and not NAN, r must be finite, as X / INF is always
2100 // 0 or NAN.
2101 frange_drop_infs (r, type);
2102 }
2103 // If lhs is a maybe or known NAN, the operand could be
2104 // NAN.
2105 else
2106 r.update_nan ();
2107 return true;
2108 }
2109
2110 // True if [lb, ub] is [+-0, +-0].
2111 static bool
2112 zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2113 {
2114 return real_iszero (&lb) && real_iszero (&ub);
2115 }
2116
2117 // True if +0 or -0 is in [lb, ub] range.
2118 static bool
2119 contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2120 {
2121 return (real_compare (LE_EXPR, &lb, &dconst0)
2122 && real_compare (GE_EXPR, &ub, &dconst0));
2123 }
2124
2125 // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
2126 static bool
2127 singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2128 {
2129 return real_isinf (&lb) && real_isinf (&ub, real_isneg (&lb));
2130 }
2131
2132 // Return -1 if binary op result must have sign bit set,
2133 // 1 if binary op result must have sign bit clear,
2134 // 0 otherwise.
2135 // Sign bit of binary op result is exclusive or of the
2136 // operand's sign bits.
2137 static int
2138 signbit_known_p (const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
2139 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub)
2140 {
2141 if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
2142 && real_isneg (&rh_lb) == real_isneg (&rh_ub))
2143 {
2144 if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
2145 return 1;
2146 else
2147 return -1;
2148 }
2149 return 0;
2150 }
2151
2152 // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
2153 // signbit_known.
2154 static void
2155 zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2156 {
2157 ub = lb = dconst0;
2158 if (signbit_known <= 0)
2159 lb = real_value_negate (&dconst0);
2160 if (signbit_known < 0)
2161 ub = lb;
2162 }
2163
2164 // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
2165 // signbit_known.
2166 static void
2167 inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2168 {
2169 if (signbit_known > 0)
2170 ub = lb = dconstinf;
2171 else if (signbit_known < 0)
2172 ub = lb = dconstninf;
2173 else
2174 {
2175 lb = dconstninf;
2176 ub = dconstinf;
2177 }
2178 }
2179
2180 // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
2181 // signbit_known.
2182 static void
2183 zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2184 {
2185 if (signbit_known > 0)
2186 {
2187 lb = dconst0;
2188 ub = dconstinf;
2189 }
2190 else if (signbit_known < 0)
2191 {
2192 lb = dconstninf;
2193 ub = real_value_negate (&dconst0);
2194 }
2195 else
2196 {
2197 lb = dconstninf;
2198 ub = dconstinf;
2199 }
2200 }
2201
2202 /* Extend the LHS range by 1ulp in each direction. For op1_range
2203 or op2_range of binary operations just computing the inverse
2204 operation on ranges isn't sufficient. Consider e.g.
2205 [1., 1.] = op1 + [1., 1.]. op1's range is not [0., 0.], but
2206 [-0x1.0p-54, 0x1.0p-53] (when not -frounding-math), any value for
2207 which adding 1. to it results in 1. after rounding to nearest.
2208 So, for op1_range/op2_range extend the lhs range by 1ulp (or 0.5ulp)
2209 in each direction. See PR109008 for more details. */
2210
2211 static frange
2212 float_widen_lhs_range (tree type, const frange &lhs)
2213 {
2214 frange ret = lhs;
2215 if (lhs.known_isnan ())
2216 return ret;
2217 REAL_VALUE_TYPE lb = lhs.lower_bound ();
2218 REAL_VALUE_TYPE ub = lhs.upper_bound ();
2219 if (real_isfinite (&lb))
2220 {
2221 frange_nextafter (TYPE_MODE (type), lb, dconstninf);
2222 if (real_isinf (&lb))
2223 {
2224 /* For -DBL_MAX, instead of -Inf use
2225 nexttoward (-DBL_MAX, -LDBL_MAX) in a hypothetical
2226 wider type with the same mantissa precision but larger
2227 exponent range; it is outside of range of double values,
2228 but makes it clear it is just one ulp larger rather than
2229 infinite amount larger. */
2230 lb = dconstm1;
2231 SET_REAL_EXP (&lb, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
2232 }
2233 if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
2234 {
2235 /* If not -frounding-math nor IBM double double, actually widen
2236 just by 0.5ulp rather than 1ulp. */
2237 REAL_VALUE_TYPE tem;
2238 real_arithmetic (&tem, PLUS_EXPR, &lhs.lower_bound (), &lb);
2239 real_arithmetic (&lb, RDIV_EXPR, &tem, &dconst2);
2240 }
2241 }
2242 if (real_isfinite (&ub))
2243 {
2244 frange_nextafter (TYPE_MODE (type), ub, dconstinf);
2245 if (real_isinf (&ub))
2246 {
2247 /* For DBL_MAX similarly. */
2248 ub = dconst1;
2249 SET_REAL_EXP (&ub, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
2250 }
2251 if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
2252 {
2253 /* If not -frounding-math nor IBM double double, actually widen
2254 just by 0.5ulp rather than 1ulp. */
2255 REAL_VALUE_TYPE tem;
2256 real_arithmetic (&tem, PLUS_EXPR, &lhs.upper_bound (), &ub);
2257 real_arithmetic (&ub, RDIV_EXPR, &tem, &dconst2);
2258 }
2259 }
2260 /* Temporarily disable -ffinite-math-only, so that frange::set doesn't
2261 reduce the range back to real_min_representable (type) as lower bound
2262 or real_max_representable (type) as upper bound. */
2263 bool save_flag_finite_math_only = flag_finite_math_only;
2264 flag_finite_math_only = false;
2265 ret.set (type, lb, ub);
2266 if (lhs.kind () != VR_VARYING)
2267 {
2268 ret.clear_nan ();
2269 ret.union_ (lhs);
2270 }
2271 flag_finite_math_only = save_flag_finite_math_only;
2272 return ret;
2273 }
2274
2275 class foperator_plus : public range_operator_float
2276 {
2277 using range_operator_float::op1_range;
2278 using range_operator_float::op2_range;
2279 public:
2280 virtual bool op1_range (frange &r, tree type,
2281 const frange &lhs,
2282 const frange &op2,
2283 relation_trio = TRIO_VARYING) const final override
2284 {
2285 if (lhs.undefined_p ())
2286 return false;
2287 range_op_handler minus (MINUS_EXPR, type);
2288 if (!minus)
2289 return false;
2290 frange wlhs = float_widen_lhs_range (type, lhs);
2291 return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
2292 r, type, wlhs);
2293 }
2294 virtual bool op2_range (frange &r, tree type,
2295 const frange &lhs,
2296 const frange &op1,
2297 relation_trio = TRIO_VARYING) const final override
2298 {
2299 return op1_range (r, type, lhs, op1);
2300 }
2301 private:
2302 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2303 tree type,
2304 const REAL_VALUE_TYPE &lh_lb,
2305 const REAL_VALUE_TYPE &lh_ub,
2306 const REAL_VALUE_TYPE &rh_lb,
2307 const REAL_VALUE_TYPE &rh_ub,
2308 relation_kind) const final override
2309 {
2310 frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
2311 frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
2312
2313 // [-INF] + [+INF] = NAN
2314 if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
2315 maybe_nan = true;
2316 // [+INF] + [-INF] = NAN
2317 else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
2318 maybe_nan = true;
2319 else
2320 maybe_nan = false;
2321 }
2322 } fop_plus;
2323
2324
2325 class foperator_minus : public range_operator_float
2326 {
2327 using range_operator_float::op1_range;
2328 using range_operator_float::op2_range;
2329 public:
2330 virtual bool op1_range (frange &r, tree type,
2331 const frange &lhs,
2332 const frange &op2,
2333 relation_trio = TRIO_VARYING) const final override
2334 {
2335 if (lhs.undefined_p ())
2336 return false;
2337 frange wlhs = float_widen_lhs_range (type, lhs);
2338 return float_binary_op_range_finish (fop_plus.fold_range (r, type, wlhs,
2339 op2),
2340 r, type, wlhs);
2341 }
2342 virtual bool op2_range (frange &r, tree type,
2343 const frange &lhs,
2344 const frange &op1,
2345 relation_trio = TRIO_VARYING) const final override
2346 {
2347 if (lhs.undefined_p ())
2348 return false;
2349 frange wlhs = float_widen_lhs_range (type, lhs);
2350 return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
2351 r, type, wlhs);
2352 }
2353 private:
2354 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2355 tree type,
2356 const REAL_VALUE_TYPE &lh_lb,
2357 const REAL_VALUE_TYPE &lh_ub,
2358 const REAL_VALUE_TYPE &rh_lb,
2359 const REAL_VALUE_TYPE &rh_ub,
2360 relation_kind) const final override
2361 {
2362 frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
2363 frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
2364
2365 // [+INF] - [+INF] = NAN
2366 if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
2367 maybe_nan = true;
2368 // [-INF] - [-INF] = NAN
2369 else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
2370 maybe_nan = true;
2371 else
2372 maybe_nan = false;
2373 }
2374 } fop_minus;
2375
2376
2377 class foperator_mult_div_base : public range_operator_float
2378 {
2379 protected:
2380 // Given CP[0] to CP[3] floating point values rounded to -INF,
2381 // set LB to the smallest of them (treating -0 as smaller to +0).
2382 // Given CP[4] to CP[7] floating point values rounded to +INF,
2383 // set UB to the largest of them (treating -0 as smaller to +0).
2384 static void find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
2385 const REAL_VALUE_TYPE (&cp)[8])
2386 {
2387 lb = cp[0];
2388 ub = cp[4];
2389 for (int i = 1; i < 4; ++i)
2390 {
2391 if (real_less (&cp[i], &lb)
2392 || (real_iszero (&lb) && real_isnegzero (&cp[i])))
2393 lb = cp[i];
2394 if (real_less (&ub, &cp[i + 4])
2395 || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
2396 ub = cp[i + 4];
2397 }
2398 }
2399 };
2400
2401
2402 class foperator_mult : public foperator_mult_div_base
2403 {
2404 using range_operator_float::op1_range;
2405 using range_operator_float::op2_range;
2406 public:
2407 virtual bool op1_range (frange &r, tree type,
2408 const frange &lhs,
2409 const frange &op2,
2410 relation_trio = TRIO_VARYING) const final override
2411 {
2412 if (lhs.undefined_p ())
2413 return false;
2414 range_op_handler rdiv (RDIV_EXPR, type);
2415 if (!rdiv)
2416 return false;
2417 frange wlhs = float_widen_lhs_range (type, lhs);
2418 bool ret = rdiv.fold_range (r, type, wlhs, op2);
2419 if (ret == false)
2420 return false;
2421 if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2422 return float_binary_op_range_finish (ret, r, type, wlhs);
2423 const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2424 const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2425 const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2426 const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2427 if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
2428 || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2429 && (real_isinf (&op2_lb) || real_isinf (&op2_ub))))
2430 {
2431 // If both lhs and op2 could be zeros or both could be infinities,
2432 // we don't know anything about op1 except maybe for the sign
2433 // and perhaps if it can be NAN or not.
2434 REAL_VALUE_TYPE lb, ub;
2435 int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2436 zero_to_inf_range (lb, ub, signbit_known);
2437 r.set (type, lb, ub);
2438 }
2439 // Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
2440 // or if lhs must be zero and op2 doesn't include zero, it would be
2441 // UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
2442 // range. Those are supersets of UNDEFINED, so let's keep that way.
2443 return float_binary_op_range_finish (ret, r, type, wlhs);
2444 }
2445 virtual bool op2_range (frange &r, tree type,
2446 const frange &lhs,
2447 const frange &op1,
2448 relation_trio = TRIO_VARYING) const final override
2449 {
2450 return op1_range (r, type, lhs, op1);
2451 }
2452 private:
2453 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2454 tree type,
2455 const REAL_VALUE_TYPE &lh_lb,
2456 const REAL_VALUE_TYPE &lh_ub,
2457 const REAL_VALUE_TYPE &rh_lb,
2458 const REAL_VALUE_TYPE &rh_ub,
2459 relation_kind kind) const final override
2460 {
2461 bool is_square
2462 = (kind == VREL_EQ
2463 && real_equal (&lh_lb, &rh_lb)
2464 && real_equal (&lh_ub, &rh_ub)
2465 && real_isneg (&lh_lb) == real_isneg (&rh_lb)
2466 && real_isneg (&lh_ub) == real_isneg (&rh_ub));
2467
2468 maybe_nan = false;
2469 // x * x never produces a new NAN and we only multiply the same
2470 // values, so the 0 * INF problematic cases never appear there.
2471 if (!is_square)
2472 {
2473 // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2474 if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
2475 || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
2476 {
2477 real_nan (&lb, "", 0, TYPE_MODE (type));
2478 ub = lb;
2479 maybe_nan = true;
2480 return;
2481 }
2482
2483 // Otherwise, if one range includes zero and the other ends with +-INF,
2484 // it is a maybe NAN.
2485 if ((contains_zero_p (lh_lb, lh_ub)
2486 && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2487 || (contains_zero_p (rh_lb, rh_ub)
2488 && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
2489 {
2490 maybe_nan = true;
2491
2492 int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2493
2494 // If one of the ranges that includes INF is singleton
2495 // and the other range includes zero, the resulting
2496 // range is INF and NAN, because the 0 * INF boundary
2497 // case will be NAN, but already nextafter (0, 1) * INF
2498 // is INF.
2499 if (singleton_inf_p (lh_lb, lh_ub)
2500 || singleton_inf_p (rh_lb, rh_ub))
2501 return inf_range (lb, ub, signbit_known);
2502
2503 // If one of the multiplicands must be zero, the resulting
2504 // range is +-0 and NAN.
2505 if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
2506 return zero_range (lb, ub, signbit_known);
2507
2508 // Otherwise one of the multiplicands could be
2509 // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
2510 // or similarly with different signs. 0.0 * DBL_MAX
2511 // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
2512 // so if the signs are always the same or always different,
2513 // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
2514 return zero_to_inf_range (lb, ub, signbit_known);
2515 }
2516 }
2517
2518 REAL_VALUE_TYPE cp[8];
2519 // Do a cross-product. At this point none of the multiplications
2520 // should produce a NAN.
2521 frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2522 frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2523 if (is_square)
2524 {
2525 // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
2526 // as maximum and -0.0 as minimum if 0.0 is in the range,
2527 // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
2528 // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
2529 // x and y are bitwise equal, just that they compare equal.
2530 if (contains_zero_p (lh_lb, lh_ub))
2531 {
2532 if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
2533 cp[1] = dconst0;
2534 else
2535 cp[1] = real_value_negate (&dconst0);
2536 }
2537 else
2538 cp[1] = cp[0];
2539 cp[2] = cp[0];
2540 cp[5] = cp[4];
2541 cp[6] = cp[4];
2542 }
2543 else
2544 {
2545 frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2546 frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2547 frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2548 frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2549 }
2550 frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2551 frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2552
2553 find_range (lb, ub, cp);
2554 }
2555 } fop_mult;
2556
2557
2558 class foperator_div : public foperator_mult_div_base
2559 {
2560 using range_operator_float::op1_range;
2561 using range_operator_float::op2_range;
2562 public:
2563 virtual bool op1_range (frange &r, tree type,
2564 const frange &lhs,
2565 const frange &op2,
2566 relation_trio = TRIO_VARYING) const final override
2567 {
2568 if (lhs.undefined_p ())
2569 return false;
2570 frange wlhs = float_widen_lhs_range (type, lhs);
2571 bool ret = fop_mult.fold_range (r, type, wlhs, op2);
2572 if (!ret)
2573 return ret;
2574 if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2575 return float_binary_op_range_finish (ret, r, type, wlhs);
2576 const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2577 const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2578 const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2579 const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2580 if ((contains_zero_p (lhs_lb, lhs_ub)
2581 && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
2582 || ((contains_zero_p (op2_lb, op2_ub))
2583 && (real_isinf (&lhs_lb) || real_isinf (&lhs_ub))))
2584 {
2585 // If both lhs could be zero and op2 infinity or vice versa,
2586 // we don't know anything about op1 except maybe for the sign
2587 // and perhaps if it can be NAN or not.
2588 REAL_VALUE_TYPE lb, ub;
2589 int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2590 zero_to_inf_range (lb, ub, signbit_known);
2591 r.set (type, lb, ub);
2592 }
2593 return float_binary_op_range_finish (ret, r, type, wlhs);
2594 }
2595 virtual bool op2_range (frange &r, tree type,
2596 const frange &lhs,
2597 const frange &op1,
2598 relation_trio = TRIO_VARYING) const final override
2599 {
2600 if (lhs.undefined_p ())
2601 return false;
2602 frange wlhs = float_widen_lhs_range (type, lhs);
2603 bool ret = fold_range (r, type, op1, wlhs);
2604 if (!ret)
2605 return ret;
2606 if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
2607 return float_binary_op_range_finish (ret, r, type, wlhs, true);
2608 const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2609 const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2610 const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
2611 const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
2612 if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
2613 || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2614 && (real_isinf (&op1_lb) || real_isinf (&op1_ub))))
2615 {
2616 // If both lhs and op1 could be zeros or both could be infinities,
2617 // we don't know anything about op2 except maybe for the sign
2618 // and perhaps if it can be NAN or not.
2619 REAL_VALUE_TYPE lb, ub;
2620 int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
2621 zero_to_inf_range (lb, ub, signbit_known);
2622 r.set (type, lb, ub);
2623 }
2624 return float_binary_op_range_finish (ret, r, type, wlhs, true);
2625 }
2626 private:
2627 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2628 tree type,
2629 const REAL_VALUE_TYPE &lh_lb,
2630 const REAL_VALUE_TYPE &lh_ub,
2631 const REAL_VALUE_TYPE &rh_lb,
2632 const REAL_VALUE_TYPE &rh_ub,
2633 relation_kind) const final override
2634 {
2635 // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
2636 if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
2637 || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
2638 {
2639 real_nan (&lb, "", 0, TYPE_MODE (type));
2640 ub = lb;
2641 maybe_nan = true;
2642 return;
2643 }
2644
2645 // If +-0.0 is in both ranges, it is a maybe NAN.
2646 if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
2647 maybe_nan = true;
2648 // If +-INF is in both ranges, it is a maybe NAN.
2649 else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
2650 && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2651 maybe_nan = true;
2652 else
2653 maybe_nan = false;
2654
2655 int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2656
2657 // If dividend must be zero, the range is just +-0
2658 // (including if the divisor is +-INF).
2659 // If divisor must be +-INF, the range is just +-0
2660 // (including if the dividend is zero).
2661 if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
2662 return zero_range (lb, ub, signbit_known);
2663
2664 // If divisor must be zero, the range is just +-INF
2665 // (including if the dividend is +-INF).
2666 // If dividend must be +-INF, the range is just +-INF
2667 // (including if the dividend is zero).
2668 if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
2669 return inf_range (lb, ub, signbit_known);
2670
2671 // Otherwise if both operands may be zero, divisor could be
2672 // nextafter(0.0, +-1.0) and dividend +-0.0
2673 // in which case result is going to INF or vice versa and
2674 // result +0.0. So, all we can say for that case is if the
2675 // signs of divisor and dividend are always the same we have
2676 // [+0.0, +INF], if they are always different we have
2677 // [-INF, -0.0]. If they vary, VARING.
2678 // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
2679 // in which case result is going to INF or vice versa and
2680 // result +0.0. So, all we can say for that case is if the
2681 // signs of divisor and dividend are always the same we have
2682 // [+0.0, +INF], if they are always different we have
2683 // [-INF, -0.0]. If they vary, VARYING.
2684 if (maybe_nan)
2685 return zero_to_inf_range (lb, ub, signbit_known);
2686
2687 REAL_VALUE_TYPE cp[8];
2688 // Do a cross-division. At this point none of the divisions should
2689 // produce a NAN.
2690 frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2691 frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2692 frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2693 frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2694 frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2695 frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2696 frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2697 frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2698
2699 find_range (lb, ub, cp);
2700
2701 // If divisor may be zero (but is not known to be only zero),
2702 // and dividend can't be zero, the range can go up to -INF or +INF
2703 // depending on the signs.
2704 if (contains_zero_p (rh_lb, rh_ub))
2705 {
2706 if (signbit_known <= 0)
2707 real_inf (&lb, true);
2708 if (signbit_known >= 0)
2709 real_inf (&ub, false);
2710 }
2711 }
2712 } fop_div;
2713
2714 // Instantiate a range_op_table for floating point operations.
2715 static floating_op_table global_floating_table;
2716
2717 // Pointer to the float table so the dispatch code can access it.
2718 floating_op_table *floating_tree_table = &global_floating_table;
2719
2720 floating_op_table::floating_op_table ()
2721 {
2722 set (SSA_NAME, fop_identity);
2723 set (PAREN_EXPR, fop_identity);
2724 set (OBJ_TYPE_REF, fop_identity);
2725 set (REAL_CST, fop_identity);
2726
2727 // All the relational operators are expected to work, because the
2728 // calculation of ranges on outgoing edges expect the handlers to be
2729 // present.
2730 set (EQ_EXPR, fop_equal);
2731 set (NE_EXPR, fop_not_equal);
2732 set (LT_EXPR, fop_lt);
2733 set (LE_EXPR, fop_le);
2734 set (GT_EXPR, fop_gt);
2735 set (GE_EXPR, fop_ge);
2736 set (UNLE_EXPR, fop_unordered_le);
2737 set (UNLT_EXPR, fop_unordered_lt);
2738 set (UNGE_EXPR, fop_unordered_ge);
2739 set (UNGT_EXPR, fop_unordered_gt);
2740 set (UNEQ_EXPR, fop_unordered_equal);
2741 set (ORDERED_EXPR, fop_ordered);
2742 set (UNORDERED_EXPR, fop_unordered);
2743
2744 set (ABS_EXPR, fop_abs);
2745 set (NEGATE_EXPR, fop_negate);
2746 set (PLUS_EXPR, fop_plus);
2747 set (MINUS_EXPR, fop_minus);
2748 set (MULT_EXPR, fop_mult);
2749 set (RDIV_EXPR, fop_div);
2750 }
2751
2752 // Return a pointer to the range_operator_float instance, if there is
2753 // one associated with tree_code CODE.
2754
2755 range_operator_float *
2756 floating_op_table::operator[] (enum tree_code code)
2757 {
2758 return m_range_tree[code];
2759 }
2760
2761 // Add OP to the handler table for CODE.
2762
2763 void
2764 floating_op_table::set (enum tree_code code, range_operator_float &op)
2765 {
2766 gcc_checking_assert (m_range_tree[code] == NULL);
2767 m_range_tree[code] = &op;
2768 }
2769
2770 #if CHECKING_P
2771 #include "selftest.h"
2772
2773 namespace selftest
2774 {
2775
2776 // Build an frange from string endpoints.
2777
2778 inline frange
2779 frange_float (const char *lb, const char *ub, tree type = float_type_node)
2780 {
2781 REAL_VALUE_TYPE min, max;
2782 gcc_assert (real_from_string (&min, lb) == 0);
2783 gcc_assert (real_from_string (&max, ub) == 0);
2784 return frange (type, min, max);
2785 }
2786
2787 void
2788 range_op_float_tests ()
2789 {
2790 frange r, r0, r1;
2791 frange trange (float_type_node);
2792
2793 // negate([-5, +10]) => [-10, 5]
2794 r0 = frange_float ("-5", "10");
2795 fop_negate.fold_range (r, float_type_node, r0, trange);
2796 ASSERT_EQ (r, frange_float ("-10", "5"));
2797
2798 // negate([0, 1] -NAN) => [-1, -0] +NAN
2799 r0 = frange_float ("0", "1");
2800 r0.update_nan (true);
2801 fop_negate.fold_range (r, float_type_node, r0, trange);
2802 r1 = frange_float ("-1", "-0");
2803 r1.update_nan (false);
2804 ASSERT_EQ (r, r1);
2805
2806 // [-INF,+INF] + [-INF,+INF] could be a NAN.
2807 range_op_handler plus (PLUS_EXPR, float_type_node);
2808 r0.set_varying (float_type_node);
2809 r1.set_varying (float_type_node);
2810 r0.clear_nan ();
2811 r1.clear_nan ();
2812 plus.fold_range (r, float_type_node, r0, r1);
2813 if (HONOR_NANS (float_type_node))
2814 ASSERT_TRUE (r.maybe_isnan ());
2815 }
2816
2817 } // namespace selftest
2818
2819 #endif // CHECKING_P