]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/range-op-float.cc
libstdc++: fix C header include guards
[thirdparty/gcc.git] / gcc / range-op-float.cc
CommitLineData
a6efab5f 1/* Floating point range operators.
a945c346 2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
a6efab5f
AH
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"
07767389 48#include "range-op-mixed.h"
a6efab5f
AH
49
50// Default definitions for floating point operators.
51
52bool
9c0fed50 53range_operator::fold_range (frange &r, tree type,
0ef5649e 54 const frange &op1, const frange &op2,
2f7f9edd 55 relation_trio trio) const
a6efab5f 56{
0ef5649e
AH
57 if (empty_range_varying (r, type, op1, op2))
58 return true;
59 if (op1.known_isnan () || op2.known_isnan ())
60 {
ce81740c 61 r.set_nan (type);
0ef5649e
AH
62 return true;
63 }
64
848b5f3a 65 rv_fold (r, type,
0ef5649e 66 op1.lower_bound (), op1.upper_bound (),
2f7f9edd 67 op2.lower_bound (), op2.upper_bound (), trio.op1_op2 ());
0ef5649e 68
848b5f3a
AH
69 if (r.known_isnan ())
70 return true;
24e97ac4 71 if (op1.maybe_isnan () || op2.maybe_isnan ())
848b5f3a 72 r.update_nan ();
24e97ac4 73
844190af
AH
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
ce3974e5
JJ
95 r.flush_denormals_to_zero ();
96
0ef5649e
AH
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
c46b5b0a 102// UB, the final range has the possibility of a NAN.
0ef5649e 103void
24e97ac4 104range_operator::rv_fold (frange &r, tree type,
24e97ac4
AH
105 const REAL_VALUE_TYPE &,
106 const REAL_VALUE_TYPE &,
107 const REAL_VALUE_TYPE &,
108 const REAL_VALUE_TYPE &, relation_kind) const
0ef5649e 109{
24e97ac4 110 r.set (type, dconstninf, dconstinf, nan_state (true));
a6efab5f
AH
111}
112
be2a25ad 113bool
9c0fed50 114range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
be2a25ad
AM
115 tree type ATTRIBUTE_UNUSED,
116 const frange &lh ATTRIBUTE_UNUSED,
117 const irange &rh ATTRIBUTE_UNUSED,
b565ac19 118 relation_trio) const
be2a25ad
AM
119{
120 return false;
121}
122
a6efab5f 123bool
9c0fed50 124range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
a6efab5f
AH
125 tree type ATTRIBUTE_UNUSED,
126 const frange &lh ATTRIBUTE_UNUSED,
127 const frange &rh ATTRIBUTE_UNUSED,
b565ac19 128 relation_trio) const
a6efab5f
AH
129{
130 return false;
131}
132
0ddc8c78
AM
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
a6efab5f 143bool
9c0fed50 144range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
a6efab5f
AH
145 tree type ATTRIBUTE_UNUSED,
146 const frange &lhs ATTRIBUTE_UNUSED,
147 const frange &op2 ATTRIBUTE_UNUSED,
b565ac19 148 relation_trio) const
a6efab5f
AH
149{
150 return false;
151}
152
153bool
9c0fed50 154range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
a6efab5f
AH
155 tree type ATTRIBUTE_UNUSED,
156 const irange &lhs ATTRIBUTE_UNUSED,
157 const frange &op2 ATTRIBUTE_UNUSED,
b565ac19 158 relation_trio) const
a6efab5f
AH
159{
160 return false;
161}
162
163bool
9c0fed50 164range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
a6efab5f
AH
165 tree type ATTRIBUTE_UNUSED,
166 const frange &lhs ATTRIBUTE_UNUSED,
167 const frange &op1 ATTRIBUTE_UNUSED,
b565ac19 168 relation_trio) const
a6efab5f
AH
169{
170 return false;
171}
172
173bool
9c0fed50 174range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
a6efab5f
AH
175 tree type ATTRIBUTE_UNUSED,
176 const irange &lhs ATTRIBUTE_UNUSED,
177 const frange &op1 ATTRIBUTE_UNUSED,
b565ac19 178 relation_trio) const
a6efab5f
AH
179{
180 return false;
181}
182
183relation_kind
9c0fed50 184range_operator::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
a6efab5f
AH
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
9c0fed50 193range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
a6efab5f
AH
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
9c0fed50 202range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
a6efab5f
AH
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
9c0fed50 211range_operator::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
a6efab5f
AH
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
9fedc3c0
AM
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
5364b425
AH
232{
233 return VREL_VARYING;
234}
235
be43d5d3 236// Return TRUE if OP1 and OP2 may be a NAN.
4fbe3e6a
AH
237
238static inline bool
be43d5d3 239maybe_isnan (const frange &op1, const frange &op2)
4fbe3e6a 240{
be43d5d3 241 return op1.maybe_isnan () || op2.maybe_isnan ();
24012539
AH
242}
243
66be6ed8
AH
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.
24012539 257
d438b67e 258static inline bool
24012539
AH
259frelop_early_resolve (irange &r, tree type,
260 const frange &op1, const frange &op2,
66be6ed8 261 relation_trio trio, relation_kind my_rel)
24012539 262{
66be6ed8
AH
263 relation_kind rel = trio.op1_op2 ();
264
66be6ed8
AH
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)
7a4e57ff 275 if (!maybe_isnan (op1, op2) && relation_union (rel, my_rel) == my_rel)
66be6ed8
AH
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 (rel, my_rel) == VREL_UNDEFINED)
283 {
284 r = range_false (type);
285 return true;
286 }
287
24012539
AH
288 // If either operand is undefined, return VARYING.
289 if (empty_range_varying (r, type, op1, op2))
290 return true;
291
66be6ed8 292 return false;
24012539
AH
293}
294
9d96a286
AH
295// Set VALUE to its next real value, or INF if the operation overflows.
296
d438b67e 297void
9d96a286
AH
298frange_nextafter (enum machine_mode mode,
299 REAL_VALUE_TYPE &value,
300 const REAL_VALUE_TYPE &inf)
301{
716c2d08
JJ
302 if (MODE_COMPOSITE_P (mode)
303 && (real_isdenormal (&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 }
9d96a286
AH
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
c46b5b0a 326// precision (64-bit mantissa) and only occasionally rounded to
9d96a286 327// SF/DFmode (when storing into memory from the 387 stack). Maybe
c46b5b0a 328// this is ok as well though it is just occasionally more precise. ??
9d96a286 329
82aef047 330void
9d96a286
AH
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
21da32d9
JJ
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
9d96a286
AH
362 // Be extra careful if there may be discrepancies between the
363 // compile and runtime results.
2f187e98
JJ
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, !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, 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)))
9d96a286 400 {
716c2d08
JJ
401 if (mode_composite
402 && (real_isdenormal (&result, mode) || real_iszero (&result)))
9d96a286 403 {
716c2d08
JJ
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);
9d96a286 409 }
716c2d08
JJ
410 else
411 frange_nextafter (mode, result, inf);
9d96a286 412 }
716c2d08
JJ
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, result, inf);
420 break;
421 case MULT_EXPR:
422 // ibm-ldouble-format documents 2ulps for *.
423 frange_nextafter (mode, result, inf);
424 frange_nextafter (mode, result, inf);
425 break;
426 case RDIV_EXPR:
427 // ibm-ldouble-format documents 3ulps for /.
428 frange_nextafter (mode, result, inf);
429 frange_nextafter (mode, result, inf);
430 frange_nextafter (mode, result, inf);
431 break;
432 default:
433 break;
434 }
9d96a286
AH
435}
436
8bb1df03
AH
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{
b7fd7fb5 443 REAL_VALUE_TYPE max = real_max_representable (type);
8bb1df03
AH
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{
b7fd7fb5 454 REAL_VALUE_TYPE min = real_min_representable (type);
8bb1df03
AH
455 frange tmp (type, min, r.upper_bound ());
456 r.intersect (tmp);
457}
458
a0ee2e52
JJ
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
3c85c118
AH
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{
91746147 476 if (r.undefined_p () || r.known_isnan ())
3c85c118
AH
477 return;
478
479 if (HONOR_SIGNED_ZEROS (type)
480 && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
91746147
AH
481 {
482 frange zero;
483 zero.set_zero (type);
484 r.union_ (zero);
485 }
3c85c118
AH
486}
487
f0068278
AH
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.
4fbe3e6a 491
f5dc9da0 492static bool
7d647a8d 493build_le (frange &r, tree type, const frange &val)
4fbe3e6a 494{
d2278da1
AH
495 gcc_checking_assert (!val.known_isnan ());
496
b7fd7fb5
AH
497 REAL_VALUE_TYPE ninf = frange_val_min (type);
498 r.set (type, ninf, val.upper_bound ());
3c85c118
AH
499
500 // Add both zeros if there's the possibility of zero equality.
501 frange_add_zeros (r, type);
502
f5dc9da0 503 return true;
4fbe3e6a
AH
504}
505
f0068278
AH
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.
4fbe3e6a 509
f5dc9da0 510static bool
7d647a8d 511build_lt (frange &r, tree type, const frange &val)
4fbe3e6a 512{
d2278da1
AH
513 gcc_checking_assert (!val.known_isnan ());
514
f5dc9da0 515 // < -INF is outside the range.
7d647a8d 516 if (real_isinf (&val.upper_bound (), 1))
f5dc9da0
AH
517 {
518 if (HONOR_NANS (type))
9c4c4186 519 r.set_nan (type);
f5dc9da0
AH
520 else
521 r.set_undefined ();
522 return false;
523 }
4c57e57b 524
b7fd7fb5 525 REAL_VALUE_TYPE ninf = frange_val_min (type);
4c57e57b
AH
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, prev, ninf);
534 r.set (type, ninf, prev);
f5dc9da0 535 return true;
4fbe3e6a
AH
536}
537
f0068278
AH
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.
4fbe3e6a 541
f5dc9da0 542static bool
7d647a8d 543build_ge (frange &r, tree type, const frange &val)
4fbe3e6a 544{
d2278da1
AH
545 gcc_checking_assert (!val.known_isnan ());
546
b7fd7fb5
AH
547 REAL_VALUE_TYPE inf = frange_val_max (type);
548 r.set (type, val.lower_bound (), inf);
3c85c118
AH
549
550 // Add both zeros if there's the possibility of zero equality.
551 frange_add_zeros (r, type);
552
f5dc9da0 553 return true;
4fbe3e6a
AH
554}
555
f0068278
AH
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.
4fbe3e6a 559
f5dc9da0 560static bool
7d647a8d 561build_gt (frange &r, tree type, const frange &val)
4fbe3e6a 562{
d2278da1
AH
563 gcc_checking_assert (!val.known_isnan ());
564
f5dc9da0 565 // > +INF is outside the range.
7d647a8d 566 if (real_isinf (&val.lower_bound (), 0))
f5dc9da0
AH
567 {
568 if (HONOR_NANS (type))
9c4c4186 569 r.set_nan (type);
f5dc9da0
AH
570 else
571 r.set_undefined ();
572 return false;
573 }
574
b7fd7fb5 575 REAL_VALUE_TYPE inf = frange_val_max (type);
4c57e57b
AH
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, next, inf);
584 r.set (type, next, inf);
f5dc9da0 585 return true;
4fbe3e6a
AH
586}
587
588
b073d8af
AM
589bool
590operator_identity::fold_range (frange &r, tree, const frange &op1,
591 const frange &, relation_trio) const
a6efab5f 592{
b073d8af
AM
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
4f0ac5a5
AM
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}
a6efab5f 612
2dbf1e61
AM
613bool
614operator_equal::op2_range (frange &r, tree type,
615 const irange &lhs, const frange &op1,
616 relation_trio rel) const
24012539 617{
2dbf1e61
AM
618 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
619}
24012539 620
4fbe3e6a 621bool
2dbf1e61
AM
622operator_equal::fold_range (irange &r, tree type,
623 const frange &op1, const frange &op2,
624 relation_trio rel) const
4fbe3e6a
AH
625{
626 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
627 return true;
628
d2278da1
AH
629 if (op1.known_isnan () || op2.known_isnan ())
630 r = range_false (type);
4fbe3e6a
AH
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.
d2278da1 633 else if (op1.singleton_p () && op2.singleton_p ())
4fbe3e6a
AH
634 {
635 if (op1 == op2)
636 r = range_true (type);
09176201
JJ
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);
4fbe3e6a
AH
641 else
642 r = range_false (type);
643 }
69044e11
JJ
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);
5fe05ffe 651 else
4fbe3e6a
AH
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 ())
09176201
JJ
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 }
4fbe3e6a
AH
670 else
671 r = range_true_and_false (type);
672 }
4fbe3e6a
AH
673 return true;
674}
675
24012539 676bool
2dbf1e61 677operator_equal::op1_range (frange &r, tree type,
24012539 678 const irange &lhs,
d2278da1 679 const frange &op2,
b565ac19 680 relation_trio trio) const
24012539 681{
b565ac19 682 relation_kind rel = trio.op1_op2 ();
24012539
AH
683 switch (get_bool_state (r, lhs, type))
684 {
685 case BRS_TRUE:
d2278da1
AH
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 }
24012539
AH
698 break;
699
700 case BRS_FALSE:
24012539
AH
701 // The FALSE side of op1 == op1 implies op1 is a NAN.
702 if (rel == VREL_EQ)
9c4c4186 703 r.set_nan (type);
d2278da1
AH
704 // On the FALSE side of x == NAN, we know nothing about x.
705 else if (op2.known_isnan ())
706 r.set_varying (type);
4fbe3e6a
AH
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 ()
be43d5d3 710 || (!op2.maybe_isnan () && op2.zero_p ()))
4fbe3e6a
AH
711 {
712 REAL_VALUE_TYPE tmp = op2.lower_bound ();
713 r.set (type, tmp, tmp, VR_ANTI_RANGE);
714 }
d2278da1
AH
715 else
716 r.set_varying (type);
24012539
AH
717 break;
718
719 default:
720 break;
721 }
722 return true;
723}
724
9fedc3c0
AM
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.
7ece864a 739 if (!contains_zero_p (lhs))
9fedc3c0
AM
740 return VREL_EQ;
741 return VREL_VARYING;
742}
743
4fbe3e6a 744bool
eb29c3e1
AM
745operator_not_equal::fold_range (irange &r, tree type,
746 const frange &op1, const frange &op2,
66be6ed8 747 relation_trio trio) const
4fbe3e6a 748{
66be6ed8
AH
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 }
7a4e57ff
AH
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, VREL_NE))
4fbe3e6a
AH
764 return true;
765
d2278da1
AH
766 // x != NAN is always TRUE.
767 if (op1.known_isnan () || op2.known_isnan ())
768 r = range_true (type);
4fbe3e6a
AH
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.
d2278da1 771 else if (op1.singleton_p () && op2.singleton_p ())
4fbe3e6a 772 {
09176201 773 if (op1 == op2)
4fbe3e6a 774 r = range_false (type);
09176201
JJ
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);
4fbe3e6a 781 }
69044e11
JJ
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);
5fe05ffe 789 else
4fbe3e6a
AH
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 ())
09176201
JJ
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 }
4fbe3e6a
AH
808 else
809 r = range_true_and_false (type);
810 }
4fbe3e6a
AH
811 return true;
812}
813
24012539 814bool
eb29c3e1
AM
815operator_not_equal::op1_range (frange &r, tree type,
816 const irange &lhs,
817 const frange &op2,
818 relation_trio trio) const
24012539 819{
b565ac19 820 relation_kind rel = trio.op1_op2 ();
24012539
AH
821 switch (get_bool_state (r, lhs, type))
822 {
823 case BRS_TRUE:
4fbe3e6a
AH
824 // If the result is true, the only time we know anything is if
825 // OP2 is a constant.
04874fed 826 if (op2.singleton_p ())
4fbe3e6a
AH
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 }
04874fed
AM
834 // The TRUE side of op1 != op1 implies op1 is NAN.
835 else if (rel == VREL_EQ)
836 r.set_nan (type);
4fbe3e6a
AH
837 else
838 r.set_varying (type);
24012539
AH
839 break;
840
841 case BRS_FALSE:
d2278da1
AH
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 }
24012539
AH
854 break;
855
856 default:
857 break;
858 }
859 return true;
860}
861
9c739c98
AH
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, op1, trio);
869}
9fedc3c0
AM
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.
7ece864a 885 if (!contains_zero_p (lhs))
9fedc3c0
AM
886 return VREL_NE;
887 return VREL_VARYING;
888}
889
4fbe3e6a 890bool
5b079541
AM
891operator_lt::fold_range (irange &r, tree type,
892 const frange &op1, const frange &op2,
66be6ed8 893 relation_trio trio) const
4fbe3e6a 894{
66be6ed8 895 if (frelop_early_resolve (r, type, op1, op2, trio, VREL_LT))
4fbe3e6a
AH
896 return true;
897
5fe05ffe
JJ
898 if (op1.known_isnan ()
899 || op2.known_isnan ()
900 || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
d2278da1 901 r = range_false (type);
5fe05ffe
JJ
902 else if (!maybe_isnan (op1, op2)
903 && real_less (&op1.upper_bound (), &op2.lower_bound ()))
904 r = range_true (type);
4fbe3e6a
AH
905 else
906 r = range_true_and_false (type);
907 return true;
908}
909
24012539 910bool
5b079541
AM
911operator_lt::op1_range (frange &r,
912 tree type,
913 const irange &lhs,
914 const frange &op2,
915 relation_trio) const
24012539
AH
916{
917 switch (get_bool_state (r, lhs, type))
918 {
919 case BRS_TRUE:
d2278da1
AH
920 // The TRUE side of x < NAN is unreachable.
921 if (op2.known_isnan ())
922 r.set_undefined ();
10bd26d6
AH
923 else if (op2.undefined_p ())
924 return false;
d2278da1 925 else if (build_lt (r, type, op2))
f5dc9da0 926 {
9c4c4186 927 r.clear_nan ();
f5dc9da0
AH
928 // x < y implies x is not +INF.
929 frange_drop_inf (r, type);
930 }
24012539
AH
931 break;
932
933 case BRS_FALSE:
d2278da1 934 // On the FALSE side of x < NAN, we know nothing about x.
36eec799 935 if (op2.maybe_isnan ())
d2278da1
AH
936 r.set_varying (type);
937 else
938 build_ge (r, type, op2);
24012539
AH
939 break;
940
941 default:
942 break;
943 }
944 return true;
945}
946
947bool
5b079541
AM
948operator_lt::op2_range (frange &r,
949 tree type,
950 const irange &lhs,
951 const frange &op1,
952 relation_trio) const
24012539
AH
953{
954 switch (get_bool_state (r, lhs, type))
955 {
956 case BRS_TRUE:
d2278da1
AH
957 // The TRUE side of NAN < x is unreachable.
958 if (op1.known_isnan ())
959 r.set_undefined ();
10bd26d6
AH
960 else if (op1.undefined_p ())
961 return false;
d2278da1 962 else if (build_gt (r, type, op1))
f5dc9da0 963 {
9c4c4186 964 r.clear_nan ();
f5dc9da0
AH
965 // x < y implies y is not -INF.
966 frange_drop_ninf (r, type);
967 }
24012539
AH
968 break;
969
970 case BRS_FALSE:
d2278da1 971 // On the FALSE side of NAN < x, we know nothing about x.
36eec799 972 if (op1.maybe_isnan ())
d2278da1
AH
973 r.set_varying (type);
974 else
975 build_le (r, type, op1);
24012539
AH
976 break;
977
978 default:
979 break;
980 }
981 return true;
982}
983
9fedc3c0
AM
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.
7ece864a 999 if (!contains_zero_p (lhs))
9fedc3c0
AM
1000 return VREL_LT;
1001 return VREL_VARYING;
1002}
1003
4fbe3e6a 1004bool
d251d14c
AM
1005operator_le::fold_range (irange &r, tree type,
1006 const frange &op1, const frange &op2,
1007 relation_trio rel) const
4fbe3e6a
AH
1008{
1009 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
1010 return true;
1011
5fe05ffe
JJ
1012 if (op1.known_isnan ()
1013 || op2.known_isnan ()
1014 || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
d2278da1 1015 r = range_false (type);
5fe05ffe
JJ
1016 else if (!maybe_isnan (op1, op2)
1017 && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1018 r = range_true (type);
4fbe3e6a
AH
1019 else
1020 r = range_true_and_false (type);
1021 return true;
1022}
1023
24012539 1024bool
d251d14c
AM
1025operator_le::op1_range (frange &r,
1026 tree type,
1027 const irange &lhs,
1028 const frange &op2,
1029 relation_trio) const
24012539
AH
1030{
1031 switch (get_bool_state (r, lhs, type))
1032 {
1033 case BRS_TRUE:
d2278da1
AH
1034 // The TRUE side of x <= NAN is unreachable.
1035 if (op2.known_isnan ())
1036 r.set_undefined ();
10bd26d6
AH
1037 else if (op2.undefined_p ())
1038 return false;
d2278da1 1039 else if (build_le (r, type, op2))
9c4c4186 1040 r.clear_nan ();
24012539
AH
1041 break;
1042
1043 case BRS_FALSE:
d2278da1 1044 // On the FALSE side of x <= NAN, we know nothing about x.
36eec799 1045 if (op2.maybe_isnan ())
d2278da1
AH
1046 r.set_varying (type);
1047 else
1048 build_gt (r, type, op2);
4fbe3e6a
AH
1049 break;
1050
1051 default:
1052 break;
1053 }
1054 return true;
1055}
1056
1057bool
d251d14c
AM
1058operator_le::op2_range (frange &r,
1059 tree type,
1060 const irange &lhs,
1061 const frange &op1,
1062 relation_trio) const
4fbe3e6a
AH
1063{
1064 switch (get_bool_state (r, lhs, type))
1065 {
1066 case BRS_TRUE:
d2278da1
AH
1067 // The TRUE side of NAN <= x is unreachable.
1068 if (op1.known_isnan ())
1069 r.set_undefined ();
10bd26d6
AH
1070 else if (op1.undefined_p ())
1071 return false;
d2278da1 1072 else if (build_ge (r, type, op1))
9c4c4186 1073 r.clear_nan ();
4fbe3e6a
AH
1074 break;
1075
1076 case BRS_FALSE:
d2278da1 1077 // On the FALSE side of NAN <= x, we know nothing about x.
36eec799 1078 if (op1.maybe_isnan ())
d2278da1 1079 r.set_varying (type);
10bd26d6
AH
1080 else if (op1.undefined_p ())
1081 return false;
d2278da1
AH
1082 else
1083 build_lt (r, type, op1);
24012539
AH
1084 break;
1085
1086 default:
1087 break;
1088 }
1089 return true;
1090}
1091
9fedc3c0
AM
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.
7ece864a 1106 if (!contains_zero_p (lhs))
9fedc3c0
AM
1107 return VREL_LE;
1108 return VREL_VARYING;
1109}
1110
4fbe3e6a 1111bool
f544e7e8
AM
1112operator_gt::fold_range (irange &r, tree type,
1113 const frange &op1, const frange &op2,
66be6ed8 1114 relation_trio trio) const
4fbe3e6a 1115{
66be6ed8 1116 if (frelop_early_resolve (r, type, op1, op2, trio, VREL_GT))
4fbe3e6a
AH
1117 return true;
1118
5fe05ffe
JJ
1119 if (op1.known_isnan ()
1120 || op2.known_isnan ()
1121 || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
d2278da1 1122 r = range_false (type);
5fe05ffe
JJ
1123 else if (!maybe_isnan (op1, op2)
1124 && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1125 r = range_true (type);
4fbe3e6a
AH
1126 else
1127 r = range_true_and_false (type);
1128 return true;
1129}
1130
24012539 1131bool
f544e7e8
AM
1132operator_gt::op1_range (frange &r,
1133 tree type,
1134 const irange &lhs,
1135 const frange &op2,
1136 relation_trio) const
24012539
AH
1137{
1138 switch (get_bool_state (r, lhs, type))
1139 {
1140 case BRS_TRUE:
d2278da1
AH
1141 // The TRUE side of x > NAN is unreachable.
1142 if (op2.known_isnan ())
1143 r.set_undefined ();
10bd26d6
AH
1144 else if (op2.undefined_p ())
1145 return false;
d2278da1 1146 else if (build_gt (r, type, op2))
f5dc9da0 1147 {
9c4c4186 1148 r.clear_nan ();
f5dc9da0
AH
1149 // x > y implies x is not -INF.
1150 frange_drop_ninf (r, type);
1151 }
24012539
AH
1152 break;
1153
1154 case BRS_FALSE:
d2278da1 1155 // On the FALSE side of x > NAN, we know nothing about x.
36eec799 1156 if (op2.maybe_isnan ())
d2278da1 1157 r.set_varying (type);
10bd26d6
AH
1158 else if (op2.undefined_p ())
1159 return false;
d2278da1
AH
1160 else
1161 build_le (r, type, op2);
24012539
AH
1162 break;
1163
1164 default:
1165 break;
1166 }
1167 return true;
1168}
1169
1170bool
f544e7e8
AM
1171operator_gt::op2_range (frange &r,
1172 tree type,
1173 const irange &lhs,
1174 const frange &op1,
1175 relation_trio) const
24012539
AH
1176{
1177 switch (get_bool_state (r, lhs, type))
1178 {
1179 case BRS_TRUE:
d2278da1
AH
1180 // The TRUE side of NAN > x is unreachable.
1181 if (op1.known_isnan ())
1182 r.set_undefined ();
10bd26d6
AH
1183 else if (op1.undefined_p ())
1184 return false;
d2278da1 1185 else if (build_lt (r, type, op1))
f5dc9da0 1186 {
9c4c4186 1187 r.clear_nan ();
f5dc9da0
AH
1188 // x > y implies y is not +INF.
1189 frange_drop_inf (r, type);
1190 }
24012539
AH
1191 break;
1192
1193 case BRS_FALSE:
d2278da1 1194 // On The FALSE side of NAN > x, we know nothing about x.
36eec799 1195 if (op1.maybe_isnan ())
d2278da1 1196 r.set_varying (type);
10bd26d6
AH
1197 else if (op1.undefined_p ())
1198 return false;
d2278da1
AH
1199 else
1200 build_ge (r, type, op1);
24012539
AH
1201 break;
1202
1203 default:
1204 break;
1205 }
1206 return true;
1207}
1208
9fedc3c0
AM
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 (lhs))
1224 return VREL_GT;
1225 return VREL_VARYING;
1226}
1227
4fbe3e6a 1228bool
a0a8f1c7
AM
1229operator_ge::fold_range (irange &r, tree type,
1230 const frange &op1, const frange &op2,
1231 relation_trio rel) const
4fbe3e6a
AH
1232{
1233 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
1234 return true;
1235
5fe05ffe
JJ
1236 if (op1.known_isnan ()
1237 || op2.known_isnan ()
1238 || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
d2278da1 1239 r = range_false (type);
5fe05ffe
JJ
1240 else if (!maybe_isnan (op1, op2)
1241 && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1242 r = range_true (type);
4fbe3e6a
AH
1243 else
1244 r = range_true_and_false (type);
1245 return true;
1246}
1247
24012539 1248bool
a0a8f1c7
AM
1249operator_ge::op1_range (frange &r,
1250 tree type,
1251 const irange &lhs,
1252 const frange &op2,
1253 relation_trio) const
24012539
AH
1254{
1255 switch (get_bool_state (r, lhs, type))
1256 {
1257 case BRS_TRUE:
d2278da1
AH
1258 // The TRUE side of x >= NAN is unreachable.
1259 if (op2.known_isnan ())
1260 r.set_undefined ();
10bd26d6
AH
1261 else if (op2.undefined_p ())
1262 return false;
d2278da1
AH
1263 else if (build_ge (r, type, op2))
1264 r.clear_nan ();
24012539
AH
1265 break;
1266
1267 case BRS_FALSE:
d2278da1 1268 // On the FALSE side of x >= NAN, we know nothing about x.
36eec799 1269 if (op2.maybe_isnan ())
d2278da1 1270 r.set_varying (type);
10bd26d6
AH
1271 else if (op2.undefined_p ())
1272 return false;
d2278da1
AH
1273 else
1274 build_lt (r, type, op2);
4fbe3e6a
AH
1275 break;
1276
1277 default:
1278 break;
1279 }
1280 return true;
1281}
1282
1283bool
a0a8f1c7
AM
1284operator_ge::op2_range (frange &r, tree type,
1285 const irange &lhs,
1286 const frange &op1,
1287 relation_trio) const
4fbe3e6a
AH
1288{
1289 switch (get_bool_state (r, lhs, type))
1290 {
d2278da1
AH
1291 case BRS_TRUE:
1292 // The TRUE side of NAN >= x is unreachable.
1293 if (op1.known_isnan ())
1294 r.set_undefined ();
10bd26d6
AH
1295 else if (op1.undefined_p ())
1296 return false;
f0068278
AH
1297 else if (build_le (r, type, op1))
1298 r.clear_nan ();
4fbe3e6a
AH
1299 break;
1300
d2278da1
AH
1301 case BRS_FALSE:
1302 // On the FALSE side of NAN >= x, we know nothing about x.
36eec799 1303 if (op1.maybe_isnan ())
d2278da1 1304 r.set_varying (type);
10bd26d6
AH
1305 else if (op1.undefined_p ())
1306 return false;
d2278da1
AH
1307 else
1308 build_gt (r, type, op1);
24012539
AH
1309 break;
1310
1311 default:
1312 break;
1313 }
1314 return true;
1315}
1316
9fedc3c0
AM
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 (lhs))
1332 return VREL_GE;
1333 return VREL_VARYING;
1334}
1335
24012539
AH
1336// UNORDERED_EXPR comparison.
1337
9c0fed50 1338class foperator_unordered : public range_operator
24012539 1339{
9c0fed50
AM
1340 using range_operator::fold_range;
1341 using range_operator::op1_range;
1342 using range_operator::op2_range;
24012539
AH
1343public:
1344 bool fold_range (irange &r, tree type,
1345 const frange &op1, const frange &op2,
b565ac19 1346 relation_trio = TRIO_VARYING) const final override;
24012539
AH
1347 bool op1_range (frange &r, tree type,
1348 const irange &lhs, const frange &op2,
b565ac19 1349 relation_trio = TRIO_VARYING) const final override;
24012539
AH
1350 bool op2_range (frange &r, tree type,
1351 const irange &lhs, const frange &op1,
b565ac19 1352 relation_trio rel = TRIO_VARYING) const final override
24012539 1353 {
b565ac19 1354 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
24012539
AH
1355 }
1356} fop_unordered;
1357
1358bool
1359foperator_unordered::fold_range (irange &r, tree type,
1360 const frange &op1, const frange &op2,
b565ac19 1361 relation_trio) const
24012539
AH
1362{
1363 // UNORDERED is TRUE if either operand is a NAN.
91746147 1364 if (op1.known_isnan () || op2.known_isnan ())
24012539
AH
1365 r = range_true (type);
1366 // UNORDERED is FALSE if neither operand is a NAN.
91746147 1367 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
24012539
AH
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,
d2278da1 1377 const frange &op2,
b565ac19 1378 relation_trio trio) const
24012539 1379{
b565ac19 1380 relation_kind rel = trio.op1_op2 ();
24012539
AH
1381 switch (get_bool_state (r, lhs, type))
1382 {
1383 case BRS_TRUE:
24012539
AH
1384 // Since at least one operand must be NAN, if one of them is
1385 // not, the other must be.
04874fed 1386 if (rel == VREL_EQ || !op2.maybe_isnan ())
9c4c4186 1387 r.set_nan (type);
d2278da1
AH
1388 else
1389 r.set_varying (type);
24012539
AH
1390 break;
1391
1392 case BRS_FALSE:
d2278da1
AH
1393 // A false UNORDERED means both operands are !NAN, so it's
1394 // impossible for op2 to be a NAN.
04874fed 1395 if (op2.known_isnan ())
d2278da1
AH
1396 r.set_undefined ();
1397 else
1398 {
1399 r.set_varying (type);
1400 r.clear_nan ();
1401 }
24012539
AH
1402 break;
1403
1404 default:
1405 break;
1406 }
1407 return true;
1408}
1409
1410// ORDERED_EXPR comparison.
1411
9c0fed50 1412class foperator_ordered : public range_operator
24012539 1413{
9c0fed50
AM
1414 using range_operator::fold_range;
1415 using range_operator::op1_range;
1416 using range_operator::op2_range;
24012539
AH
1417public:
1418 bool fold_range (irange &r, tree type,
1419 const frange &op1, const frange &op2,
b565ac19 1420 relation_trio = TRIO_VARYING) const final override;
24012539
AH
1421 bool op1_range (frange &r, tree type,
1422 const irange &lhs, const frange &op2,
b565ac19 1423 relation_trio = TRIO_VARYING) const final override;
24012539
AH
1424 bool op2_range (frange &r, tree type,
1425 const irange &lhs, const frange &op1,
b565ac19 1426 relation_trio rel = TRIO_VARYING) const final override
24012539 1427 {
b565ac19 1428 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
24012539
AH
1429 }
1430} fop_ordered;
1431
1432bool
1433foperator_ordered::fold_range (irange &r, tree type,
1434 const frange &op1, const frange &op2,
b565ac19 1435 relation_trio) const
24012539 1436{
d2278da1 1437 if (op1.known_isnan () || op2.known_isnan ())
24012539 1438 r = range_false (type);
d2278da1
AH
1439 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1440 r = range_true (type);
24012539
AH
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,
d2278da1 1449 const frange &op2,
b565ac19 1450 relation_trio trio) const
24012539 1451{
b565ac19 1452 relation_kind rel = trio.op1_op2 ();
24012539
AH
1453 switch (get_bool_state (r, lhs, type))
1454 {
1455 case BRS_TRUE:
d2278da1
AH
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 }
24012539
AH
1465 break;
1466
1467 case BRS_FALSE:
04874fed 1468 // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
24012539 1469 if (rel == VREL_EQ)
04874fed
AM
1470 r.set_nan (type);
1471 else
1472 r.set_varying (type);
24012539
AH
1473 break;
1474
1475 default:
1476 break;
1477 }
1478 return true;
1479}
1480
56518bef
AM
1481bool
1482operator_negate::fold_range (frange &r, tree type,
1483 const frange &op1, const frange &op2,
1484 relation_trio) const
a0c1a059 1485{
56518bef
AM
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 (sign))
1492 r.set_nan (type, !sign);
1493 else
1494 r.set_nan (type);
a0c1a059 1495 return true;
56518bef 1496 }
a0c1a059 1497
56518bef
AM
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 (sign))
1507 r.update_nan (!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, lhs, op2, rel);
1522}
a0c1a059 1523
706d8583 1524bool
a1aaaff3
AM
1525operator_abs::fold_range (frange &r, tree type,
1526 const frange &op1, const frange &op2,
1527 relation_trio) const
706d8583
AH
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 (min, 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
a1aaaff3
AM
1575operator_abs::op1_range (frange &r, tree type,
1576 const frange &lhs, const frange &op2,
1577 relation_trio) const
706d8583
AH
1578{
1579 if (empty_range_varying (r, type, 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;
5bcd92d0
AH
1592 // Add -NAN if relevant.
1593 if (r.maybe_isnan ())
1594 {
1595 frange neg_nan;
1596 neg_nan.set_nan (type, true);
1597 r.union_ (neg_nan);
1598 }
4e306222 1599 if (r.known_isnan () || r.undefined_p ())
5bcd92d0 1600 return true;
706d8583
AH
1601 // Then add the negative of each pair:
1602 // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
d943927f
JJ
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);
706d8583
AH
1607 return true;
1608}
1609
9c0fed50 1610class foperator_unordered_lt : public range_operator
4cbc312a 1611{
9c0fed50
AM
1612 using range_operator::fold_range;
1613 using range_operator::op1_range;
1614 using range_operator::op2_range;
4cbc312a
AH
1615public:
1616 bool fold_range (irange &r, tree type,
1617 const frange &op1, const frange &op2,
66be6ed8 1618 relation_trio trio = TRIO_VARYING) const final override
4cbc312a 1619 {
0bd96163 1620 if (op1.known_isnan () || op2.known_isnan ())
4cbc312a
AH
1621 {
1622 r = range_true (type);
1623 return true;
1624 }
e02c9d91
JJ
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 ();
5b079541 1631 if (!range_op_handler (LT_EXPR).fold_range (r, type, op1_no_nan,
66be6ed8 1632 op2_no_nan, trio))
4cbc312a
AH
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.
be43d5d3 1636 if (!maybe_isnan (op1, op2) || r == range_true (type))
4cbc312a
AH
1637 return true;
1638 else
1639 {
1640 r = range_true_and_false (type);
1641 return true;
1642 }
1643 }
2e158eae
AH
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;
4cbc312a 1652} fop_unordered_lt;
24012539 1653
2e158eae
AH
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, type))
1661 {
1662 case BRS_TRUE:
36eec799 1663 if (op2.maybe_isnan ())
bdf00185 1664 r.set_varying (type);
10bd26d6
AH
1665 else if (op2.undefined_p ())
1666 return false;
bdf00185
AH
1667 else
1668 build_lt (r, type, op2);
2e158eae
AH
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 ();
10bd26d6
AH
1676 else if (op2.undefined_p ())
1677 return false;
2e158eae
AH
1678 else if (build_ge (r, type, 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, type))
1695 {
1696 case BRS_TRUE:
36eec799 1697 if (op1.maybe_isnan ())
bdf00185 1698 r.set_varying (type);
10bd26d6
AH
1699 else if (op1.undefined_p ())
1700 return false;
bdf00185
AH
1701 else
1702 build_gt (r, type, op1);
2e158eae
AH
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 ();
10bd26d6
AH
1710 else if (op1.undefined_p ())
1711 return false;
2e158eae
AH
1712 else if (build_le (r, type, op1))
1713 r.clear_nan ();
1714 break;
1715
1716 default:
1717 break;
1718 }
1719 return true;
1720}
1721
9c0fed50 1722class foperator_unordered_le : public range_operator
24012539 1723{
9c0fed50
AM
1724 using range_operator::fold_range;
1725 using range_operator::op1_range;
1726 using range_operator::op2_range;
4cbc312a
AH
1727public:
1728 bool fold_range (irange &r, tree type,
1729 const frange &op1, const frange &op2,
66be6ed8 1730 relation_trio trio = TRIO_VARYING) const final override
4cbc312a 1731 {
0bd96163 1732 if (op1.known_isnan () || op2.known_isnan ())
4cbc312a
AH
1733 {
1734 r = range_true (type);
1735 return true;
1736 }
e02c9d91
JJ
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 ();
d251d14c 1743 if (!range_op_handler (LE_EXPR).fold_range (r, type, op1_no_nan,
66be6ed8 1744 op2_no_nan, trio))
4cbc312a
AH
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.
be43d5d3 1748 if (!maybe_isnan (op1, op2) || r == range_true (type))
4cbc312a
AH
1749 return true;
1750 else
1751 {
1752 r = range_true_and_false (type);
1753 return true;
1754 }
1755 }
fe7371e7
AH
1756 bool op1_range (frange &r, tree type,
1757 const irange &lhs, const frange &op2,
b565ac19 1758 relation_trio = TRIO_VARYING) const final override;
fe7371e7
AH
1759 bool op2_range (frange &r, tree type,
1760 const irange &lhs, const frange &op1,
b565ac19 1761 relation_trio = TRIO_VARYING) const final override;
4cbc312a 1762} fop_unordered_le;
24012539 1763
fe7371e7
AH
1764bool
1765foperator_unordered_le::op1_range (frange &r, tree type,
1766 const irange &lhs, const frange &op2,
b565ac19 1767 relation_trio) const
fe7371e7
AH
1768{
1769 switch (get_bool_state (r, lhs, type))
1770 {
1771 case BRS_TRUE:
36eec799 1772 if (op2.maybe_isnan ())
bdf00185 1773 r.set_varying (type);
10bd26d6
AH
1774 else if (op2.undefined_p ())
1775 return false;
bdf00185
AH
1776 else
1777 build_le (r, type, op2);
fe7371e7
AH
1778 break;
1779
1780 case BRS_FALSE:
3dfdc0d1
AH
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, op2))
f0068278 1786 r.clear_nan ();
fe7371e7
AH
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,
b565ac19 1800 relation_trio) const
fe7371e7
AH
1801{
1802 switch (get_bool_state (r, lhs, type))
1803 {
1804 case BRS_TRUE:
36eec799 1805 if (op1.maybe_isnan ())
bdf00185 1806 r.set_varying (type);
10bd26d6
AH
1807 else if (op1.undefined_p ())
1808 return false;
bdf00185
AH
1809 else
1810 build_ge (r, type, op1);
fe7371e7
AH
1811 break;
1812
1813 case BRS_FALSE:
3dfdc0d1
AH
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 ();
10bd26d6
AH
1818 else if (op1.undefined_p ())
1819 return false;
3dfdc0d1 1820 else if (build_lt (r, type, op1))
f0068278 1821 r.clear_nan ();
fe7371e7
AH
1822 break;
1823
1824 default:
1825 break;
1826 }
1827 return true;
1828}
1829
9c0fed50 1830class foperator_unordered_gt : public range_operator
4cbc312a 1831{
9c0fed50
AM
1832 using range_operator::fold_range;
1833 using range_operator::op1_range;
1834 using range_operator::op2_range;
24012539
AH
1835public:
1836 bool fold_range (irange &r, tree type,
d2278da1 1837 const frange &op1, const frange &op2,
66be6ed8 1838 relation_trio trio = TRIO_VARYING) const final override
24012539 1839 {
0bd96163 1840 if (op1.known_isnan () || op2.known_isnan ())
4cbc312a
AH
1841 {
1842 r = range_true (type);
1843 return true;
1844 }
e02c9d91
JJ
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 ();
f544e7e8 1851 if (!range_op_handler (GT_EXPR).fold_range (r, type, op1_no_nan,
66be6ed8 1852 op2_no_nan, trio))
4cbc312a
AH
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.
be43d5d3 1856 if (!maybe_isnan (op1, op2) || r == range_true (type))
4cbc312a 1857 return true;
d2278da1 1858 else
4cbc312a
AH
1859 {
1860 r = range_true_and_false (type);
1861 return true;
1862 }
1863 }
fe7371e7
AH
1864 bool op1_range (frange &r, tree type,
1865 const irange &lhs, const frange &op2,
b565ac19 1866 relation_trio = TRIO_VARYING) const final override;
fe7371e7
AH
1867 bool op2_range (frange &r, tree type,
1868 const irange &lhs, const frange &op1,
b565ac19 1869 relation_trio = TRIO_VARYING) const final override;
4cbc312a
AH
1870} fop_unordered_gt;
1871
fe7371e7
AH
1872bool
1873foperator_unordered_gt::op1_range (frange &r,
1874 tree type,
1875 const irange &lhs,
1876 const frange &op2,
b565ac19 1877 relation_trio) const
fe7371e7
AH
1878{
1879 switch (get_bool_state (r, lhs, type))
1880 {
1881 case BRS_TRUE:
36eec799 1882 if (op2.maybe_isnan ())
bdf00185 1883 r.set_varying (type);
10bd26d6
AH
1884 else if (op2.undefined_p ())
1885 return false;
bdf00185
AH
1886 else
1887 build_gt (r, type, op2);
fe7371e7
AH
1888 break;
1889
1890 case BRS_FALSE:
3dfdc0d1
AH
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 ();
10bd26d6
AH
1895 else if (op2.undefined_p ())
1896 return false;
3dfdc0d1 1897 else if (build_le (r, type, op2))
f0068278 1898 r.clear_nan ();
fe7371e7
AH
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,
b565ac19 1912 relation_trio) const
fe7371e7
AH
1913{
1914 switch (get_bool_state (r, lhs, type))
1915 {
1916 case BRS_TRUE:
36eec799 1917 if (op1.maybe_isnan ())
bdf00185 1918 r.set_varying (type);
10bd26d6
AH
1919 else if (op1.undefined_p ())
1920 return false;
bdf00185
AH
1921 else
1922 build_lt (r, type, op1);
fe7371e7
AH
1923 break;
1924
1925 case BRS_FALSE:
3dfdc0d1
AH
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 ();
10bd26d6
AH
1930 else if (op1.undefined_p ())
1931 return false;
3dfdc0d1 1932 else if (build_ge (r, type, op1))
f0068278 1933 r.clear_nan ();
fe7371e7
AH
1934 break;
1935
1936 default:
1937 break;
1938 }
1939 return true;
1940}
1941
9c0fed50 1942class foperator_unordered_ge : public range_operator
4cbc312a 1943{
9c0fed50
AM
1944 using range_operator::fold_range;
1945 using range_operator::op1_range;
1946 using range_operator::op2_range;
4cbc312a
AH
1947public:
1948 bool fold_range (irange &r, tree type,
1949 const frange &op1, const frange &op2,
66be6ed8 1950 relation_trio trio = TRIO_VARYING) const final override
4cbc312a 1951 {
0bd96163 1952 if (op1.known_isnan () || op2.known_isnan ())
4cbc312a
AH
1953 {
1954 r = range_true (type);
1955 return true;
1956 }
e02c9d91
JJ
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 ();
a0a8f1c7 1963 if (!range_op_handler (GE_EXPR).fold_range (r, type, op1_no_nan,
66be6ed8 1964 op2_no_nan, trio))
4cbc312a
AH
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.
be43d5d3 1968 if (!maybe_isnan (op1, op2) || r == range_true (type))
4cbc312a
AH
1969 return true;
1970 else
1971 {
1972 r = range_true_and_false (type);
1973 return true;
1974 }
1975 }
fe7371e7
AH
1976 bool op1_range (frange &r, tree type,
1977 const irange &lhs, const frange &op2,
b565ac19 1978 relation_trio = TRIO_VARYING) const final override;
fe7371e7
AH
1979 bool op2_range (frange &r, tree type,
1980 const irange &lhs, const frange &op1,
b565ac19 1981 relation_trio = TRIO_VARYING) const final override;
4cbc312a
AH
1982} fop_unordered_ge;
1983
fe7371e7
AH
1984bool
1985foperator_unordered_ge::op1_range (frange &r,
1986 tree type,
1987 const irange &lhs,
1988 const frange &op2,
b565ac19 1989 relation_trio) const
fe7371e7
AH
1990{
1991 switch (get_bool_state (r, lhs, type))
1992 {
1993 case BRS_TRUE:
36eec799 1994 if (op2.maybe_isnan ())
bdf00185 1995 r.set_varying (type);
10bd26d6
AH
1996 else if (op2.undefined_p ())
1997 return false;
bdf00185
AH
1998 else
1999 build_ge (r, type, op2);
fe7371e7
AH
2000 break;
2001
2002 case BRS_FALSE:
3dfdc0d1
AH
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 ();
10bd26d6
AH
2007 else if (op2.undefined_p ())
2008 return false;
3dfdc0d1 2009 else if (build_lt (r, type, op2))
f0068278 2010 r.clear_nan ();
fe7371e7
AH
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,
b565ac19 2023 relation_trio) const
fe7371e7
AH
2024{
2025 switch (get_bool_state (r, lhs, type))
2026 {
2027 case BRS_TRUE:
36eec799 2028 if (op1.maybe_isnan ())
bdf00185 2029 r.set_varying (type);
10bd26d6
AH
2030 else if (op1.undefined_p ())
2031 return false;
bdf00185
AH
2032 else
2033 build_le (r, type, op1);
fe7371e7
AH
2034 break;
2035
2036 case BRS_FALSE:
3dfdc0d1
AH
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 ();
10bd26d6
AH
2041 else if (op1.undefined_p ())
2042 return false;
3dfdc0d1 2043 else if (build_gt (r, type, op1))
f0068278 2044 r.clear_nan ();
fe7371e7
AH
2045 break;
2046
2047 default:
2048 break;
2049 }
2050 return true;
2051}
2052
9c0fed50 2053class foperator_unordered_equal : public range_operator
4cbc312a 2054{
9c0fed50
AM
2055 using range_operator::fold_range;
2056 using range_operator::op1_range;
2057 using range_operator::op2_range;
4cbc312a
AH
2058public:
2059 bool fold_range (irange &r, tree type,
2060 const frange &op1, const frange &op2,
66be6ed8 2061 relation_trio trio = TRIO_VARYING) const final override
4cbc312a 2062 {
7a4e57ff 2063 if (op1.known_isnan () || op2.known_isnan ())
4cbc312a
AH
2064 {
2065 r = range_true (type);
2066 return true;
2067 }
e02c9d91
JJ
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 ();
2dbf1e61 2074 if (!range_op_handler (EQ_EXPR).fold_range (r, type, op1_no_nan,
66be6ed8 2075 op2_no_nan, trio))
4cbc312a
AH
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.
be43d5d3 2079 if (!maybe_isnan (op1, op2) || r == range_true (type))
4cbc312a
AH
2080 return true;
2081 else
2082 {
2083 r = range_true_and_false (type);
2084 return true;
2085 }
24012539 2086 }
fe7371e7
AH
2087 bool op1_range (frange &r, tree type,
2088 const irange &lhs, const frange &op2,
b565ac19 2089 relation_trio = TRIO_VARYING) const final override;
fe7371e7
AH
2090 bool op2_range (frange &r, tree type,
2091 const irange &lhs, const frange &op1,
b565ac19 2092 relation_trio rel = TRIO_VARYING) const final override
fe7371e7 2093 {
b565ac19 2094 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
fe7371e7 2095 }
4cbc312a 2096} fop_unordered_equal;
24012539 2097
fe7371e7
AH
2098bool
2099foperator_unordered_equal::op1_range (frange &r, tree type,
2100 const irange &lhs,
2101 const frange &op2,
b565ac19 2102 relation_trio) const
fe7371e7
AH
2103{
2104 switch (get_bool_state (r, lhs, 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);
c46b5b0a 2111 // Add the possibility of a NAN.
fe7371e7
AH
2112 r.update_nan ();
2113 break;
2114
2115 case BRS_FALSE:
3dfdc0d1
AH
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 {
c46b5b0a 2122 // The false side indicates !NAN and not equal. We can at least
3dfdc0d1
AH
2123 // represent !NAN.
2124 r.set_varying (type);
2125 r.clear_nan ();
2126 }
fe7371e7
AH
2127 break;
2128
2129 default:
2130 break;
2131 }
2132 return true;
2133}
a6efab5f 2134
9c0fed50 2135class foperator_ltgt : public range_operator
5fe05ffe 2136{
9c0fed50
AM
2137 using range_operator::fold_range;
2138 using range_operator::op1_range;
2139 using range_operator::op2_range;
5fe05ffe
JJ
2140public:
2141 bool fold_range (irange &r, tree type,
2142 const frange &op1, const frange &op2,
979e0fbf 2143 relation_trio trio = TRIO_VARYING) const final override
5fe05ffe
JJ
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 ();
eb29c3e1 2156 if (!range_op_handler (NE_EXPR).fold_range (r, type, op1_no_nan,
979e0fbf 2157 op2_no_nan, trio))
5fe05ffe
JJ
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, 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, 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
d4c2f1d3
JJ
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,
a0ee2e52 2222 const frange &lhs, bool div_op2 = false)
d4c2f1d3
JJ
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.
7c6cd9c0 2232 // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
d4c2f1d3 2233 // Or if lhs is a known NAN, we also don't know anything.
7c6cd9c0 2234 if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
d4c2f1d3
JJ
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 ())
a0ee2e52
JJ
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 }
d4c2f1d3
JJ
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
5747470e
JJ
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, 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)
19cb965e 2313 lb = dconstm0;
5747470e
JJ
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;
19cb965e 2347 ub = dconstm0;
5747470e
JJ
2348 }
2349 else
2350 {
2351 lb = dconstninf;
2352 ub = dconstinf;
2353 }
2354}
2355
bad177e8
JJ
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.
44f80a37
JJ
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. */
bad177e8
JJ
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))
a1d5c729
JJ
2374 {
2375 frange_nextafter (TYPE_MODE (type), lb, 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 }
44f80a37
JJ
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 }
a1d5c729 2395 }
bad177e8 2396 if (real_isfinite (&ub))
a1d5c729
JJ
2397 {
2398 frange_nextafter (TYPE_MODE (type), ub, 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 }
44f80a37
JJ
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 }
a1d5c729
JJ
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;
ccaee0d2 2419 ret.set (type, lb, ub, lhs.get_nan_state ());
a1d5c729 2420 flag_finite_math_only = save_flag_finite_math_only;
bad177e8
JJ
2421 return ret;
2422}
2423
29dbd7ef
AM
2424bool
2425operator_plus::op1_range (frange &r, tree type, const frange &lhs,
2426 const frange &op2, relation_trio) const
9d96a286 2427{
29dbd7ef
AM
2428 if (lhs.undefined_p ())
2429 return false;
2eb50117 2430 range_op_handler minus (MINUS_EXPR);
29dbd7ef
AM
2431 if (!minus)
2432 return false;
2433 frange wlhs = float_widen_lhs_range (type, lhs);
2434 return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
2435 r, type, wlhs);
2436}
0ef5649e 2437
29dbd7ef
AM
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, op1);
2444}
2445
2446void
24e97ac4 2447operator_plus::rv_fold (frange &r, tree type,
29dbd7ef
AM
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{
848b5f3a
AH
2454 REAL_VALUE_TYPE lb, ub;
2455 bool maybe_nan = false;
2456
29dbd7ef
AM
2457 frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
2458 frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
2459
2460 // [-INF] + [+INF] = NAN
2461 if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
2462 maybe_nan = true;
2463 // [+INF] + [-INF] = NAN
2464 else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
2465 maybe_nan = true;
24e97ac4
AH
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));
29dbd7ef 2481}
9d96a286 2482
9d96a286 2483
d5818a36
AM
2484bool
2485operator_minus::op1_range (frange &r, tree type,
2486 const frange &lhs, const frange &op2,
2487 relation_trio) const
38ec5e4b 2488{
d5818a36
AM
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 range_op_handler (PLUS_EXPR).fold_range (r, type, wlhs, op2),
2494 r, type, wlhs);
2495}
38ec5e4b 2496
d5818a36
AM
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 (fold_range (r, type, op1, wlhs),
2506 r, type, wlhs);
2507}
2508
2509void
24e97ac4 2510operator_minus::rv_fold (frange &r, tree type,
d5818a36
AM
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{
848b5f3a
AH
2517 REAL_VALUE_TYPE lb, ub;
2518 bool maybe_nan = false;
2519
d5818a36
AM
2520 frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
2521 frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
2522
2523 // [+INF] - [+INF] = NAN
2524 if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
2525 maybe_nan = true;
2526 // [-INF] - [-INF] = NAN
2527 else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
2528 maybe_nan = true;
24e97ac4
AH
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));
d5818a36 2544}
38ec5e4b 2545
2f7f9edd 2546
a13c4440
AM
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}
5747470e
JJ
2568
2569
a13c4440
AM
2570bool
2571operator_mult::op1_range (frange &r, tree type,
2572 const frange &lhs, const frange &op2,
2573 relation_trio) const
2f7f9edd 2574{
a13c4440
AM
2575 if (lhs.undefined_p ())
2576 return false;
2eb50117 2577 range_op_handler rdiv (RDIV_EXPR);
a13c4440
AM
2578 if (!rdiv)
2579 return false;
2580 frange wlhs = float_widen_lhs_range (type, lhs);
2581 bool ret = rdiv.fold_range (r, type, wlhs, op2);
2582 if (ret == false)
2583 return false;
2584 if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
bad177e8 2585 return float_binary_op_range_finish (ret, r, type, wlhs);
a13c4440
AM
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 (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, 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 (lhs_lb, lhs_ub, op2_lb, 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, wlhs);
2607}
2f7f9edd 2608
a13c4440
AM
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, op1);
2615}
2f7f9edd 2616
a13c4440 2617void
24e97ac4 2618operator_mult::rv_fold (frange &r, tree type,
a13c4440
AM
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));
848b5f3a
AH
2631 REAL_VALUE_TYPE lb, ub;
2632 bool maybe_nan = false;
a13c4440
AM
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 (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
2639 || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
2640 {
24e97ac4 2641 r.set_nan (type);
a13c4440
AM
2642 return;
2643 }
2f7f9edd 2644
a13c4440
AM
2645 // Otherwise, if one range includes zero and the other ends with +-INF,
2646 // it is a maybe NAN.
2647 if ((contains_zero_p (lh_lb, lh_ub)
2648 && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2649 || (contains_zero_p (rh_lb, 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 (lh_lb, lh_ub)
2662 || singleton_inf_p (rh_lb, rh_ub))
24e97ac4
AH
2663 {
2664 inf_range (lb, ub, signbit_known);
2665 r.set (type, lb, ub, nan_state (true));
2666 return;
2667 }
a13c4440
AM
2668
2669 // If one of the multiplicands must be zero, the resulting
2670 // range is +-0 and NAN.
2671 if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
24e97ac4
AH
2672 {
2673 zero_range (lb, ub, signbit_known);
2674 r.set (type, lb, ub, nan_state (true));
2675 return;
2676 }
a13c4440
AM
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.
24e97ac4
AH
2684 zero_to_inf_range (lb, ub, signbit_known);
2685 r.set (type, lb, ub, nan_state (true));
2686 return;
a13c4440
AM
2687 }
2688 }
2f7f9edd 2689
a13c4440
AM
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 (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2694 frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, 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 (lh_lb, 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 (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2718 frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2719 frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2720 frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2721 }
2722 frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2723 frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
5747470e 2724
a13c4440 2725 find_range (lb, ub, cp);
24e97ac4
AH
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));
a13c4440
AM
2730}
2731
2732
2733class foperator_div : public range_operator
2d5c4a16 2734{
9c0fed50
AM
2735 using range_operator::op1_range;
2736 using range_operator::op2_range;
d4c2f1d3
JJ
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;
bad177e8 2745 frange wlhs = float_widen_lhs_range (type, lhs);
a13c4440 2746 bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
4500baac
JJ
2747 if (!ret)
2748 return ret;
bad177e8
JJ
2749 if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2750 return float_binary_op_range_finish (ret, r, type, wlhs);
2751 const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2752 const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
4500baac
JJ
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 (lhs_lb, lhs_ub)
2756 && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
2757 || ((contains_zero_p (op2_lb, 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 (lhs_lb, lhs_ub, op2_lb, op2_ub);
2765 zero_to_inf_range (lb, ub, signbit_known);
2766 r.set (type, lb, ub);
2767 }
bad177e8 2768 return float_binary_op_range_finish (ret, r, type, wlhs);
d4c2f1d3
JJ
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;
bad177e8
JJ
2777 frange wlhs = float_widen_lhs_range (type, lhs);
2778 bool ret = fold_range (r, type, op1, wlhs);
4500baac
JJ
2779 if (!ret)
2780 return ret;
bad177e8
JJ
2781 if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
2782 return float_binary_op_range_finish (ret, r, type, wlhs, true);
2783 const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2784 const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
4500baac
JJ
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 (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, 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 (lhs_lb, lhs_ub, op1_lb, op1_ub);
2796 zero_to_inf_range (lb, ub, signbit_known);
2797 r.set (type, lb, ub);
2798 }
bad177e8 2799 return float_binary_op_range_finish (ret, r, type, wlhs, true);
d4c2f1d3
JJ
2800 }
2801private:
24e97ac4 2802 void rv_fold (frange &r, tree type,
2d5c4a16
JJ
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.
5747470e 2810 if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
4500baac 2811 || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
2d5c4a16 2812 {
24e97ac4 2813 r.set_nan (type);
2d5c4a16
JJ
2814 return;
2815 }
2816
848b5f3a
AH
2817 REAL_VALUE_TYPE lb, ub;
2818 bool maybe_nan = false;
2d5c4a16 2819 // If +-0.0 is in both ranges, it is a maybe NAN.
5747470e
JJ
2820 if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
2821 maybe_nan = true;
2d5c4a16
JJ
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)))
5747470e 2825 maybe_nan = true;
2d5c4a16 2826
5747470e 2827 int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2d5c4a16
JJ
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).
5747470e 2833 if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
24e97ac4
AH
2834 {
2835 zero_range (lb, ub, signbit_known);
2836 r.set (type, lb, ub, nan_state (maybe_nan));
2837 return;
2838 }
2d5c4a16
JJ
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).
5747470e 2844 if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
24e97ac4
AH
2845 {
2846 inf_range (lb, ub, signbit_known);
2847 r.set (type, lb, ub, nan_state (maybe_nan));
2848 return;
2849 }
2d5c4a16
JJ
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
c46b5b0a 2857 // [-INF, -0.0]. If they vary, VARYING.
2d5c4a16
JJ
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.
5747470e 2864 if (maybe_nan)
24e97ac4
AH
2865 {
2866 zero_to_inf_range (lb, ub, signbit_known);
2867 r.set (type, lb, ub, nan_state (maybe_nan));
2868 return;
2869 }
2d5c4a16
JJ
2870
2871 REAL_VALUE_TYPE cp[8];
2872 // Do a cross-division. At this point none of the divisions should
2873 // produce a NAN.
2d5c4a16
JJ
2874 frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2875 frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2876 frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2877 frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2878 frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2879 frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2880 frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2881 frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2882
5747470e 2883 find_range (lb, ub, cp);
2d5c4a16
JJ
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.
5747470e 2888 if (contains_zero_p (rh_lb, rh_ub))
2d5c4a16 2889 {
5747470e 2890 if (signbit_known <= 0)
2d5c4a16 2891 real_inf (&lb, true);
5747470e 2892 if (signbit_known >= 0)
2d5c4a16
JJ
2893 real_inf (&ub, false);
2894 }
24e97ac4
AH
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));
2d5c4a16
JJ
2899 }
2900} fop_div;
2901
a6efab5f 2902
a13c4440 2903// Initialize any float operators to the primary table
07767389
AM
2904
2905void
2906range_op_table::initialize_float_ops ()
2907{
4cbc312a
AH
2908 set (UNLE_EXPR, fop_unordered_le);
2909 set (UNLT_EXPR, fop_unordered_lt);
2910 set (UNGE_EXPR, fop_unordered_ge);
2911 set (UNGT_EXPR, fop_unordered_gt);
2912 set (UNEQ_EXPR, fop_unordered_equal);
24012539
AH
2913 set (ORDERED_EXPR, fop_ordered);
2914 set (UNORDERED_EXPR, fop_unordered);
5fe05ffe 2915 set (LTGT_EXPR, fop_ltgt);
2d5c4a16 2916 set (RDIV_EXPR, fop_div);
a6efab5f
AH
2917}
2918
1c0670c6
AH
2919#if CHECKING_P
2920#include "selftest.h"
2921
2922namespace selftest
2923{
2924
2925// Build an frange from string endpoints.
2926
d438b67e 2927static inline frange
1c0670c6
AH
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{
a0c1a059
AH
2939 frange r, r0, r1;
2940 frange trange (float_type_node);
2941
2942 // negate([-5, +10]) => [-10, 5]
2943 r0 = frange_float ("-5", "10");
56518bef 2944 range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
a0c1a059
AH
2945 ASSERT_EQ (r, frange_float ("-10", "5"));
2946
2947 // negate([0, 1] -NAN) => [-1, -0] +NAN
2948 r0 = frange_float ("0", "1");
2949 r0.update_nan (true);
56518bef 2950 range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
a0c1a059
AH
2951 r1 = frange_float ("-1", "-0");
2952 r1.update_nan (false);
2953 ASSERT_EQ (r, r1);
68b0615b
AH
2954
2955 // [-INF,+INF] + [-INF,+INF] could be a NAN.
2eb50117 2956 range_op_handler plus (PLUS_EXPR);
68b0615b
AH
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, r0, r1);
2962 if (HONOR_NANS (float_type_node))
2963 ASSERT_TRUE (r.maybe_isnan ());
1c0670c6
AH
2964}
2965
2966} // namespace selftest
2967
2968#endif // CHECKING_P