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

source code of gcc/range-op-float.cc