Line data Source code
1 : /* Floating point range operators.
2 : Copyright (C) 2022-2026 Free Software Foundation, Inc.
3 : Contributed by Aldy Hernandez <aldyh@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "backend.h"
25 : #include "insn-codes.h"
26 : #include "rtl.h"
27 : #include "tree.h"
28 : #include "gimple.h"
29 : #include "cfghooks.h"
30 : #include "tree-pass.h"
31 : #include "ssa.h"
32 : #include "optabs-tree.h"
33 : #include "gimple-pretty-print.h"
34 : #include "diagnostic-core.h"
35 : #include "flags.h"
36 : #include "fold-const.h"
37 : #include "stor-layout.h"
38 : #include "calls.h"
39 : #include "cfganal.h"
40 : #include "gimple-iterator.h"
41 : #include "gimple-fold.h"
42 : #include "tree-eh.h"
43 : #include "gimple-walk.h"
44 : #include "tree-cfg.h"
45 : #include "wide-int.h"
46 : #include "value-relation.h"
47 : #include "range-op.h"
48 : #include "range-op-mixed.h"
49 :
50 : // Default definitions for floating point operators.
51 :
52 : bool
53 5831965 : range_operator::fold_range (frange &r, tree type,
54 : const frange &op1, const frange &op2,
55 : relation_trio trio) const
56 : {
57 5831965 : if (empty_range_varying (r, type, op1, op2))
58 6396 : return true;
59 5825569 : if (op1.known_isnan () || op2.known_isnan ())
60 : {
61 7483 : r.set_nan (type);
62 7483 : return true;
63 : }
64 :
65 5818086 : rv_fold (r, type,
66 : op1.lower_bound (), op1.upper_bound (),
67 : op2.lower_bound (), op2.upper_bound (), trio.op1_op2 ());
68 :
69 5818086 : if (r.known_isnan ())
70 : return true;
71 9542281 : if (op1.maybe_isnan () || op2.maybe_isnan ())
72 4129948 : r.update_nan ();
73 :
74 : // If the result has overflowed and flag_trapping_math, folding this
75 : // operation could elide an overflow or division by zero exception.
76 : // Avoid returning a singleton +-INF, to keep the propagators (DOM
77 : // and substitute_and_fold_engine) from folding. See PR107608.
78 5817464 : if (flag_trapping_math
79 27337351 : && MODE_HAS_INFINITIES (TYPE_MODE (type))
80 11197838 : && r.known_isinf () && !op1.known_isinf () && !op2.known_isinf ())
81 : {
82 1609 : REAL_VALUE_TYPE inf = r.lower_bound ();
83 1609 : if (real_isneg (&inf))
84 : {
85 96 : REAL_VALUE_TYPE min = real_min_representable (type);
86 96 : r.set (type, inf, min);
87 : }
88 : else
89 : {
90 1513 : REAL_VALUE_TYPE max = real_max_representable (type);
91 1513 : r.set (type, max, inf);
92 : }
93 : }
94 :
95 5817464 : r.flush_denormals_to_zero ();
96 :
97 5817464 : return true;
98 : }
99 :
100 : // For a given operation, fold two sets of ranges into [lb, ub].
101 : // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
102 : // UB, the final range has the possibility of a NAN.
103 : void
104 504478 : range_operator::rv_fold (frange &r, tree type,
105 : const REAL_VALUE_TYPE &,
106 : const REAL_VALUE_TYPE &,
107 : const REAL_VALUE_TYPE &,
108 : const REAL_VALUE_TYPE &, relation_kind) const
109 : {
110 504478 : r.set (type, dconstninf, dconstinf, nan_state (true));
111 504478 : }
112 :
113 : bool
114 101807 : range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
115 : tree type ATTRIBUTE_UNUSED,
116 : const frange &lh ATTRIBUTE_UNUSED,
117 : const irange &rh ATTRIBUTE_UNUSED,
118 : relation_trio) const
119 : {
120 101807 : return false;
121 : }
122 :
123 : bool
124 0 : range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
125 : tree type ATTRIBUTE_UNUSED,
126 : const frange &lh ATTRIBUTE_UNUSED,
127 : const frange &rh ATTRIBUTE_UNUSED,
128 : relation_trio) const
129 : {
130 0 : return false;
131 : }
132 :
133 : bool
134 0 : range_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 0 : return false;
141 : }
142 :
143 : bool
144 676 : range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
145 : tree type ATTRIBUTE_UNUSED,
146 : const frange &lhs ATTRIBUTE_UNUSED,
147 : const frange &op2 ATTRIBUTE_UNUSED,
148 : relation_trio) const
149 : {
150 676 : return false;
151 : }
152 :
153 : bool
154 6068 : range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
155 : tree type ATTRIBUTE_UNUSED,
156 : const irange &lhs ATTRIBUTE_UNUSED,
157 : const frange &op2 ATTRIBUTE_UNUSED,
158 : relation_trio) const
159 : {
160 6068 : return false;
161 : }
162 :
163 : bool
164 2407 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
165 : tree type ATTRIBUTE_UNUSED,
166 : const frange &lhs ATTRIBUTE_UNUSED,
167 : const frange &op1 ATTRIBUTE_UNUSED,
168 : relation_trio) const
169 : {
170 2407 : return false;
171 : }
172 :
173 : bool
174 0 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
175 : tree type ATTRIBUTE_UNUSED,
176 : const irange &lhs ATTRIBUTE_UNUSED,
177 : const frange &op1 ATTRIBUTE_UNUSED,
178 : relation_trio) const
179 : {
180 0 : return false;
181 : }
182 :
183 : relation_kind
184 5786196 : range_operator::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
185 : const frange &op1 ATTRIBUTE_UNUSED,
186 : const frange &op2 ATTRIBUTE_UNUSED,
187 : relation_kind) const
188 : {
189 5786196 : return VREL_VARYING;
190 : }
191 :
192 : relation_kind
193 1032708 : range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
194 : const frange &op1 ATTRIBUTE_UNUSED,
195 : const frange &op2 ATTRIBUTE_UNUSED,
196 : relation_kind) const
197 : {
198 1032708 : return VREL_VARYING;
199 : }
200 :
201 : relation_kind
202 169745 : range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
203 : const frange &op1 ATTRIBUTE_UNUSED,
204 : const frange &op2 ATTRIBUTE_UNUSED,
205 : relation_kind) const
206 : {
207 169745 : return VREL_VARYING;
208 : }
209 :
210 : relation_kind
211 3632923 : range_operator::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
212 : const frange &op1 ATTRIBUTE_UNUSED,
213 : const frange &op2 ATTRIBUTE_UNUSED,
214 : relation_kind) const
215 : {
216 3632923 : return VREL_VARYING;
217 : }
218 :
219 : relation_kind
220 353277 : range_operator::op1_op2_relation (const irange &,
221 : const frange &,
222 : const frange &) const
223 : {
224 353277 : return VREL_VARYING;
225 : }
226 :
227 :
228 : relation_kind
229 656035 : range_operator::op1_op2_relation (const frange &,
230 : const frange &,
231 : const frange &) const
232 : {
233 656035 : return VREL_VARYING;
234 : }
235 :
236 : // Return TRUE if OP1 and OP2 may be a NAN.
237 :
238 : static inline bool
239 3624237 : maybe_isnan (const frange &op1, const frange &op2)
240 : {
241 6321354 : return op1.maybe_isnan () || op2.maybe_isnan ();
242 : }
243 :
244 : // Floating point version of relop_early_resolve that takes NANs into
245 : // account.
246 : //
247 : // For relation opcodes, first try to see if the supplied relation
248 : // forces a true or false result, and return that.
249 : // Then check for undefined operands. If none of this applies,
250 : // return false.
251 : //
252 : // TRIO are the relations between operands as they appear in the IL.
253 : // MY_REL is the relation that corresponds to the operator being
254 : // folded. For example, when attempting to fold x_3 == y_5, MY_REL is
255 : // VREL_EQ, and if the statement is dominated by x_3 > y_5, then
256 : // TRIO.op1_op2() is VREL_GT.
257 :
258 : static inline bool
259 2097308 : frelop_early_resolve (irange &r, tree type,
260 : const frange &op1, const frange &op2,
261 : relation_trio trio, relation_kind my_rel)
262 : {
263 2097308 : relation_kind rel = trio.op1_op2 ();
264 :
265 : // If known relation is a complete subset of this relation, always
266 : // return true. However, avoid doing this when NAN is a possibility
267 : // as we'll incorrectly fold conditions:
268 : //
269 : // if (x_3 >= y_5)
270 : // ;
271 : // else
272 : // ;; With NANs the relation here is basically VREL_UNLT, so we
273 : // ;; can't fold the following:
274 : // if (x_3 < y_5)
275 2097308 : if (!maybe_isnan (op1, op2) && relation_union (rel, my_rel) == my_rel)
276 : {
277 1946 : r = range_true (type);
278 1946 : return true;
279 : }
280 :
281 : // If known relation has no subset of this relation, always false.
282 2095362 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
283 : {
284 1086 : r = range_false (type);
285 1086 : return true;
286 : }
287 :
288 : // If either operand is undefined, return VARYING.
289 2094276 : if (empty_range_varying (r, type, op1, op2))
290 2448 : return true;
291 :
292 : return false;
293 : }
294 :
295 : // Set VALUE to its next real value, or INF if the operation overflows.
296 :
297 : void
298 3925054 : frange_nextafter (enum machine_mode mode,
299 : REAL_VALUE_TYPE &value,
300 : const REAL_VALUE_TYPE &inf)
301 : {
302 27475378 : if (MODE_COMPOSITE_P (mode)
303 0 : && (real_isdenormal (&value, mode) || real_iszero (&value)))
304 : {
305 : // IBM extended denormals only have DFmode precision.
306 0 : REAL_VALUE_TYPE tmp, tmp2;
307 0 : real_convert (&tmp2, DFmode, &value);
308 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
309 0 : real_convert (&value, mode, &tmp);
310 : }
311 : else
312 : {
313 3925054 : REAL_VALUE_TYPE tmp;
314 3925054 : real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
315 3925054 : value = tmp;
316 : }
317 3925054 : }
318 :
319 : // Like real_arithmetic, but round the result to INF if the operation
320 : // produced inexact results.
321 : //
322 : // ?? There is still one problematic case, i387. With
323 : // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
324 : // XFmode (long_double_type_node), so that case is OK. But without
325 : // -mfpmath=sse, all the SF/DFmode computations are in XFmode
326 : // precision (64-bit mantissa) and only occasionally rounded to
327 : // SF/DFmode (when storing into memory from the 387 stack). Maybe
328 : // this is ok as well though it is just occasionally more precise. ??
329 :
330 : void
331 15775210 : frange_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 15775210 : REAL_VALUE_TYPE value;
338 15775210 : enum machine_mode mode = TYPE_MODE (type);
339 110426470 : bool mode_composite = MODE_COMPOSITE_P (mode);
340 :
341 15775210 : bool inexact = real_arithmetic (&value, code, &op1, &op2);
342 15775210 : real_convert (&result, mode, &value);
343 :
344 : /* When rounding towards negative infinity, x + (-x) and
345 : x - x is -0 rather than +0 real_arithmetic computes.
346 : So, when we are looking for lower bound (inf is negative),
347 : use -0 rather than +0. */
348 15775210 : if (flag_rounding_math
349 16568 : && (code == PLUS_EXPR || code == MINUS_EXPR)
350 4868 : && !inexact
351 4868 : && real_iszero (&result)
352 66 : && !real_isneg (&result)
353 15775276 : && real_isneg (&inf))
354 : {
355 36 : REAL_VALUE_TYPE op2a = op2;
356 36 : if (code == PLUS_EXPR)
357 30 : op2a.sign ^= 1;
358 36 : if (real_isneg (&op1) == real_isneg (&op2a) && real_equal (&op1, &op2a))
359 36 : result.sign = 1;
360 : }
361 :
362 : // Be extra careful if there may be discrepancies between the
363 : // compile and runtime results.
364 15775210 : bool round = false;
365 15775210 : if (mode_composite)
366 : round = true;
367 : else
368 : {
369 15775210 : bool low = real_isneg (&inf);
370 15775210 : round = (low ? !real_less (&result, &value)
371 7887682 : : !real_less (&value, &result));
372 15775210 : if (real_isinf (&result, !low)
373 1544689 : && !real_isinf (&value)
374 16167497 : && !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 390386 : if (!inexact)
384 : round = false;
385 : else
386 : {
387 56702 : REAL_VALUE_TYPE tmp = result, tmp2;
388 56702 : frange_nextafter (mode, tmp, inf);
389 : // TMP is at this point the maximum representable
390 : // number.
391 56702 : real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp);
392 56702 : if (real_isneg (&tmp2) != low
393 56702 : && (REAL_EXP (&tmp2) - REAL_EXP (&tmp)
394 56702 : >= 2 - REAL_MODE_FORMAT (mode)->p))
395 56701 : round = false;
396 : }
397 : }
398 : }
399 15441526 : if (round && (inexact || !real_identical (&result, &value)))
400 : {
401 1488623 : if (mode_composite
402 1488623 : && (real_isdenormal (&result, mode) || real_iszero (&result)))
403 : {
404 : // IBM extended denormals only have DFmode precision.
405 0 : REAL_VALUE_TYPE tmp, tmp2;
406 0 : real_convert (&tmp2, DFmode, &value);
407 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
408 0 : real_convert (&result, mode, &tmp);
409 : }
410 : else
411 1488623 : frange_nextafter (mode, result, inf);
412 : }
413 15775210 : if (mode_composite)
414 0 : switch (code)
415 : {
416 0 : case PLUS_EXPR:
417 0 : case MINUS_EXPR:
418 : // ibm-ldouble-format documents 1ulp for + and -.
419 0 : frange_nextafter (mode, result, inf);
420 0 : break;
421 0 : case MULT_EXPR:
422 : // ibm-ldouble-format documents 2ulps for *.
423 0 : frange_nextafter (mode, result, inf);
424 0 : frange_nextafter (mode, result, inf);
425 0 : break;
426 0 : case RDIV_EXPR:
427 : // ibm-ldouble-format documents 3ulps for /.
428 0 : frange_nextafter (mode, result, inf);
429 0 : frange_nextafter (mode, result, inf);
430 0 : frange_nextafter (mode, result, inf);
431 0 : break;
432 : default:
433 : break;
434 : }
435 15775210 : }
436 :
437 : // Crop R to [-INF, MAX] where MAX is the maximum representable number
438 : // for TYPE.
439 :
440 : static inline void
441 175241 : frange_drop_inf (frange &r, tree type)
442 : {
443 175241 : REAL_VALUE_TYPE max = real_max_representable (type);
444 175241 : frange tmp (type, r.lower_bound (), max);
445 175241 : r.intersect (tmp);
446 175241 : }
447 :
448 : // Crop R to [MIN, +INF] where MIN is the minimum representable number
449 : // for TYPE.
450 :
451 : static inline void
452 94022 : frange_drop_ninf (frange &r, tree type)
453 : {
454 94022 : REAL_VALUE_TYPE min = real_min_representable (type);
455 94022 : frange tmp (type, min, r.upper_bound ());
456 94022 : r.intersect (tmp);
457 94022 : }
458 :
459 : // Crop R to [MIN, MAX] where MAX is the maximum representable number
460 : // for TYPE and MIN the minimum representable number for TYPE.
461 :
462 : static inline void
463 1427761 : frange_drop_infs (frange &r, tree type)
464 : {
465 1427761 : REAL_VALUE_TYPE max = real_max_representable (type);
466 1427761 : REAL_VALUE_TYPE min = real_min_representable (type);
467 1427761 : frange tmp (type, min, max);
468 1427761 : r.intersect (tmp);
469 1427761 : }
470 :
471 : // If zero is in R, make sure both -0.0 and +0.0 are in the range.
472 :
473 : static inline void
474 990834 : frange_add_zeros (frange &r, tree type)
475 : {
476 990834 : if (r.undefined_p () || r.known_isnan ())
477 : return;
478 :
479 990834 : if (HONOR_SIGNED_ZEROS (type)
480 990834 : && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
481 : {
482 159556 : frange zero;
483 159556 : zero.set_zero (type);
484 159556 : r.union_ (zero);
485 159556 : }
486 : }
487 :
488 : // Build a range that is <= VAL and store it in R. Return TRUE if
489 : // further changes may be needed for R, or FALSE if R is in its final
490 : // form.
491 :
492 : static bool
493 256408 : build_le (frange &r, tree type, const frange &val)
494 : {
495 256408 : gcc_checking_assert (!val.known_isnan ());
496 :
497 256408 : REAL_VALUE_TYPE ninf = frange_val_min (type);
498 256408 : r.set (type, ninf, val.upper_bound ());
499 :
500 : // Add both zeros if there's the possibility of zero equality.
501 256408 : frange_add_zeros (r, type);
502 :
503 256408 : return true;
504 : }
505 :
506 : // Build a range that is < VAL and store it in R. Return TRUE if
507 : // further changes may be needed for R, or FALSE if R is in its final
508 : // form.
509 :
510 : static bool
511 305077 : build_lt (frange &r, tree type, const frange &val)
512 : {
513 305077 : gcc_checking_assert (!val.known_isnan ());
514 :
515 : // < -INF is outside the range.
516 305077 : if (real_isinf (&val.upper_bound (), 1))
517 : {
518 1494 : if (HONOR_NANS (type))
519 1494 : r.set_nan (type);
520 : else
521 0 : r.set_undefined ();
522 1494 : return false;
523 : }
524 :
525 303583 : REAL_VALUE_TYPE ninf = frange_val_min (type);
526 303583 : REAL_VALUE_TYPE prev = val.upper_bound ();
527 303583 : 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 2125081 : if (!MODE_COMPOSITE_P (mode))
533 303583 : frange_nextafter (mode, prev, ninf);
534 303583 : r.set (type, ninf, prev);
535 303583 : return true;
536 : }
537 :
538 : // Build a range that is >= VAL and store it in R. Return TRUE if
539 : // further changes may be needed for R, or FALSE if R is in its final
540 : // form.
541 :
542 : static bool
543 382773 : build_ge (frange &r, tree type, const frange &val)
544 : {
545 382773 : gcc_checking_assert (!val.known_isnan ());
546 :
547 382773 : REAL_VALUE_TYPE inf = frange_val_max (type);
548 382773 : r.set (type, val.lower_bound (), inf);
549 :
550 : // Add both zeros if there's the possibility of zero equality.
551 382773 : frange_add_zeros (r, type);
552 :
553 382773 : return true;
554 : }
555 :
556 : // Build a range that is > VAL and store it in R. Return TRUE if
557 : // further changes may be needed for R, or FALSE if R is in its final
558 : // form.
559 :
560 : static bool
561 206598 : build_gt (frange &r, tree type, const frange &val)
562 : {
563 206598 : gcc_checking_assert (!val.known_isnan ());
564 :
565 : // > +INF is outside the range.
566 206598 : if (real_isinf (&val.lower_bound (), 0))
567 : {
568 3376 : if (HONOR_NANS (type))
569 3376 : r.set_nan (type);
570 : else
571 0 : r.set_undefined ();
572 3376 : return false;
573 : }
574 :
575 203222 : REAL_VALUE_TYPE inf = frange_val_max (type);
576 203222 : REAL_VALUE_TYPE next = val.lower_bound ();
577 203222 : 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 1422554 : if (!MODE_COMPOSITE_P (mode))
583 203222 : frange_nextafter (mode, next, inf);
584 203222 : r.set (type, next, inf);
585 203222 : return true;
586 : }
587 :
588 :
589 : bool
590 55185 : operator_identity::fold_range (frange &r, tree, const frange &op1,
591 : const frange &, relation_trio) const
592 : {
593 55185 : r = op1;
594 55185 : return true;
595 : }
596 :
597 : bool
598 17017 : operator_identity::op1_range (frange &r, tree, const frange &lhs,
599 : const frange &, relation_trio) const
600 : {
601 17017 : r = lhs;
602 17017 : return true;
603 : }
604 :
605 : bool
606 979 : operator_cst::fold_range (frange &r, tree, const frange &op1,
607 : const frange &, relation_trio) const
608 : {
609 979 : r = op1;
610 979 : return true;
611 : }
612 :
613 : bool
614 25695 : operator_equal::op2_range (frange &r, tree type,
615 : const irange &lhs, const frange &op1,
616 : relation_trio rel) const
617 : {
618 25695 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
619 : }
620 :
621 : bool
622 171423 : operator_equal::fold_range (irange &r, tree type,
623 : const frange &op1, const frange &op2,
624 : relation_trio rel) const
625 : {
626 171423 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
627 : return true;
628 :
629 169660 : if (op1.known_isnan () || op2.known_isnan ())
630 529 : r = range_false (type);
631 : // We can be sure the values are always equal or not if both ranges
632 : // consist of a single value, and then compare them.
633 169131 : else if (op1.singleton_p () && op2.singleton_p ())
634 : {
635 491 : if (op1 == op2)
636 142 : r = range_true (type);
637 : // If one operand is -0.0 and other 0.0, they are still equal.
638 349 : else if (real_iszero (&op1.lower_bound ())
639 349 : && real_iszero (&op2.lower_bound ()))
640 30 : r = range_true (type);
641 : else
642 319 : r = range_false (type);
643 : }
644 168640 : else if (real_iszero (&op1.lower_bound ())
645 5744 : && real_iszero (&op1.upper_bound ())
646 726 : && real_iszero (&op2.lower_bound ())
647 300 : && real_iszero (&op2.upper_bound ())
648 168940 : && !maybe_isnan (op1, op2))
649 : // [-0.0, 0.0] == [-0.0, 0.0] or similar.
650 157 : r = range_true (type);
651 : else
652 : {
653 : // If ranges do not intersect, we know the range is not equal,
654 : // otherwise we don't know anything for sure.
655 168483 : frange tmp = op1;
656 168483 : tmp.intersect (op2);
657 168483 : if (tmp.undefined_p ())
658 : {
659 : // If one range is [whatever, -0.0] and another
660 : // [0.0, whatever2], we don't know anything either,
661 : // because -0.0 == 0.0.
662 612 : if ((real_iszero (&op1.upper_bound ())
663 59 : && real_iszero (&op2.lower_bound ()))
664 615 : || (real_iszero (&op1.lower_bound ())
665 37 : && real_iszero (&op2.upper_bound ())))
666 56 : r = range_true_and_false (type);
667 : else
668 556 : r = range_false (type);
669 : }
670 : else
671 167871 : r = range_true_and_false (type);
672 168483 : }
673 : return true;
674 : }
675 :
676 : bool
677 136492 : operator_equal::op1_range (frange &r, tree type,
678 : const irange &lhs,
679 : const frange &op2,
680 : relation_trio trio) const
681 : {
682 136492 : relation_kind rel = trio.op1_op2 ();
683 136492 : switch (get_bool_state (r, lhs, type))
684 : {
685 37438 : case BRS_TRUE:
686 : // The TRUE side of x == NAN is unreachable.
687 37438 : if (op2.known_isnan ())
688 0 : r.set_undefined ();
689 : else
690 : {
691 : // If it's true, the result is the same as OP2.
692 37438 : r = op2;
693 : // Add both zeros if there's the possibility of zero equality.
694 37438 : frange_add_zeros (r, type);
695 : // The TRUE side of op1 == op2 implies op1 is !NAN.
696 37438 : r.clear_nan ();
697 : }
698 : break;
699 :
700 97296 : case BRS_FALSE:
701 : // The FALSE side of op1 == op1 implies op1 is a NAN.
702 97296 : if (rel == VREL_EQ)
703 2217 : r.set_nan (type);
704 : // On the FALSE side of x == NAN, we know nothing about x.
705 95079 : else if (op2.known_isnan ())
706 0 : r.set_varying (type);
707 : // If the result is false, the only time we know anything is
708 : // if OP2 is a constant.
709 95079 : else if (op2.singleton_p ()
710 104138 : || (!op2.maybe_isnan () && op2.zero_p ()))
711 : {
712 62594 : REAL_VALUE_TYPE tmp = op2.lower_bound ();
713 62594 : r.set (type, tmp, tmp, VR_ANTI_RANGE);
714 : }
715 : else
716 32485 : r.set_varying (type);
717 : break;
718 :
719 : default:
720 : break;
721 : }
722 136492 : return true;
723 : }
724 :
725 : // Check if the LHS range indicates a relation between OP1 and OP2.
726 :
727 : relation_kind
728 134185 : operator_equal::op1_op2_relation (const irange &lhs, const frange &,
729 : const frange &) const
730 : {
731 134185 : if (lhs.undefined_p ())
732 : return VREL_UNDEFINED;
733 :
734 : // FALSE = op1 == op2 indicates NE_EXPR.
735 134185 : if (lhs.zero_p ())
736 : return VREL_NE;
737 :
738 : // TRUE = op1 == op2 indicates EQ_EXPR.
739 70104 : if (!contains_zero_p (lhs))
740 68530 : return VREL_EQ;
741 : return VREL_VARYING;
742 : }
743 :
744 : bool
745 858713 : operator_not_equal::fold_range (irange &r, tree type,
746 : const frange &op1, const frange &op2,
747 : relation_trio trio) const
748 : {
749 858713 : relation_kind rel = trio.op1_op2 ();
750 :
751 : // VREL_NE & NE_EXPR is always true, even with NANs.
752 858713 : if (rel == VREL_NE)
753 : {
754 26 : r = range_true (type);
755 26 : return true;
756 : }
757 858687 : 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 831643 : else if (frelop_early_resolve (r, type, op1, op2, trio, VREL_NE))
764 : return true;
765 :
766 : // x != NAN is always TRUE.
767 857328 : if (op1.known_isnan () || op2.known_isnan ())
768 1267 : r = range_true (type);
769 : // We can be sure the values are always equal or not if both ranges
770 : // consist of a single value, and then compare them.
771 856061 : else if (op1.singleton_p () && op2.singleton_p ())
772 : {
773 1358 : if (op1 == op2)
774 873 : r = range_false (type);
775 : // If one operand is -0.0 and other 0.0, they are still equal.
776 485 : else if (real_iszero (&op1.lower_bound ())
777 485 : && real_iszero (&op2.lower_bound ()))
778 0 : r = range_false (type);
779 : else
780 485 : r = range_true (type);
781 : }
782 854703 : else if (real_iszero (&op1.lower_bound ())
783 7184 : && real_iszero (&op1.upper_bound ())
784 403 : && real_iszero (&op2.lower_bound ())
785 224 : && real_iszero (&op2.upper_bound ())
786 854927 : && !maybe_isnan (op1, op2))
787 : // [-0.0, 0.0] != [-0.0, 0.0] or similar.
788 136 : r = range_false (type);
789 : else
790 : {
791 : // If ranges do not intersect, we know the range is not equal,
792 : // otherwise we don't know anything for sure.
793 854567 : frange tmp = op1;
794 854567 : tmp.intersect (op2);
795 854567 : if (tmp.undefined_p ())
796 : {
797 : // If one range is [whatever, -0.0] and another
798 : // [0.0, whatever2], we don't know anything either,
799 : // because -0.0 == 0.0.
800 542 : if ((real_iszero (&op1.upper_bound ())
801 5 : && real_iszero (&op2.lower_bound ()))
802 547 : || (real_iszero (&op1.lower_bound ())
803 10 : && real_iszero (&op2.upper_bound ())))
804 0 : r = range_true_and_false (type);
805 : else
806 542 : r = range_true (type);
807 : }
808 : else
809 854025 : r = range_true_and_false (type);
810 854567 : }
811 : return true;
812 : }
813 :
814 : bool
815 363302 : operator_not_equal::op1_range (frange &r, tree type,
816 : const irange &lhs,
817 : const frange &op2,
818 : relation_trio trio) const
819 : {
820 363302 : relation_kind rel = trio.op1_op2 ();
821 363302 : switch (get_bool_state (r, lhs, type))
822 : {
823 47346 : case BRS_TRUE:
824 : // If the result is true, the only time we know anything is if
825 : // OP2 is a constant.
826 47346 : if (op2.singleton_p ())
827 : {
828 : // This is correct even if op1 is NAN, because the following
829 : // range would be ~[tmp, tmp] with the NAN property set to
830 : // maybe (VARYING).
831 23266 : REAL_VALUE_TYPE tmp = op2.lower_bound ();
832 23266 : r.set (type, tmp, tmp, VR_ANTI_RANGE);
833 : }
834 : // The TRUE side of op1 != op1 implies op1 is NAN.
835 24080 : else if (rel == VREL_EQ)
836 5907 : r.set_nan (type);
837 : else
838 18173 : r.set_varying (type);
839 : break;
840 :
841 314372 : case BRS_FALSE:
842 : // The FALSE side of x != NAN is impossible.
843 314372 : if (op2.known_isnan ())
844 170 : r.set_undefined ();
845 : else
846 : {
847 : // If it's false, the result is the same as OP2.
848 314202 : r = op2;
849 : // Add both zeros if there's the possibility of zero equality.
850 314202 : frange_add_zeros (r, type);
851 : // The FALSE side of op1 != op2 implies op1 is !NAN.
852 314202 : r.clear_nan ();
853 : }
854 : break;
855 :
856 : default:
857 : break;
858 : }
859 363302 : return true;
860 : }
861 :
862 : bool
863 245393 : operator_not_equal::op2_range (frange &r, tree type,
864 : const irange &lhs,
865 : const frange &op1,
866 : relation_trio trio) const
867 : {
868 245393 : return op1_range (r, type, lhs, op1, trio);
869 : }
870 :
871 : // Check if the LHS range indicates a relation between OP1 and OP2.
872 :
873 : relation_kind
874 734367 : operator_not_equal::op1_op2_relation (const irange &lhs, const frange &,
875 : const frange &) const
876 : {
877 734367 : if (lhs.undefined_p ())
878 : return VREL_UNDEFINED;
879 :
880 : // FALSE = op1 != op2 indicates EQ_EXPR.
881 734367 : if (lhs.zero_p ())
882 : return VREL_EQ;
883 :
884 : // TRUE = op1 != op2 indicates NE_EXPR.
885 118262 : if (!contains_zero_p (lhs))
886 116705 : return VREL_NE;
887 : return VREL_VARYING;
888 : }
889 :
890 : bool
891 274607 : operator_lt::fold_range (irange &r, tree type,
892 : const frange &op1, const frange &op2,
893 : relation_trio trio) const
894 : {
895 274607 : if (frelop_early_resolve (r, type, op1, op2, trio, VREL_LT))
896 : return true;
897 :
898 273946 : if (op1.known_isnan ()
899 273490 : || op2.known_isnan ()
900 547189 : || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
901 2946 : r = range_false (type);
902 271000 : else if (!maybe_isnan (op1, op2)
903 271000 : && real_less (&op1.upper_bound (), &op2.lower_bound ()))
904 1083 : r = range_true (type);
905 : else
906 269917 : r = range_true_and_false (type);
907 : return true;
908 : }
909 :
910 : bool
911 430248 : operator_lt::op1_range (frange &r,
912 : tree type,
913 : const irange &lhs,
914 : const frange &op2,
915 : relation_trio) const
916 : {
917 430248 : switch (get_bool_state (r, lhs, type))
918 : {
919 146767 : case BRS_TRUE:
920 : // The TRUE side of x < NAN is unreachable.
921 146767 : if (op2.known_isnan ())
922 68 : r.set_undefined ();
923 146699 : else if (op2.undefined_p ())
924 : return false;
925 146699 : else if (build_lt (r, type, op2))
926 : {
927 146699 : r.clear_nan ();
928 : // x < y implies x is not +INF.
929 146699 : frange_drop_inf (r, type);
930 : }
931 : break;
932 :
933 282901 : case BRS_FALSE:
934 : // On the FALSE side of x < NAN, we know nothing about x.
935 534297 : if (op2.maybe_isnan ())
936 31505 : r.set_varying (type);
937 : else
938 251396 : build_ge (r, type, op2);
939 : break;
940 :
941 : default:
942 : break;
943 : }
944 : return true;
945 : }
946 :
947 : bool
948 68048 : operator_lt::op2_range (frange &r,
949 : tree type,
950 : const irange &lhs,
951 : const frange &op1,
952 : relation_trio) const
953 : {
954 68048 : switch (get_bool_state (r, lhs, type))
955 : {
956 27421 : case BRS_TRUE:
957 : // The TRUE side of NAN < x is unreachable.
958 27421 : if (op1.known_isnan ())
959 22 : r.set_undefined ();
960 27399 : else if (op1.undefined_p ())
961 : return false;
962 27399 : else if (build_gt (r, type, op1))
963 : {
964 27399 : r.clear_nan ();
965 : // x < y implies y is not -INF.
966 27399 : frange_drop_ninf (r, type);
967 : }
968 : break;
969 :
970 40236 : case BRS_FALSE:
971 : // On the FALSE side of NAN < x, we know nothing about x.
972 44228 : if (op1.maybe_isnan ())
973 36244 : r.set_varying (type);
974 : else
975 3992 : build_le (r, type, op1);
976 : break;
977 :
978 : default:
979 : break;
980 : }
981 : return true;
982 : }
983 :
984 :
985 : // Check if the LHS range indicates a relation between OP1 and OP2.
986 :
987 : relation_kind
988 260157 : operator_lt::op1_op2_relation (const irange &lhs, const frange &,
989 : const frange &) const
990 : {
991 260157 : if (lhs.undefined_p ())
992 : return VREL_UNDEFINED;
993 :
994 : // FALSE = op1 < op2 indicates GE_EXPR.
995 260157 : if (lhs.zero_p ())
996 : return VREL_GE;
997 :
998 : // TRUE = op1 < op2 indicates LT_EXPR.
999 119438 : if (!contains_zero_p (lhs))
1000 118686 : return VREL_LT;
1001 : return VREL_VARYING;
1002 : }
1003 :
1004 : bool
1005 272758 : operator_le::fold_range (irange &r, tree type,
1006 : const frange &op1, const frange &op2,
1007 : relation_trio rel) const
1008 : {
1009 272758 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
1010 : return true;
1011 :
1012 272183 : if (op1.known_isnan ()
1013 271129 : || op2.known_isnan ()
1014 543278 : || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1015 2522 : r = range_false (type);
1016 269661 : else if (!maybe_isnan (op1, op2)
1017 269661 : && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1018 855 : r = range_true (type);
1019 : else
1020 268806 : r = range_true_and_false (type);
1021 : return true;
1022 : }
1023 :
1024 : bool
1025 99837 : operator_le::op1_range (frange &r,
1026 : tree type,
1027 : const irange &lhs,
1028 : const frange &op2,
1029 : relation_trio) const
1030 : {
1031 99837 : switch (get_bool_state (r, lhs, type))
1032 : {
1033 68408 : case BRS_TRUE:
1034 : // The TRUE side of x <= NAN is unreachable.
1035 68408 : if (op2.known_isnan ())
1036 0 : r.set_undefined ();
1037 68408 : else if (op2.undefined_p ())
1038 : return false;
1039 68408 : else if (build_le (r, type, op2))
1040 68408 : r.clear_nan ();
1041 : break;
1042 :
1043 31090 : case BRS_FALSE:
1044 : // On the FALSE side of x <= NAN, we know nothing about x.
1045 56627 : if (op2.maybe_isnan ())
1046 5553 : r.set_varying (type);
1047 : else
1048 25537 : build_gt (r, type, op2);
1049 : break;
1050 :
1051 : default:
1052 : break;
1053 : }
1054 : return true;
1055 : }
1056 :
1057 : bool
1058 15954 : operator_le::op2_range (frange &r,
1059 : tree type,
1060 : const irange &lhs,
1061 : const frange &op1,
1062 : relation_trio) const
1063 : {
1064 15954 : switch (get_bool_state (r, lhs, type))
1065 : {
1066 4434 : case BRS_TRUE:
1067 : // The TRUE side of NAN <= x is unreachable.
1068 4434 : if (op1.known_isnan ())
1069 0 : r.set_undefined ();
1070 4434 : else if (op1.undefined_p ())
1071 : return false;
1072 4434 : else if (build_ge (r, type, op1))
1073 4434 : r.clear_nan ();
1074 : break;
1075 :
1076 11217 : case BRS_FALSE:
1077 : // On the FALSE side of NAN <= x, we know nothing about x.
1078 12063 : if (op1.maybe_isnan ())
1079 10371 : r.set_varying (type);
1080 846 : else if (op1.undefined_p ())
1081 : return false;
1082 : else
1083 846 : build_lt (r, type, op1);
1084 : break;
1085 :
1086 : default:
1087 : break;
1088 : }
1089 : return true;
1090 : }
1091 :
1092 : // Check if the LHS range indicates a relation between OP1 and OP2.
1093 :
1094 : relation_kind
1095 64989 : operator_le::op1_op2_relation (const irange &lhs, const frange &,
1096 : const frange &) const
1097 : {
1098 64989 : if (lhs.undefined_p ())
1099 : return VREL_UNDEFINED;
1100 :
1101 : // FALSE = op1 <= op2 indicates GT_EXPR.
1102 64989 : if (lhs.zero_p ())
1103 : return VREL_GT;
1104 :
1105 : // TRUE = op1 <= op2 indicates LE_EXPR.
1106 32443 : if (!contains_zero_p (lhs))
1107 31833 : return VREL_LE;
1108 : return VREL_VARYING;
1109 : }
1110 :
1111 : bool
1112 277067 : operator_gt::fold_range (irange &r, tree type,
1113 : const frange &op1, const frange &op2,
1114 : relation_trio trio) const
1115 : {
1116 277067 : if (frelop_early_resolve (r, type, op1, op2, trio, VREL_GT))
1117 : return true;
1118 :
1119 276324 : if (op1.known_isnan ()
1120 275971 : || op2.known_isnan ()
1121 552046 : || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1122 4528 : r = range_false (type);
1123 271796 : else if (!maybe_isnan (op1, op2)
1124 271796 : && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1125 689 : r = range_true (type);
1126 : else
1127 271107 : r = range_true_and_false (type);
1128 : return true;
1129 : }
1130 :
1131 : bool
1132 172463 : operator_gt::op1_range (frange &r,
1133 : tree type,
1134 : const irange &lhs,
1135 : const frange &op2,
1136 : relation_trio) const
1137 : {
1138 172463 : switch (get_bool_state (r, lhs, type))
1139 : {
1140 66651 : case BRS_TRUE:
1141 : // The TRUE side of x > NAN is unreachable.
1142 66651 : if (op2.known_isnan ())
1143 28 : r.set_undefined ();
1144 66623 : else if (op2.undefined_p ())
1145 : return false;
1146 66623 : else if (build_gt (r, type, op2))
1147 : {
1148 66623 : r.clear_nan ();
1149 : // x > y implies x is not -INF.
1150 66623 : frange_drop_ninf (r, type);
1151 : }
1152 : break;
1153 :
1154 105065 : case BRS_FALSE:
1155 : // On the FALSE side of x > NAN, we know nothing about x.
1156 180184 : if (op2.maybe_isnan ())
1157 29946 : r.set_varying (type);
1158 75119 : else if (op2.undefined_p ())
1159 : return false;
1160 : else
1161 75119 : build_le (r, type, op2);
1162 : break;
1163 :
1164 : default:
1165 : break;
1166 : }
1167 : return true;
1168 : }
1169 :
1170 : bool
1171 72494 : operator_gt::op2_range (frange &r,
1172 : tree type,
1173 : const irange &lhs,
1174 : const frange &op1,
1175 : relation_trio) const
1176 : {
1177 72494 : switch (get_bool_state (r, lhs, type))
1178 : {
1179 28564 : case BRS_TRUE:
1180 : // The TRUE side of NAN > x is unreachable.
1181 28564 : if (op1.known_isnan ())
1182 22 : r.set_undefined ();
1183 28542 : else if (op1.undefined_p ())
1184 : return false;
1185 28542 : else if (build_lt (r, type, op1))
1186 : {
1187 28542 : r.clear_nan ();
1188 : // x > y implies y is not +INF.
1189 28542 : frange_drop_inf (r, type);
1190 : }
1191 : break;
1192 :
1193 43517 : case BRS_FALSE:
1194 : // On The FALSE side of NAN > x, we know nothing about x.
1195 46862 : if (op1.maybe_isnan ())
1196 40172 : r.set_varying (type);
1197 3345 : else if (op1.undefined_p ())
1198 : return false;
1199 : else
1200 3345 : build_ge (r, type, op1);
1201 : break;
1202 :
1203 : default:
1204 : break;
1205 : }
1206 : return true;
1207 : }
1208 :
1209 : // Check if the LHS range indicates a relation between OP1 and OP2.
1210 :
1211 : relation_kind
1212 276205 : operator_gt::op1_op2_relation (const irange &lhs, const frange &,
1213 : const frange &) const
1214 : {
1215 276205 : if (lhs.undefined_p ())
1216 : return VREL_UNDEFINED;
1217 :
1218 : // FALSE = op1 > op2 indicates LE_EXPR.
1219 276205 : if (lhs.zero_p ())
1220 : return VREL_LE;
1221 :
1222 : // TRUE = op1 > op2 indicates GT_EXPR.
1223 124885 : if (!contains_zero_p (lhs))
1224 124023 : return VREL_GT;
1225 : return VREL_VARYING;
1226 : }
1227 :
1228 : bool
1229 269810 : operator_ge::fold_range (irange &r, tree type,
1230 : const frange &op1, const frange &op2,
1231 : relation_trio rel) const
1232 : {
1233 269810 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
1234 : return true;
1235 :
1236 269431 : if (op1.known_isnan ()
1237 268613 : || op2.known_isnan ()
1238 538013 : || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1239 1498 : r = range_false (type);
1240 267933 : else if (!maybe_isnan (op1, op2)
1241 267933 : && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1242 2509 : r = range_true (type);
1243 : else
1244 265424 : r = range_true_and_false (type);
1245 : return true;
1246 : }
1247 :
1248 : bool
1249 109119 : operator_ge::op1_range (frange &r,
1250 : tree type,
1251 : const irange &lhs,
1252 : const frange &op2,
1253 : relation_trio) const
1254 : {
1255 109119 : switch (get_bool_state (r, lhs, type))
1256 : {
1257 60576 : case BRS_TRUE:
1258 : // The TRUE side of x >= NAN is unreachable.
1259 60576 : if (op2.known_isnan ())
1260 0 : r.set_undefined ();
1261 60576 : else if (op2.undefined_p ())
1262 : return false;
1263 60576 : else if (build_ge (r, type, op2))
1264 60576 : r.clear_nan ();
1265 : break;
1266 :
1267 48240 : case BRS_FALSE:
1268 : // On the FALSE side of x >= NAN, we know nothing about x.
1269 89403 : if (op2.maybe_isnan ())
1270 7077 : r.set_varying (type);
1271 41163 : else if (op2.undefined_p ())
1272 : return false;
1273 : else
1274 41163 : build_lt (r, type, op2);
1275 : break;
1276 :
1277 : default:
1278 : break;
1279 : }
1280 : return true;
1281 : }
1282 :
1283 : bool
1284 14295 : operator_ge::op2_range (frange &r, tree type,
1285 : const irange &lhs,
1286 : const frange &op1,
1287 : relation_trio) const
1288 : {
1289 14295 : switch (get_bool_state (r, lhs, type))
1290 : {
1291 5671 : case BRS_TRUE:
1292 : // The TRUE side of NAN >= x is unreachable.
1293 5671 : if (op1.known_isnan ())
1294 0 : r.set_undefined ();
1295 5671 : else if (op1.undefined_p ())
1296 : return false;
1297 5671 : else if (build_le (r, type, op1))
1298 5671 : r.clear_nan ();
1299 : break;
1300 :
1301 8357 : case BRS_FALSE:
1302 : // On the FALSE side of NAN >= x, we know nothing about x.
1303 9120 : if (op1.maybe_isnan ())
1304 7594 : r.set_varying (type);
1305 763 : else if (op1.undefined_p ())
1306 : return false;
1307 : else
1308 763 : build_gt (r, type, op1);
1309 : break;
1310 :
1311 : default:
1312 : break;
1313 : }
1314 : return true;
1315 : }
1316 :
1317 : // Check if the LHS range indicates a relation between OP1 and OP2.
1318 :
1319 : relation_kind
1320 61197 : operator_ge::op1_op2_relation (const irange &lhs, const frange &,
1321 : const frange &) const
1322 : {
1323 61197 : if (lhs.undefined_p ())
1324 : return VREL_UNDEFINED;
1325 :
1326 : // FALSE = op1 >= op2 indicates LT_EXPR.
1327 61197 : if (lhs.zero_p ())
1328 : return VREL_LT;
1329 :
1330 : // TRUE = op1 >= op2 indicates GE_EXPR.
1331 31660 : if (!contains_zero_p (lhs))
1332 31122 : return VREL_GE;
1333 : return VREL_VARYING;
1334 : }
1335 :
1336 : // UNORDERED_EXPR comparison.
1337 :
1338 : class foperator_unordered : public range_operator
1339 : {
1340 : using range_operator::fold_range;
1341 : using range_operator::op1_range;
1342 : using range_operator::op2_range;
1343 : public:
1344 : bool fold_range (irange &r, tree type,
1345 : const frange &op1, const frange &op2,
1346 : relation_trio = TRIO_VARYING) const final override;
1347 : bool op1_range (frange &r, tree type,
1348 : const irange &lhs, const frange &op2,
1349 : relation_trio = TRIO_VARYING) const final override;
1350 56460 : bool op2_range (frange &r, tree type,
1351 : const irange &lhs, const frange &op1,
1352 : relation_trio rel = TRIO_VARYING) const final override
1353 : {
1354 56460 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1355 : }
1356 : } fop_unordered;
1357 :
1358 : bool
1359 54138 : foperator_unordered::fold_range (irange &r, tree type,
1360 : const frange &op1, const frange &op2,
1361 : relation_trio) const
1362 : {
1363 : // UNORDERED is TRUE if either operand is a NAN.
1364 54138 : if (op1.known_isnan () || op2.known_isnan ())
1365 115 : r = range_true (type);
1366 : // UNORDERED is FALSE if neither operand is a NAN.
1367 56483 : else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1368 1232 : r = range_false (type);
1369 : else
1370 52791 : r = range_true_and_false (type);
1371 54138 : return true;
1372 : }
1373 :
1374 : bool
1375 103100 : foperator_unordered::op1_range (frange &r, tree type,
1376 : const irange &lhs,
1377 : const frange &op2,
1378 : relation_trio trio) const
1379 : {
1380 103100 : relation_kind rel = trio.op1_op2 ();
1381 103100 : switch (get_bool_state (r, lhs, type))
1382 : {
1383 37810 : case BRS_TRUE:
1384 : // Since at least one operand must be NAN, if one of them is
1385 : // not, the other must be.
1386 37810 : if (rel == VREL_EQ || !op2.maybe_isnan ())
1387 9557 : r.set_nan (type);
1388 : else
1389 28253 : r.set_varying (type);
1390 : break;
1391 :
1392 57447 : case BRS_FALSE:
1393 : // A false UNORDERED means both operands are !NAN, so it's
1394 : // impossible for op2 to be a NAN.
1395 57447 : if (op2.known_isnan ())
1396 0 : r.set_undefined ();
1397 : else
1398 : {
1399 57447 : r.set_varying (type);
1400 57447 : r.clear_nan ();
1401 : }
1402 : break;
1403 :
1404 : default:
1405 : break;
1406 : }
1407 103100 : return true;
1408 : }
1409 :
1410 : // ORDERED_EXPR comparison.
1411 :
1412 : class foperator_ordered : public range_operator
1413 : {
1414 : using range_operator::fold_range;
1415 : using range_operator::op1_range;
1416 : using range_operator::op2_range;
1417 : public:
1418 : bool fold_range (irange &r, tree type,
1419 : const frange &op1, const frange &op2,
1420 : relation_trio = TRIO_VARYING) const final override;
1421 : bool op1_range (frange &r, tree type,
1422 : const irange &lhs, const frange &op2,
1423 : relation_trio = TRIO_VARYING) const final override;
1424 30098 : bool op2_range (frange &r, tree type,
1425 : const irange &lhs, const frange &op1,
1426 : relation_trio rel = TRIO_VARYING) const final override
1427 : {
1428 30098 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1429 : }
1430 : } fop_ordered;
1431 :
1432 : bool
1433 32907 : foperator_ordered::fold_range (irange &r, tree type,
1434 : const frange &op1, const frange &op2,
1435 : relation_trio) const
1436 : {
1437 32907 : if (op1.known_isnan () || op2.known_isnan ())
1438 366 : r = range_false (type);
1439 35491 : else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1440 1472 : r = range_true (type);
1441 : else
1442 31069 : r = range_true_and_false (type);
1443 32907 : return true;
1444 : }
1445 :
1446 : bool
1447 63999 : foperator_ordered::op1_range (frange &r, tree type,
1448 : const irange &lhs,
1449 : const frange &op2,
1450 : relation_trio trio) const
1451 : {
1452 63999 : relation_kind rel = trio.op1_op2 ();
1453 63999 : switch (get_bool_state (r, lhs, type))
1454 : {
1455 57326 : case BRS_TRUE:
1456 : // The TRUE side of ORDERED means both operands are !NAN, so
1457 : // it's impossible for op2 to be a NAN.
1458 57326 : if (op2.known_isnan ())
1459 10 : r.set_undefined ();
1460 : else
1461 : {
1462 57316 : r.set_varying (type);
1463 57316 : r.clear_nan ();
1464 : }
1465 : break;
1466 :
1467 4690 : case BRS_FALSE:
1468 : // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1469 4690 : if (rel == VREL_EQ)
1470 2175 : r.set_nan (type);
1471 : else
1472 2515 : r.set_varying (type);
1473 : break;
1474 :
1475 : default:
1476 : break;
1477 : }
1478 63999 : return true;
1479 : }
1480 :
1481 : bool
1482 241327 : operator_negate::fold_range (frange &r, tree type,
1483 : const frange &op1, const frange &op2,
1484 : relation_trio) const
1485 : {
1486 241327 : if (empty_range_varying (r, type, op1, op2))
1487 353 : return true;
1488 240974 : if (op1.known_isnan ())
1489 : {
1490 398 : bool sign;
1491 398 : if (op1.nan_signbit_p (sign))
1492 38 : r.set_nan (type, !sign);
1493 : else
1494 360 : r.set_nan (type);
1495 398 : return true;
1496 : }
1497 :
1498 240576 : REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1499 240576 : REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1500 240576 : lh_lb = real_value_negate (&lh_lb);
1501 240576 : lh_ub = real_value_negate (&lh_ub);
1502 240576 : r.set (type, lh_ub, lh_lb);
1503 430232 : if (op1.maybe_isnan ())
1504 : {
1505 50924 : bool sign;
1506 50924 : if (op1.nan_signbit_p (sign))
1507 2396 : r.update_nan (!sign);
1508 : else
1509 48528 : r.update_nan ();
1510 : }
1511 : else
1512 189652 : r.clear_nan ();
1513 : return true;
1514 : }
1515 :
1516 : bool
1517 3166 : operator_negate::op1_range (frange &r, tree type,
1518 : const frange &lhs, const frange &op2,
1519 : relation_trio rel) const
1520 : {
1521 3166 : return fold_range (r, type, lhs, op2, rel);
1522 : }
1523 :
1524 : bool
1525 572406 : operator_abs::fold_range (frange &r, tree type,
1526 : const frange &op1, const frange &op2,
1527 : relation_trio) const
1528 : {
1529 572406 : if (empty_range_varying (r, type, op1, op2))
1530 113 : return true;
1531 572293 : if (op1.known_isnan ())
1532 : {
1533 586 : r.set_nan (type, /*sign=*/false);
1534 586 : return true;
1535 : }
1536 :
1537 571707 : const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1538 571707 : const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1539 : // Handle the easy case where everything is positive.
1540 571707 : if (real_compare (GE_EXPR, &lh_lb, &dconst0)
1541 161543 : && !real_iszero (&lh_lb, /*sign=*/true)
1542 730688 : && !op1.maybe_isnan (/*sign=*/true))
1543 : {
1544 158616 : r = op1;
1545 158616 : return true;
1546 : }
1547 :
1548 413091 : REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
1549 413091 : 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 413091 : if (real_compare (LE_EXPR, &lh_lb, &dconst0)
1553 413091 : && real_compare (GE_EXPR, &lh_ub, &dconst0))
1554 : {
1555 412224 : if (real_compare (GT_EXPR, &min, &max))
1556 5414 : max = min;
1557 412224 : min = dconst0;
1558 : }
1559 : else
1560 : {
1561 : // If the range was reversed, swap MIN and MAX.
1562 867 : if (real_compare (GT_EXPR, &min, &max))
1563 788 : std::swap (min, max);
1564 : }
1565 :
1566 413091 : r.set (type, min, max);
1567 439139 : if (op1.maybe_isnan ())
1568 388974 : r.update_nan (/*sign=*/false);
1569 : else
1570 24117 : r.clear_nan ();
1571 : return true;
1572 : }
1573 :
1574 : bool
1575 323490 : operator_abs::op1_range (frange &r, tree type,
1576 : const frange &lhs, const frange &op2,
1577 : relation_trio) const
1578 : {
1579 323490 : if (empty_range_varying (r, type, lhs, op2))
1580 0 : return true;
1581 323490 : if (lhs.known_isnan ())
1582 : {
1583 2853 : r.set_nan (type);
1584 2853 : return true;
1585 : }
1586 :
1587 : // Start with the positives because negatives are an impossible result.
1588 320637 : frange positives (type, dconst0, frange_val_max (type));
1589 320637 : positives.update_nan (/*sign=*/false);
1590 320637 : positives.intersect (lhs);
1591 320637 : r = positives;
1592 : // Add -NAN if relevant.
1593 484495 : if (r.maybe_isnan ())
1594 : {
1595 156719 : frange neg_nan;
1596 156719 : neg_nan.set_nan (type, true);
1597 156719 : r.union_ (neg_nan);
1598 156719 : }
1599 320637 : if (r.known_isnan () || r.undefined_p ())
1600 : return true;
1601 : // Then add the negative of each pair:
1602 : // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1603 320565 : frange negatives (type, real_value_negate (&positives.upper_bound ()),
1604 320565 : real_value_negate (&positives.lower_bound ()));
1605 320565 : negatives.clear_nan ();
1606 320565 : r.union_ (negatives);
1607 320565 : return true;
1608 641202 : }
1609 :
1610 : class foperator_unordered_lt : public range_operator
1611 : {
1612 : using range_operator::fold_range;
1613 : using range_operator::op1_range;
1614 : using range_operator::op2_range;
1615 : public:
1616 11078 : bool fold_range (irange &r, tree type,
1617 : const frange &op1, const frange &op2,
1618 : relation_trio trio = TRIO_VARYING) const final override
1619 : {
1620 11078 : if (op1.known_isnan () || op2.known_isnan ())
1621 : {
1622 33 : r = range_true (type);
1623 33 : return true;
1624 : }
1625 11045 : frange op1_no_nan = op1;
1626 11045 : frange op2_no_nan = op2;
1627 13650 : if (op1.maybe_isnan ())
1628 8424 : op1_no_nan.clear_nan ();
1629 18506 : if (op2.maybe_isnan ())
1630 3584 : op2_no_nan.clear_nan ();
1631 11045 : if (!range_op_handler (LT_EXPR).fold_range (r, type, op1_no_nan,
1632 : op2_no_nan, trio))
1633 : return false;
1634 : // The result is the same as the ordered version when the
1635 : // comparison is true or when the operands cannot be NANs.
1636 11045 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1637 : return true;
1638 : else
1639 : {
1640 8320 : r = range_true_and_false (type);
1641 8320 : return true;
1642 : }
1643 11045 : }
1644 : bool op1_range (frange &r, tree type,
1645 : const irange &lhs,
1646 : const frange &op2,
1647 : relation_trio trio) const final override;
1648 : bool op2_range (frange &r, tree type,
1649 : const irange &lhs,
1650 : const frange &op1,
1651 : relation_trio trio) const final override;
1652 : } fop_unordered_lt;
1653 :
1654 : bool
1655 3606 : foperator_unordered_lt::op1_range (frange &r, tree type,
1656 : const irange &lhs,
1657 : const frange &op2,
1658 : relation_trio) const
1659 : {
1660 3606 : switch (get_bool_state (r, lhs, type))
1661 : {
1662 1740 : case BRS_TRUE:
1663 3424 : if (op2.maybe_isnan ())
1664 56 : r.set_varying (type);
1665 1684 : else if (op2.undefined_p ())
1666 : return false;
1667 : else
1668 1684 : build_lt (r, type, op2);
1669 : break;
1670 :
1671 1236 : 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 1236 : if (op2.known_isnan ())
1675 0 : r.set_undefined ();
1676 1236 : else if (op2.undefined_p ())
1677 : return false;
1678 1236 : else if (build_ge (r, type, op2))
1679 1236 : r.clear_nan ();
1680 : break;
1681 :
1682 : default:
1683 : break;
1684 : }
1685 : return true;
1686 : }
1687 :
1688 : bool
1689 686 : foperator_unordered_lt::op2_range (frange &r, tree type,
1690 : const irange &lhs,
1691 : const frange &op1,
1692 : relation_trio) const
1693 : {
1694 686 : switch (get_bool_state (r, lhs, type))
1695 : {
1696 56 : case BRS_TRUE:
1697 56 : if (op1.maybe_isnan ())
1698 56 : r.set_varying (type);
1699 0 : else if (op1.undefined_p ())
1700 : return false;
1701 : else
1702 0 : build_gt (r, type, op1);
1703 : break;
1704 :
1705 0 : 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 0 : if (op1.known_isnan ())
1709 0 : r.set_undefined ();
1710 0 : else if (op1.undefined_p ())
1711 : return false;
1712 0 : else if (build_le (r, type, op1))
1713 0 : r.clear_nan ();
1714 : break;
1715 :
1716 : default:
1717 : break;
1718 : }
1719 : return true;
1720 : }
1721 :
1722 : class foperator_unordered_le : public range_operator
1723 : {
1724 : using range_operator::fold_range;
1725 : using range_operator::op1_range;
1726 : using range_operator::op2_range;
1727 : public:
1728 180006 : bool fold_range (irange &r, tree type,
1729 : const frange &op1, const frange &op2,
1730 : relation_trio trio = TRIO_VARYING) const final override
1731 : {
1732 180006 : if (op1.known_isnan () || op2.known_isnan ())
1733 : {
1734 98 : r = range_true (type);
1735 98 : return true;
1736 : }
1737 179908 : frange op1_no_nan = op1;
1738 179908 : frange op2_no_nan = op2;
1739 205990 : if (op1.maybe_isnan ())
1740 153800 : op1_no_nan.clear_nan ();
1741 352623 : if (op2.maybe_isnan ())
1742 7187 : op2_no_nan.clear_nan ();
1743 179908 : if (!range_op_handler (LE_EXPR).fold_range (r, type, op1_no_nan,
1744 : op2_no_nan, trio))
1745 : return false;
1746 : // The result is the same as the ordered version when the
1747 : // comparison is true or when the operands cannot be NANs.
1748 179908 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1749 : return true;
1750 : else
1751 : {
1752 155564 : r = range_true_and_false (type);
1753 155564 : return true;
1754 : }
1755 179908 : }
1756 : bool op1_range (frange &r, tree type,
1757 : const irange &lhs, const frange &op2,
1758 : relation_trio = TRIO_VARYING) const final override;
1759 : bool op2_range (frange &r, tree type,
1760 : const irange &lhs, const frange &op1,
1761 : relation_trio = TRIO_VARYING) const final override;
1762 : } fop_unordered_le;
1763 :
1764 : bool
1765 167175 : foperator_unordered_le::op1_range (frange &r, tree type,
1766 : const irange &lhs, const frange &op2,
1767 : relation_trio) const
1768 : {
1769 167175 : switch (get_bool_state (r, lhs, type))
1770 : {
1771 92219 : case BRS_TRUE:
1772 179321 : if (op2.maybe_isnan ())
1773 5117 : r.set_varying (type);
1774 87102 : else if (op2.undefined_p ())
1775 : return false;
1776 : else
1777 87102 : build_le (r, type, op2);
1778 : break;
1779 :
1780 74312 : case BRS_FALSE:
1781 : // A false UNORDERED_LE means both operands are !NAN, so it's
1782 : // impossible for op2 to be a NAN.
1783 74312 : if (op2.known_isnan ())
1784 0 : r.set_undefined ();
1785 74312 : else if (build_gt (r, type, op2))
1786 74310 : r.clear_nan ();
1787 : break;
1788 :
1789 : default:
1790 : break;
1791 : }
1792 : return true;
1793 : }
1794 :
1795 : bool
1796 14100 : foperator_unordered_le::op2_range (frange &r,
1797 : tree type,
1798 : const irange &lhs,
1799 : const frange &op1,
1800 : relation_trio) const
1801 : {
1802 14100 : switch (get_bool_state (r, lhs, type))
1803 : {
1804 9851 : case BRS_TRUE:
1805 14857 : if (op1.maybe_isnan ())
1806 4845 : r.set_varying (type);
1807 5006 : else if (op1.undefined_p ())
1808 : return false;
1809 : else
1810 5006 : build_ge (r, type, op1);
1811 : break;
1812 :
1813 3605 : case BRS_FALSE:
1814 : // A false UNORDERED_LE means both operands are !NAN, so it's
1815 : // impossible for op1 to be a NAN.
1816 3605 : if (op1.known_isnan ())
1817 0 : r.set_undefined ();
1818 3605 : else if (op1.undefined_p ())
1819 : return false;
1820 3605 : else if (build_lt (r, type, op1))
1821 3605 : r.clear_nan ();
1822 : break;
1823 :
1824 : default:
1825 : break;
1826 : }
1827 : return true;
1828 : }
1829 :
1830 : class foperator_unordered_gt : public range_operator
1831 : {
1832 : using range_operator::fold_range;
1833 : using range_operator::op1_range;
1834 : using range_operator::op2_range;
1835 : public:
1836 48269 : bool fold_range (irange &r, tree type,
1837 : const frange &op1, const frange &op2,
1838 : relation_trio trio = TRIO_VARYING) const final override
1839 : {
1840 48269 : if (op1.known_isnan () || op2.known_isnan ())
1841 : {
1842 159 : r = range_true (type);
1843 159 : return true;
1844 : }
1845 48110 : frange op1_no_nan = op1;
1846 48110 : frange op2_no_nan = op2;
1847 52074 : if (op1.maybe_isnan ())
1848 44127 : op1_no_nan.clear_nan ();
1849 92544 : if (op2.maybe_isnan ())
1850 3676 : op2_no_nan.clear_nan ();
1851 48110 : if (!range_op_handler (GT_EXPR).fold_range (r, type, op1_no_nan,
1852 : op2_no_nan, trio))
1853 : return false;
1854 : // The result is the same as the ordered version when the
1855 : // comparison is true or when the operands cannot be NANs.
1856 48110 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1857 : return true;
1858 : else
1859 : {
1860 44020 : r = range_true_and_false (type);
1861 44020 : return true;
1862 : }
1863 48110 : }
1864 : bool op1_range (frange &r, tree type,
1865 : const irange &lhs, const frange &op2,
1866 : relation_trio = TRIO_VARYING) const final override;
1867 : bool op2_range (frange &r, tree type,
1868 : const irange &lhs, const frange &op1,
1869 : relation_trio = TRIO_VARYING) const final override;
1870 : } fop_unordered_gt;
1871 :
1872 : bool
1873 18994 : foperator_unordered_gt::op1_range (frange &r,
1874 : tree type,
1875 : const irange &lhs,
1876 : const frange &op2,
1877 : relation_trio) const
1878 : {
1879 18994 : switch (get_bool_state (r, lhs, type))
1880 : {
1881 6652 : case BRS_TRUE:
1882 13228 : if (op2.maybe_isnan ())
1883 76 : r.set_varying (type);
1884 6576 : else if (op2.undefined_p ())
1885 : return false;
1886 : else
1887 6576 : build_gt (r, type, op2);
1888 : break;
1889 :
1890 11742 : case BRS_FALSE:
1891 : // A false UNORDERED_GT means both operands are !NAN, so it's
1892 : // impossible for op2 to be a NAN.
1893 11742 : if (op2.known_isnan ())
1894 0 : r.set_undefined ();
1895 11742 : else if (op2.undefined_p ())
1896 : return false;
1897 11742 : else if (build_le (r, type, op2))
1898 11742 : r.clear_nan ();
1899 : break;
1900 :
1901 : default:
1902 : break;
1903 : }
1904 : return true;
1905 : }
1906 :
1907 : bool
1908 676 : foperator_unordered_gt::op2_range (frange &r,
1909 : tree type,
1910 : const irange &lhs,
1911 : const frange &op1,
1912 : relation_trio) const
1913 : {
1914 676 : switch (get_bool_state (r, lhs, type))
1915 : {
1916 76 : case BRS_TRUE:
1917 76 : if (op1.maybe_isnan ())
1918 76 : r.set_varying (type);
1919 0 : else if (op1.undefined_p ())
1920 : return false;
1921 : else
1922 0 : build_lt (r, type, op1);
1923 : break;
1924 :
1925 0 : case BRS_FALSE:
1926 : // A false UNORDERED_GT means both operands are !NAN, so it's
1927 : // impossible for op1 to be a NAN.
1928 0 : if (op1.known_isnan ())
1929 0 : r.set_undefined ();
1930 0 : else if (op1.undefined_p ())
1931 : return false;
1932 0 : else if (build_ge (r, type, op1))
1933 0 : r.clear_nan ();
1934 : break;
1935 :
1936 : default:
1937 : break;
1938 : }
1939 : return true;
1940 : }
1941 :
1942 : class foperator_unordered_ge : public range_operator
1943 : {
1944 : using range_operator::fold_range;
1945 : using range_operator::op1_range;
1946 : using range_operator::op2_range;
1947 : public:
1948 173527 : bool fold_range (irange &r, tree type,
1949 : const frange &op1, const frange &op2,
1950 : relation_trio trio = TRIO_VARYING) const final override
1951 : {
1952 173527 : if (op1.known_isnan () || op2.known_isnan ())
1953 : {
1954 49 : r = range_true (type);
1955 49 : return true;
1956 : }
1957 173478 : frange op1_no_nan = op1;
1958 173478 : frange op2_no_nan = op2;
1959 186990 : if (op1.maybe_isnan ())
1960 159905 : op1_no_nan.clear_nan ();
1961 339849 : if (op2.maybe_isnan ())
1962 7101 : op2_no_nan.clear_nan ();
1963 173478 : if (!range_op_handler (GE_EXPR).fold_range (r, type, op1_no_nan,
1964 : op2_no_nan, trio))
1965 : return false;
1966 : // The result is the same as the ordered version when the
1967 : // comparison is true or when the operands cannot be NANs.
1968 173478 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1969 : return true;
1970 : else
1971 : {
1972 160027 : r = range_true_and_false (type);
1973 160027 : return true;
1974 : }
1975 173478 : }
1976 : bool op1_range (frange &r, tree type,
1977 : const irange &lhs, const frange &op2,
1978 : relation_trio = TRIO_VARYING) const final override;
1979 : bool op2_range (frange &r, tree type,
1980 : const irange &lhs, const frange &op1,
1981 : relation_trio = TRIO_VARYING) const final override;
1982 : } fop_unordered_ge;
1983 :
1984 : bool
1985 144669 : foperator_unordered_ge::op1_range (frange &r,
1986 : tree type,
1987 : const irange &lhs,
1988 : const frange &op2,
1989 : relation_trio) const
1990 : {
1991 144669 : switch (get_bool_state (r, lhs, type))
1992 : {
1993 61425 : case BRS_TRUE:
1994 118205 : if (op2.maybe_isnan ())
1995 4645 : r.set_varying (type);
1996 56780 : else if (op2.undefined_p ())
1997 : return false;
1998 : else
1999 56780 : build_ge (r, type, op2);
2000 : break;
2001 :
2002 82538 : case BRS_FALSE:
2003 : // A false UNORDERED_GE means both operands are !NAN, so it's
2004 : // impossible for op2 to be a NAN.
2005 82538 : if (op2.known_isnan ())
2006 0 : r.set_undefined ();
2007 82538 : else if (op2.undefined_p ())
2008 : return false;
2009 82538 : else if (build_lt (r, type, op2))
2010 82534 : r.clear_nan ();
2011 : break;
2012 :
2013 : default:
2014 : break;
2015 : }
2016 : return true;
2017 : }
2018 :
2019 : bool
2020 14835 : foperator_unordered_ge::op2_range (frange &r, tree type,
2021 : const irange &lhs,
2022 : const frange &op1,
2023 : relation_trio) const
2024 : {
2025 14835 : switch (get_bool_state (r, lhs, type))
2026 : {
2027 8861 : case BRS_TRUE:
2028 13235 : if (op1.maybe_isnan ())
2029 4487 : r.set_varying (type);
2030 4374 : else if (op1.undefined_p ())
2031 : return false;
2032 : else
2033 4374 : build_le (r, type, op1);
2034 : break;
2035 :
2036 5388 : case BRS_FALSE:
2037 : // A false UNORDERED_GE means both operands are !NAN, so it's
2038 : // impossible for op1 to be a NAN.
2039 5388 : if (op1.known_isnan ())
2040 0 : r.set_undefined ();
2041 5388 : else if (op1.undefined_p ())
2042 : return false;
2043 5388 : else if (build_gt (r, type, op1))
2044 5388 : r.clear_nan ();
2045 : break;
2046 :
2047 : default:
2048 : break;
2049 : }
2050 : return true;
2051 : }
2052 :
2053 : class foperator_unordered_equal : public range_operator
2054 : {
2055 : using range_operator::fold_range;
2056 : using range_operator::op1_range;
2057 : using range_operator::op2_range;
2058 : public:
2059 3633 : bool fold_range (irange &r, tree type,
2060 : const frange &op1, const frange &op2,
2061 : relation_trio trio = TRIO_VARYING) const final override
2062 : {
2063 3633 : if (op1.known_isnan () || op2.known_isnan ())
2064 : {
2065 0 : r = range_true (type);
2066 0 : return true;
2067 : }
2068 3633 : frange op1_no_nan = op1;
2069 3633 : frange op2_no_nan = op2;
2070 3953 : if (op1.maybe_isnan ())
2071 3313 : op1_no_nan.clear_nan ();
2072 4054 : if (op2.maybe_isnan ())
2073 3212 : op2_no_nan.clear_nan ();
2074 3633 : if (!range_op_handler (EQ_EXPR).fold_range (r, type, op1_no_nan,
2075 : op2_no_nan, trio))
2076 : return false;
2077 : // The result is the same as the ordered version when the
2078 : // comparison is true or when the operands cannot be NANs.
2079 3633 : if (!maybe_isnan (op1, op2) || r == range_true (type))
2080 : return true;
2081 : else
2082 : {
2083 3312 : r = range_true_and_false (type);
2084 3312 : return true;
2085 : }
2086 3633 : }
2087 : bool op1_range (frange &r, tree type,
2088 : const irange &lhs, const frange &op2,
2089 : relation_trio = TRIO_VARYING) const final override;
2090 632 : bool op2_range (frange &r, tree type,
2091 : const irange &lhs, const frange &op1,
2092 : relation_trio rel = TRIO_VARYING) const final override
2093 : {
2094 632 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2095 : }
2096 : } fop_unordered_equal;
2097 :
2098 : bool
2099 1267 : foperator_unordered_equal::op1_range (frange &r, tree type,
2100 : const irange &lhs,
2101 : const frange &op2,
2102 : relation_trio) const
2103 : {
2104 1267 : switch (get_bool_state (r, lhs, type))
2105 : {
2106 3 : case BRS_TRUE:
2107 : // If it's true, the result is the same as OP2 plus a NAN.
2108 3 : r = op2;
2109 : // Add both zeros if there's the possibility of zero equality.
2110 3 : frange_add_zeros (r, type);
2111 : // Add the possibility of a NAN.
2112 3 : r.update_nan ();
2113 3 : break;
2114 :
2115 0 : case BRS_FALSE:
2116 : // A false UNORDERED_EQ means both operands are !NAN, so it's
2117 : // impossible for op2 to be a NAN.
2118 0 : if (op2.known_isnan ())
2119 0 : r.set_undefined ();
2120 : else
2121 : {
2122 : // The false side indicates !NAN and not equal. We can at least
2123 : // represent !NAN.
2124 0 : r.set_varying (type);
2125 0 : r.clear_nan ();
2126 : }
2127 : break;
2128 :
2129 : default:
2130 : break;
2131 : }
2132 1267 : return true;
2133 : }
2134 :
2135 : class foperator_ltgt : public range_operator
2136 : {
2137 : using range_operator::fold_range;
2138 : using range_operator::op1_range;
2139 : using range_operator::op2_range;
2140 : public:
2141 2143 : bool fold_range (irange &r, tree type,
2142 : const frange &op1, const frange &op2,
2143 : relation_trio trio = TRIO_VARYING) const final override
2144 : {
2145 2143 : if (op1.known_isnan () || op2.known_isnan ())
2146 : {
2147 2 : r = range_false (type);
2148 2 : return true;
2149 : }
2150 2141 : frange op1_no_nan = op1;
2151 2141 : frange op2_no_nan = op2;
2152 2461 : if (op1.maybe_isnan ())
2153 1805 : op1_no_nan.clear_nan ();
2154 2461 : if (op2.maybe_isnan ())
2155 1805 : op2_no_nan.clear_nan ();
2156 2141 : if (!range_op_handler (NE_EXPR).fold_range (r, type, op1_no_nan,
2157 : op2_no_nan, trio))
2158 : return false;
2159 : // The result is the same as the ordered version when the
2160 : // comparison is true or when the operands cannot be NANs.
2161 2141 : if (!maybe_isnan (op1, op2) || r == range_false (type))
2162 : return true;
2163 : else
2164 : {
2165 1805 : r = range_true_and_false (type);
2166 1805 : return true;
2167 : }
2168 2141 : }
2169 : bool op1_range (frange &r, tree type,
2170 : const irange &lhs, const frange &op2,
2171 : relation_trio = TRIO_VARYING) const final override;
2172 794 : 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 794 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2177 : }
2178 : } fop_ltgt;
2179 :
2180 : bool
2181 1578 : foperator_ltgt::op1_range (frange &r, tree type,
2182 : const irange &lhs,
2183 : const frange &op2,
2184 : relation_trio) const
2185 : {
2186 1578 : switch (get_bool_state (r, lhs, type))
2187 : {
2188 0 : case BRS_TRUE:
2189 : // A true LTGT means both operands are !NAN, so it's
2190 : // impossible for op2 to be a NAN.
2191 0 : if (op2.known_isnan ())
2192 0 : r.set_undefined ();
2193 : else
2194 : {
2195 : // The true side indicates !NAN and not equal. We can at least
2196 : // represent !NAN.
2197 0 : r.set_varying (type);
2198 0 : r.clear_nan ();
2199 : }
2200 : break;
2201 :
2202 10 : case BRS_FALSE:
2203 : // If it's false, the result is the same as OP2 plus a NAN.
2204 10 : r = op2;
2205 : // Add both zeros if there's the possibility of zero equality.
2206 10 : frange_add_zeros (r, type);
2207 : // Add the possibility of a NAN.
2208 10 : r.update_nan ();
2209 10 : break;
2210 :
2211 : default:
2212 : break;
2213 : }
2214 1578 : return true;
2215 : }
2216 :
2217 : // Final tweaks for float binary op op1_range/op2_range.
2218 : // Return TRUE if the operation is performed and a valid range is available.
2219 :
2220 : static bool
2221 933635 : float_binary_op_range_finish (bool ret, frange &r, tree type,
2222 : const frange &lhs, bool div_op2 = false)
2223 : {
2224 933635 : if (!ret)
2225 : return false;
2226 :
2227 : // If we get a known NAN from reverse op, it means either that
2228 : // the other operand was known NAN (in that case we know nothing),
2229 : // or the reverse operation introduced a known NAN.
2230 : // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
2231 : // 0 / 0 is known NAN. Just punt in that case.
2232 : // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
2233 : // Or if lhs is a known NAN, we also don't know anything.
2234 933635 : if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
2235 : {
2236 7033 : r.set_varying (type);
2237 7033 : 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 1690546 : if (!lhs.maybe_isnan ())
2243 : {
2244 763944 : r.clear_nan ();
2245 763944 : if (div_op2
2246 788237 : ? !(real_compare (LE_EXPR, &lhs.lower_bound (), &dconst0)
2247 24293 : && real_compare (GE_EXPR, &lhs.upper_bound (), &dconst0))
2248 1340433 : : !(real_isinf (&lhs.lower_bound ())
2249 608158 : || 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 588222 : frange_drop_infs (r, type);
2256 : }
2257 : // If lhs is a maybe or known NAN, the operand could be
2258 : // NAN.
2259 : else
2260 162658 : r.update_nan ();
2261 : return true;
2262 : }
2263 :
2264 : // True if [lb, ub] is [+-0, +-0].
2265 : static bool
2266 5218532 : zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2267 : {
2268 5218532 : return real_iszero (&lb) && real_iszero (&ub);
2269 : }
2270 :
2271 : // True if +0 or -0 is in [lb, ub] range.
2272 : static bool
2273 4353159 : contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2274 : {
2275 4353159 : return (real_compare (LE_EXPR, &lb, &dconst0)
2276 4353159 : && real_compare (GE_EXPR, &ub, &dconst0));
2277 : }
2278 :
2279 : // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
2280 : static bool
2281 2955299 : singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2282 : {
2283 2955299 : 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.
2291 : static int
2292 1314844 : signbit_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 1314844 : if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
2296 1314844 : && real_isneg (&rh_lb) == real_isneg (&rh_ub))
2297 : {
2298 111983 : if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
2299 : return 1;
2300 : else
2301 6552 : 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.
2308 : static void
2309 6180 : zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2310 : {
2311 6180 : ub = lb = dconst0;
2312 6180 : if (signbit_known <= 0)
2313 6110 : lb = dconstm0;
2314 6110 : if (signbit_known < 0)
2315 42 : ub = lb;
2316 6180 : }
2317 :
2318 : // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
2319 : // signbit_known.
2320 : static void
2321 4319 : inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2322 : {
2323 4319 : if (signbit_known > 0)
2324 950 : ub = lb = dconstinf;
2325 3369 : else if (signbit_known < 0)
2326 96 : ub = lb = dconstninf;
2327 : else
2328 : {
2329 3273 : lb = dconstninf;
2330 3273 : ub = dconstinf;
2331 : }
2332 4319 : }
2333 :
2334 : // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
2335 : // signbit_known.
2336 : static void
2337 928080 : zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2338 : {
2339 928080 : if (signbit_known > 0)
2340 : {
2341 10259 : lb = dconst0;
2342 10259 : ub = dconstinf;
2343 : }
2344 917821 : else if (signbit_known < 0)
2345 : {
2346 222 : lb = dconstninf;
2347 222 : ub = dconstm0;
2348 : }
2349 : else
2350 : {
2351 917599 : lb = dconstninf;
2352 917599 : ub = dconstinf;
2353 : }
2354 928080 : }
2355 :
2356 : /* Extend the LHS range by 1ulp in each direction. For op1_range
2357 : or op2_range of binary operations just computing the inverse
2358 : operation on ranges isn't sufficient. Consider e.g.
2359 : [1., 1.] = op1 + [1., 1.]. op1's range is not [0., 0.], but
2360 : [-0x1.0p-54, 0x1.0p-53] (when not -frounding-math), any value for
2361 : which adding 1. to it results in 1. after rounding to nearest.
2362 : So, for op1_range/op2_range extend the lhs range by 1ulp (or 0.5ulp)
2363 : in each direction. See PR109008 for more details. */
2364 :
2365 : static frange
2366 905672 : float_widen_lhs_range (tree type, const frange &lhs)
2367 : {
2368 905672 : frange ret = lhs;
2369 905672 : if (lhs.known_isnan ())
2370 : return ret;
2371 898640 : REAL_VALUE_TYPE lb = lhs.lower_bound ();
2372 898640 : REAL_VALUE_TYPE ub = lhs.upper_bound ();
2373 898640 : if (real_isfinite (&lb))
2374 : {
2375 714948 : frange_nextafter (TYPE_MODE (type), lb, dconstninf);
2376 714948 : 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 55357 : lb = dconstm1;
2385 221428 : SET_REAL_EXP (&lb, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
2386 : }
2387 5004636 : 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 714948 : REAL_VALUE_TYPE tem;
2392 714948 : real_arithmetic (&tem, PLUS_EXPR, &lhs.lower_bound (), &lb);
2393 714948 : real_arithmetic (&lb, RDIV_EXPR, &tem, &dconst2);
2394 : }
2395 : }
2396 898640 : if (real_isfinite (&ub))
2397 : {
2398 646116 : frange_nextafter (TYPE_MODE (type), ub, dconstinf);
2399 646116 : if (real_isinf (&ub))
2400 : {
2401 : /* For DBL_MAX similarly. */
2402 56042 : ub = dconst1;
2403 224168 : SET_REAL_EXP (&ub, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
2404 : }
2405 4522812 : 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 646116 : REAL_VALUE_TYPE tem;
2410 646116 : real_arithmetic (&tem, PLUS_EXPR, &lhs.upper_bound (), &ub);
2411 646116 : real_arithmetic (&ub, RDIV_EXPR, &tem, &dconst2);
2412 : }
2413 : }
2414 : /* Temporarily disable -ffinite-math-only, so that frange::set doesn't
2415 : reduce the range back to real_min_representable (type) as lower bound
2416 : or real_max_representable (type) as upper bound. */
2417 898640 : bool save_flag_finite_math_only = flag_finite_math_only;
2418 898640 : flag_finite_math_only = false;
2419 898640 : ret.set (type, lb, ub, lhs.get_nan_state ());
2420 898640 : flag_finite_math_only = save_flag_finite_math_only;
2421 898640 : return ret;
2422 : }
2423 :
2424 : bool
2425 166175 : operator_plus::op1_range (frange &r, tree type, const frange &lhs,
2426 : const frange &op2, relation_trio) const
2427 : {
2428 166175 : if (lhs.undefined_p ())
2429 : return false;
2430 166175 : range_op_handler minus (MINUS_EXPR);
2431 166175 : if (!minus)
2432 : return false;
2433 166175 : frange wlhs = float_widen_lhs_range (type, lhs);
2434 166175 : return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
2435 : r, type, wlhs);
2436 166175 : }
2437 :
2438 : bool
2439 71515 : operator_plus::op2_range (frange &r, tree type,
2440 : const frange &lhs, const frange &op1,
2441 : relation_trio) const
2442 : {
2443 71515 : return op1_range (r, type, lhs, op1);
2444 : }
2445 :
2446 : void
2447 2456934 : operator_plus::rv_fold (frange &r, tree type,
2448 : const REAL_VALUE_TYPE &lh_lb,
2449 : const REAL_VALUE_TYPE &lh_ub,
2450 : const REAL_VALUE_TYPE &rh_lb,
2451 : const REAL_VALUE_TYPE &rh_ub,
2452 : relation_kind) const
2453 : {
2454 2456934 : REAL_VALUE_TYPE lb, ub;
2455 2456934 : bool maybe_nan = false;
2456 :
2457 2456934 : frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
2458 2456934 : frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
2459 :
2460 : // [-INF] + [+INF] = NAN
2461 2456934 : if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
2462 : maybe_nan = true;
2463 : // [+INF] + [-INF] = NAN
2464 798278 : else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
2465 : maybe_nan = true;
2466 :
2467 : // Handle possible NANs by saturating to the appropriate INF if only
2468 : // one end is a NAN. If both ends are a NAN, just return a NAN.
2469 2456934 : bool lb_nan = real_isnan (&lb);
2470 2456934 : bool ub_nan = real_isnan (&ub);
2471 2456934 : if (lb_nan && ub_nan)
2472 : {
2473 0 : r.set_nan (type);
2474 0 : return;
2475 : }
2476 2456934 : if (lb_nan)
2477 374 : lb = dconstninf;
2478 2456560 : else if (ub_nan)
2479 0 : ub = dconstinf;
2480 2456934 : r.set (type, lb, ub, nan_state (maybe_nan));
2481 : }
2482 :
2483 :
2484 : bool
2485 91979 : operator_minus::op1_range (frange &r, tree type,
2486 : const frange &lhs, const frange &op2,
2487 : relation_trio) const
2488 : {
2489 91979 : if (lhs.undefined_p ())
2490 : return false;
2491 91979 : frange wlhs = float_widen_lhs_range (type, lhs);
2492 91979 : return float_binary_op_range_finish (
2493 183958 : range_op_handler (PLUS_EXPR).fold_range (r, type, wlhs, op2),
2494 : r, type, wlhs);
2495 91979 : }
2496 :
2497 : bool
2498 178153 : operator_minus::op2_range (frange &r, tree type,
2499 : const frange &lhs, const frange &op1,
2500 : relation_trio) const
2501 : {
2502 178153 : if (lhs.undefined_p ())
2503 : return false;
2504 178153 : frange wlhs = float_widen_lhs_range (type, lhs);
2505 178153 : return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
2506 : r, type, wlhs);
2507 178153 : }
2508 :
2509 : void
2510 978981 : operator_minus::rv_fold (frange &r, tree type,
2511 : const REAL_VALUE_TYPE &lh_lb,
2512 : const REAL_VALUE_TYPE &lh_ub,
2513 : const REAL_VALUE_TYPE &rh_lb,
2514 : const REAL_VALUE_TYPE &rh_ub,
2515 : relation_kind) const
2516 : {
2517 978981 : REAL_VALUE_TYPE lb, ub;
2518 978981 : bool maybe_nan = false;
2519 :
2520 978981 : frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
2521 978981 : frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
2522 :
2523 : // [+INF] - [+INF] = NAN
2524 978981 : if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
2525 : maybe_nan = true;
2526 : // [-INF] - [-INF] = NAN
2527 694965 : else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
2528 : maybe_nan = true;
2529 :
2530 : // Handle possible NANs by saturating to the appropriate INF if only
2531 : // one end is a NAN. If both ends are a NAN, just return a NAN.
2532 978981 : bool lb_nan = real_isnan (&lb);
2533 978981 : bool ub_nan = real_isnan (&ub);
2534 978981 : if (lb_nan && ub_nan)
2535 : {
2536 0 : r.set_nan (type);
2537 0 : return;
2538 : }
2539 978981 : if (lb_nan)
2540 182 : lb = dconstninf;
2541 978799 : else if (ub_nan)
2542 310 : ub = dconstinf;
2543 978981 : r.set (type, lb, ub, nan_state (maybe_nan));
2544 : }
2545 :
2546 :
2547 : // Given CP[0] to CP[3] floating point values rounded to -INF,
2548 : // set LB to the smallest of them (treating -0 as smaller to +0).
2549 : // Given CP[4] to CP[7] floating point values rounded to +INF,
2550 : // set UB to the largest of them (treating -0 as smaller to +0).
2551 :
2552 : static void
2553 1131407 : find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
2554 : const REAL_VALUE_TYPE (&cp)[8])
2555 : {
2556 1131407 : lb = cp[0];
2557 1131407 : ub = cp[4];
2558 4525628 : for (int i = 1; i < 4; ++i)
2559 : {
2560 3394221 : if (real_less (&cp[i], &lb)
2561 3394221 : || (real_iszero (&lb) && real_isnegzero (&cp[i])))
2562 357499 : lb = cp[i];
2563 3394221 : if (real_less (&ub, &cp[i + 4])
2564 3394221 : || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
2565 1107261 : ub = cp[i + 4];
2566 : }
2567 1131407 : }
2568 :
2569 :
2570 : bool
2571 369824 : operator_mult::op1_range (frange &r, tree type,
2572 : const frange &lhs, const frange &op2,
2573 : relation_trio) const
2574 : {
2575 369824 : if (lhs.undefined_p ())
2576 : return false;
2577 369824 : range_op_handler rdiv (RDIV_EXPR);
2578 369824 : if (!rdiv)
2579 : return false;
2580 369824 : frange wlhs = float_widen_lhs_range (type, lhs);
2581 369824 : bool ret = rdiv.fold_range (r, type, wlhs, op2);
2582 369824 : if (ret == false)
2583 : return false;
2584 369824 : if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2585 16 : return float_binary_op_range_finish (ret, r, type, wlhs);
2586 369808 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2587 369808 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2588 369808 : const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2589 369808 : const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2590 691261 : if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
2591 556135 : || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2592 40543 : && (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 142387 : REAL_VALUE_TYPE lb, ub;
2598 142387 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2599 142387 : zero_to_inf_range (lb, ub, signbit_known);
2600 142387 : 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 369808 : return float_binary_op_range_finish (ret, r, type, wlhs);
2607 369824 : }
2608 :
2609 : bool
2610 79626 : operator_mult::op2_range (frange &r, tree type,
2611 : const frange &lhs, const frange &op1,
2612 : relation_trio) const
2613 : {
2614 79626 : return op1_range (r, type, lhs, op1);
2615 : }
2616 :
2617 : void
2618 1172978 : operator_mult::rv_fold (frange &r, tree type,
2619 : const REAL_VALUE_TYPE &lh_lb,
2620 : const REAL_VALUE_TYPE &lh_ub,
2621 : const REAL_VALUE_TYPE &rh_lb,
2622 : const REAL_VALUE_TYPE &rh_ub,
2623 : relation_kind kind) const
2624 : {
2625 1172978 : bool is_square
2626 : = (kind == VREL_EQ
2627 37072 : && real_equal (&lh_lb, &rh_lb)
2628 37072 : && real_equal (&lh_ub, &rh_ub)
2629 37072 : && real_isneg (&lh_lb) == real_isneg (&rh_lb)
2630 1210050 : && real_isneg (&lh_ub) == real_isneg (&rh_ub));
2631 1135906 : REAL_VALUE_TYPE lb, ub;
2632 1891048 : bool maybe_nan = false;
2633 : // x * x never produces a new NAN and we only multiply the same
2634 : // values, so the 0 * INF problematic cases never appear there.
2635 1135906 : if (!is_square)
2636 : {
2637 : // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2638 1141290 : if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
2639 1141284 : || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
2640 : {
2641 37 : r.set_nan (type);
2642 417836 : return;
2643 : }
2644 :
2645 : // Otherwise, if one range includes zero and the other ends with +-INF,
2646 : // it is a maybe NAN.
2647 1135869 : if ((contains_zero_p (lh_lb, lh_ub)
2648 1031955 : && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2649 1777908 : || (contains_zero_p (rh_lb, rh_ub)
2650 202246 : && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
2651 : {
2652 417799 : maybe_nan = true;
2653 :
2654 417799 : 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 417799 : if (singleton_inf_p (lh_lb, lh_ub)
2662 417799 : || singleton_inf_p (rh_lb, rh_ub))
2663 : {
2664 988 : inf_range (lb, ub, signbit_known);
2665 988 : r.set (type, lb, ub, nan_state (true));
2666 988 : return;
2667 : }
2668 :
2669 : // If one of the multiplicands must be zero, the resulting
2670 : // range is +-0 and NAN.
2671 416811 : if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
2672 : {
2673 5650 : zero_range (lb, ub, signbit_known);
2674 5650 : r.set (type, lb, ub, nan_state (true));
2675 5650 : return;
2676 : }
2677 :
2678 : // Otherwise one of the multiplicands could be
2679 : // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
2680 : // or similarly with different signs. 0.0 * DBL_MAX
2681 : // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
2682 : // so if the signs are always the same or always different,
2683 : // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
2684 411161 : zero_to_inf_range (lb, ub, signbit_known);
2685 411161 : r.set (type, lb, ub, nan_state (true));
2686 411161 : return;
2687 : }
2688 : }
2689 :
2690 755142 : REAL_VALUE_TYPE cp[8];
2691 : // Do a cross-product. At this point none of the multiplications
2692 : // should produce a NAN.
2693 755142 : frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2694 755142 : frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2695 755142 : 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 37072 : if (contains_zero_p (lh_lb, lh_ub))
2703 : {
2704 34040 : if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
2705 1135 : cp[1] = dconst0;
2706 : else
2707 32905 : cp[1] = dconstm0;
2708 : }
2709 : else
2710 3032 : cp[1] = cp[0];
2711 37072 : cp[2] = cp[0];
2712 37072 : cp[5] = cp[4];
2713 37072 : cp[6] = cp[4];
2714 : }
2715 : else
2716 : {
2717 718070 : frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2718 718070 : frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2719 718070 : frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2720 718070 : frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2721 : }
2722 755142 : frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2723 755142 : frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2724 :
2725 755142 : find_range (lb, ub, cp);
2726 :
2727 755142 : gcc_checking_assert (!real_isnan (&lb));
2728 755142 : gcc_checking_assert (!real_isnan (&ub));
2729 755142 : r.set (type, lb, ub, nan_state (maybe_nan));
2730 : }
2731 :
2732 :
2733 : class foperator_div : public range_operator
2734 : {
2735 : using range_operator::op1_range;
2736 : using range_operator::op2_range;
2737 : public:
2738 24673 : 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 24673 : if (lhs.undefined_p ())
2744 : return false;
2745 24673 : frange wlhs = float_widen_lhs_range (type, lhs);
2746 24673 : bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
2747 24673 : if (!ret)
2748 : return ret;
2749 24673 : if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2750 4 : return float_binary_op_range_finish (ret, r, type, wlhs);
2751 24669 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2752 24669 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2753 24669 : const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2754 24669 : const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2755 24669 : if ((contains_zero_p (lhs_lb, lhs_ub)
2756 17231 : && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
2757 31096 : || ((contains_zero_p (op2_lb, op2_ub))
2758 8188 : && (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 18510 : REAL_VALUE_TYPE lb, ub;
2764 18510 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2765 18510 : zero_to_inf_range (lb, ub, signbit_known);
2766 18510 : r.set (type, lb, ub);
2767 : }
2768 24669 : return float_binary_op_range_finish (ret, r, type, wlhs);
2769 24673 : }
2770 41111 : 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 41111 : if (lhs.undefined_p ())
2776 : return false;
2777 41111 : frange wlhs = float_widen_lhs_range (type, lhs);
2778 41111 : bool ret = fold_range (r, type, op1, wlhs);
2779 41111 : if (!ret)
2780 : return ret;
2781 41111 : if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
2782 20 : return float_binary_op_range_finish (ret, r, type, wlhs, true);
2783 41091 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2784 41091 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2785 41091 : const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
2786 41091 : const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
2787 72275 : if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
2788 44569 : || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2789 7626 : && (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 32018 : REAL_VALUE_TYPE lb, ub;
2795 32018 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
2796 32018 : zero_to_inf_range (lb, ub, signbit_known);
2797 32018 : r.set (type, lb, ub);
2798 : }
2799 41091 : return float_binary_op_range_finish (ret, r, type, wlhs, true);
2800 41111 : }
2801 : private:
2802 704715 : void rv_fold (frange &r, tree type,
2803 : const REAL_VALUE_TYPE &lh_lb,
2804 : const REAL_VALUE_TYPE &lh_ub,
2805 : const REAL_VALUE_TYPE &rh_lb,
2806 : const REAL_VALUE_TYPE &rh_ub,
2807 : relation_kind) const final override
2808 : {
2809 : // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
2810 705822 : if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
2811 705243 : || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
2812 : {
2813 585 : r.set_nan (type);
2814 328450 : return;
2815 : }
2816 :
2817 704130 : REAL_VALUE_TYPE lb, ub;
2818 704130 : bool maybe_nan = false;
2819 : // If +-0.0 is in both ranges, it is a maybe NAN.
2820 704130 : if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
2821 : maybe_nan = true;
2822 : // If +-INF is in both ranges, it is a maybe NAN.
2823 728780 : else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
2824 421972 : && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2825 : maybe_nan = true;
2826 :
2827 704130 : int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2828 :
2829 : // If dividend must be zero, the range is just +-0
2830 : // (including if the divisor is +-INF).
2831 : // If divisor must be +-INF, the range is just +-0
2832 : // (including if the dividend is zero).
2833 704130 : if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
2834 : {
2835 530 : zero_range (lb, ub, signbit_known);
2836 530 : r.set (type, lb, ub, nan_state (maybe_nan));
2837 530 : return;
2838 : }
2839 :
2840 : // If divisor must be zero, the range is just +-INF
2841 : // (including if the dividend is +-INF).
2842 : // If dividend must be +-INF, the range is just +-INF
2843 : // (including if the dividend is zero).
2844 703600 : if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
2845 : {
2846 3331 : inf_range (lb, ub, signbit_known);
2847 3331 : r.set (type, lb, ub, nan_state (maybe_nan));
2848 3331 : return;
2849 : }
2850 :
2851 : // Otherwise if both operands may be zero, divisor could be
2852 : // nextafter(0.0, +-1.0) and dividend +-0.0
2853 : // in which case result is going to INF or vice versa and
2854 : // result +0.0. So, all we can say for that case is if the
2855 : // signs of divisor and dividend are always the same we have
2856 : // [+0.0, +INF], if they are always different we have
2857 : // [-INF, -0.0]. If they vary, VARYING.
2858 : // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
2859 : // in which case result is going to INF or vice versa and
2860 : // result +0.0. So, all we can say for that case is if the
2861 : // signs of divisor and dividend are always the same we have
2862 : // [+0.0, +INF], if they are always different we have
2863 : // [-INF, -0.0]. If they vary, VARYING.
2864 700269 : if (maybe_nan)
2865 : {
2866 324004 : zero_to_inf_range (lb, ub, signbit_known);
2867 324004 : r.set (type, lb, ub, nan_state (maybe_nan));
2868 324004 : return;
2869 : }
2870 :
2871 376265 : REAL_VALUE_TYPE cp[8];
2872 : // Do a cross-division. At this point none of the divisions should
2873 : // produce a NAN.
2874 376265 : frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2875 376265 : frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2876 376265 : frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2877 376265 : frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2878 376265 : frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2879 376265 : frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2880 376265 : frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2881 376265 : frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2882 :
2883 376265 : find_range (lb, ub, cp);
2884 :
2885 : // If divisor may be zero (but is not known to be only zero),
2886 : // and dividend can't be zero, the range can go up to -INF or +INF
2887 : // depending on the signs.
2888 376265 : if (contains_zero_p (rh_lb, rh_ub))
2889 : {
2890 50154 : if (signbit_known <= 0)
2891 47731 : real_inf (&lb, true);
2892 47731 : if (signbit_known >= 0)
2893 50118 : real_inf (&ub, false);
2894 : }
2895 :
2896 376265 : gcc_checking_assert (!real_isnan (&lb));
2897 376265 : gcc_checking_assert (!real_isnan (&ub));
2898 376265 : r.set (type, lb, ub, nan_state (maybe_nan));
2899 : }
2900 : } fop_div;
2901 :
2902 : bool
2903 945348 : operator_cast::fold_range (frange &r, tree type, const frange &op1,
2904 : const frange &, relation_trio) const
2905 : {
2906 945348 : REAL_VALUE_TYPE lb, ub;
2907 945348 : enum machine_mode mode = TYPE_MODE (type);
2908 6617436 : bool mode_composite = MODE_COMPOSITE_P (mode);
2909 :
2910 945348 : if (empty_range_varying (r, type, op1, op1))
2911 819 : return true;
2912 3778116 : if (!MODE_HAS_NANS (mode) && op1.maybe_isnan ())
2913 : {
2914 0 : r.set_varying (type);
2915 0 : return true;
2916 : }
2917 944529 : if (op1.known_isnan ())
2918 : {
2919 3004 : r.set_nan (type);
2920 3004 : return true;
2921 : }
2922 :
2923 941525 : const REAL_VALUE_TYPE &lh_lb = op1.lower_bound ();
2924 941525 : const REAL_VALUE_TYPE &lh_ub = op1.upper_bound ();
2925 941525 : real_convert (&lb, mode, &lh_lb);
2926 941525 : real_convert (&ub, mode, &lh_ub);
2927 :
2928 941525 : if (flag_rounding_math)
2929 : {
2930 31161 : if (real_less (&lh_lb, &lb))
2931 : {
2932 2668 : if (mode_composite
2933 2668 : && (real_isdenormal (&lb, mode) || real_iszero (&lb)))
2934 : {
2935 : // IBM extended denormals only have DFmode precision.
2936 0 : REAL_VALUE_TYPE tmp, tmp2;
2937 0 : real_convert (&tmp2, DFmode, &lh_lb);
2938 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
2939 : &dconstninf);
2940 0 : real_convert (&lb, mode, &tmp);
2941 : }
2942 : else
2943 2668 : frange_nextafter (mode, lb, dconstninf);
2944 : }
2945 31161 : if (real_less (&ub, &lh_ub))
2946 : {
2947 1070 : if (mode_composite
2948 1070 : && (real_isdenormal (&ub, mode) || real_iszero (&ub)))
2949 : {
2950 : // IBM extended denormals only have DFmode precision.
2951 0 : REAL_VALUE_TYPE tmp, tmp2;
2952 0 : real_convert (&tmp2, DFmode, &lh_ub);
2953 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
2954 : &dconstinf);
2955 0 : real_convert (&ub, mode, &tmp);
2956 : }
2957 : else
2958 1070 : frange_nextafter (mode, ub, dconstinf);
2959 : }
2960 : }
2961 :
2962 941525 : r.set (type, lb, ub, op1.get_nan_state ());
2963 :
2964 941525 : if (flag_trapping_math
2965 4248080 : && MODE_HAS_INFINITIES (TYPE_MODE (type))
2966 826639 : && r.known_isinf ()
2967 941599 : && !op1.known_isinf ())
2968 : {
2969 1 : REAL_VALUE_TYPE inf = r.lower_bound ();
2970 1 : if (real_isneg (&inf))
2971 : {
2972 0 : REAL_VALUE_TYPE min = real_min_representable (type);
2973 0 : r.set (type, inf, min);
2974 : }
2975 : else
2976 : {
2977 1 : REAL_VALUE_TYPE max = real_max_representable (type);
2978 1 : r.set (type, max, inf);
2979 : }
2980 : }
2981 :
2982 941525 : r.flush_denormals_to_zero ();
2983 941525 : return true;
2984 : }
2985 :
2986 : // Implement fold for a cast from float to another float.
2987 : bool
2988 61720 : operator_cast::op1_range (frange &r, tree type, const frange &lhs,
2989 : const frange &op2, relation_trio) const
2990 : {
2991 61720 : if (lhs.undefined_p ())
2992 : return false;
2993 61720 : tree lhs_type = lhs.type ();
2994 61720 : enum machine_mode mode = TYPE_MODE (type);
2995 61720 : enum machine_mode lhs_mode = TYPE_MODE (lhs_type);
2996 61720 : frange wlhs;
2997 61720 : bool rm;
2998 61720 : if (REAL_MODE_FORMAT (mode)->ieee_bits
2999 57356 : && REAL_MODE_FORMAT (lhs_mode)->ieee_bits
3000 54134 : && (REAL_MODE_FORMAT (lhs_mode)->ieee_bits
3001 : >= REAL_MODE_FORMAT (mode)->ieee_bits)
3002 89683 : && pow2p_hwi (REAL_MODE_FORMAT (mode)->ieee_bits))
3003 : {
3004 : /* If the cast is widening from IEEE exchange mode to
3005 : wider exchange mode or extended mode, no need to extend
3006 : the range on reverse operation. */
3007 27963 : rm = false;
3008 27963 : wlhs = lhs;
3009 : }
3010 : else
3011 : {
3012 33757 : rm = true;
3013 33757 : wlhs = float_widen_lhs_range (lhs_type, lhs);
3014 : }
3015 61720 : auto save_flag_rounding_math = flag_rounding_math;
3016 61720 : flag_rounding_math = rm;
3017 61720 : bool ret = float_binary_op_range_finish (fold_range (r, type, wlhs, op2),
3018 : r, type, lhs);
3019 61720 : flag_rounding_math = save_flag_rounding_math;
3020 61720 : return ret;
3021 61720 : }
3022 :
3023 : // Implement fold for a cast from float to an int.
3024 : bool
3025 208702 : operator_cast::fold_range (irange &r, tree type, const frange &op1,
3026 : const irange &, relation_trio) const
3027 : {
3028 208702 : if (empty_range_varying (r, type, op1, op1))
3029 541 : return true;
3030 208161 : if (op1.maybe_isnan () || op1.maybe_isinf ())
3031 : {
3032 182057 : r.set_varying (type);
3033 182057 : return true;
3034 : }
3035 26104 : REAL_VALUE_TYPE lb, ub;
3036 26104 : real_trunc (&lb, VOIDmode, &op1.lower_bound ());
3037 26104 : real_trunc (&ub, VOIDmode, &op1.upper_bound ());
3038 26104 : REAL_VALUE_TYPE l, u;
3039 26104 : l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
3040 26104 : if (real_less (&lb, &l))
3041 : {
3042 9430 : r.set_varying (type);
3043 9430 : return true;
3044 : }
3045 16674 : u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
3046 16674 : if (real_less (&u, &ub))
3047 : {
3048 7922 : r.set_varying (type);
3049 7922 : return true;
3050 : }
3051 8752 : bool fail = false;
3052 8752 : wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
3053 8752 : wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
3054 8752 : if (fail)
3055 : {
3056 0 : r.set_varying (type);
3057 0 : return true;
3058 : }
3059 8752 : r.set (type, wlb, wub);
3060 8752 : return true;
3061 8752 : }
3062 :
3063 : // Implement op1_range for a cast from float to an int.
3064 : bool
3065 7165 : operator_cast::op1_range (frange &r, tree type, const irange &lhs,
3066 : const frange &, relation_trio) const
3067 : {
3068 7165 : if (lhs.undefined_p ())
3069 : return false;
3070 7165 : REAL_VALUE_TYPE lb, lbo, ub, ubo;
3071 7165 : wide_int lhs_lb = lhs.lower_bound ();
3072 7165 : wide_int lhs_ub = lhs.upper_bound ();
3073 7165 : tree lhs_type = lhs.type ();
3074 7165 : enum machine_mode mode = TYPE_MODE (type);
3075 7165 : real_from_integer (&lbo, VOIDmode, lhs_lb, TYPE_SIGN (lhs_type));
3076 7165 : real_from_integer (&ubo, VOIDmode, lhs_ub, TYPE_SIGN (lhs_type));
3077 7165 : real_convert (&lb, mode, &lbo);
3078 7165 : real_convert (&ub, mode, &ubo);
3079 7165 : if (real_identical (&lb, &lbo))
3080 : {
3081 : /* If low bound is exactly representable in type,
3082 : use nextafter (lb - 1., +inf). */
3083 7036 : real_arithmetic (&lb, PLUS_EXPR, &lbo, &dconstm1);
3084 7036 : real_convert (&lb, mode, &lb);
3085 7036 : if (!real_identical (&lb, &lbo))
3086 5806 : frange_nextafter (mode, lb, dconstinf);
3087 7036 : if (real_identical (&lb, &lbo))
3088 1232 : frange_nextafter (mode, lb, dconstninf);
3089 : }
3090 129 : else if (real_less (&lbo, &lb))
3091 13 : frange_nextafter (mode, lb, dconstninf);
3092 7165 : if (real_identical (&ub, &ubo))
3093 : {
3094 : /* If upper bound is exactly representable in type,
3095 : use nextafter (ub + 1., -inf). */
3096 5333 : real_arithmetic (&ub, PLUS_EXPR, &ubo, &dconst1);
3097 5333 : real_convert (&ub, mode, &ub);
3098 5333 : if (!real_identical (&ub, &ubo))
3099 5273 : frange_nextafter (mode, ub, dconstninf);
3100 5333 : if (real_identical (&ub, &ubo))
3101 60 : frange_nextafter (mode, ub, dconstinf);
3102 : }
3103 1832 : else if (real_less (&ub, &ubo))
3104 0 : frange_nextafter (mode, ub, dconstinf);
3105 7165 : r.set (type, lb, ub, nan_state (false));
3106 7165 : return true;
3107 7165 : }
3108 :
3109 : // Implement fold for a cast from int to a float.
3110 : bool
3111 840941 : operator_cast::fold_range (frange &r, tree type, const irange &op1,
3112 : const frange &, relation_trio) const
3113 : {
3114 840941 : if (empty_range_varying (r, type, op1, op1))
3115 1402 : return true;
3116 839539 : REAL_VALUE_TYPE lb, ub;
3117 839539 : wide_int op1_lb = op1.lower_bound ();
3118 839539 : wide_int op1_ub = op1.upper_bound ();
3119 839539 : tree op1_type = op1.type ();
3120 839539 : enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
3121 839539 : real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
3122 839539 : real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
3123 839539 : if (flag_rounding_math)
3124 : {
3125 1129 : REAL_VALUE_TYPE lbo = lb, ubo = ub;
3126 1129 : mode = TYPE_MODE (type);
3127 1129 : real_convert (&lb, mode, &lb);
3128 1129 : real_convert (&ub, mode, &ub);
3129 1129 : if (real_less (&lbo, &lb))
3130 322 : frange_nextafter (mode, lb, dconstninf);
3131 1129 : if (real_less (&ub, &ubo))
3132 192 : frange_nextafter (mode, ub, dconstinf);
3133 : }
3134 839539 : r.set (type, lb, ub, nan_state (false));
3135 839539 : frange_drop_infs (r, type);
3136 839539 : if (r.undefined_p ())
3137 4 : r.set_varying (type);
3138 839539 : return true;
3139 839551 : }
3140 :
3141 : // Implement op1_range for a cast from int to a float.
3142 : bool
3143 243279 : operator_cast::op1_range (irange &r, tree type, const frange &lhs,
3144 : const irange &, relation_trio) const
3145 : {
3146 243279 : if (lhs.undefined_p ())
3147 : return false;
3148 243279 : if (lhs.known_isnan ())
3149 : {
3150 0 : r.set_varying (type);
3151 0 : return true;
3152 : }
3153 243279 : REAL_VALUE_TYPE lb = lhs.lower_bound ();
3154 243279 : REAL_VALUE_TYPE ub = lhs.upper_bound ();
3155 243279 : enum machine_mode mode = TYPE_MODE (lhs.type ());
3156 243279 : frange_nextafter (mode, lb, dconstninf);
3157 243279 : frange_nextafter (mode, ub, dconstinf);
3158 243279 : if (flag_rounding_math)
3159 : {
3160 37 : real_floor (&lb, mode, &lb);
3161 37 : real_ceil (&ub, mode, &ub);
3162 : }
3163 : else
3164 : {
3165 243242 : real_trunc (&lb, mode, &lb);
3166 243242 : real_trunc (&ub, mode, &ub);
3167 : }
3168 243279 : REAL_VALUE_TYPE l, u;
3169 243279 : wide_int wlb, wub;
3170 243279 : l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
3171 243279 : if (real_less (&lb, &l))
3172 28757 : wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3173 : else
3174 : {
3175 214522 : bool fail = false;
3176 214522 : wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
3177 214522 : if (fail)
3178 0 : wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3179 : }
3180 243279 : u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
3181 243279 : if (real_less (&u, &ub))
3182 39885 : wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3183 : else
3184 : {
3185 203394 : bool fail = false;
3186 203394 : wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
3187 203394 : if (fail)
3188 0 : wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3189 : }
3190 243279 : r.set (type, wlb, wub);
3191 243279 : return true;
3192 243279 : }
3193 :
3194 : // Initialize any float operators to the primary table
3195 :
3196 : void
3197 284591 : range_op_table::initialize_float_ops ()
3198 : {
3199 284591 : set (UNLE_EXPR, fop_unordered_le);
3200 284591 : set (UNLT_EXPR, fop_unordered_lt);
3201 284591 : set (UNGE_EXPR, fop_unordered_ge);
3202 284591 : set (UNGT_EXPR, fop_unordered_gt);
3203 284591 : set (UNEQ_EXPR, fop_unordered_equal);
3204 284591 : set (ORDERED_EXPR, fop_ordered);
3205 284591 : set (UNORDERED_EXPR, fop_unordered);
3206 284591 : set (LTGT_EXPR, fop_ltgt);
3207 284591 : set (RDIV_EXPR, fop_div);
3208 284591 : }
3209 :
3210 : #if CHECKING_P
3211 : #include "selftest.h"
3212 :
3213 : namespace selftest
3214 : {
3215 :
3216 : // Build an frange from string endpoints.
3217 :
3218 : static inline frange
3219 16 : frange_float (const char *lb, const char *ub, tree type = float_type_node)
3220 : {
3221 16 : REAL_VALUE_TYPE min, max;
3222 16 : gcc_assert (real_from_string (&min, lb) == 0);
3223 16 : gcc_assert (real_from_string (&max, ub) == 0);
3224 16 : return frange (type, min, max);
3225 : }
3226 :
3227 : void
3228 4 : range_op_float_tests ()
3229 : {
3230 4 : frange r, r0, r1;
3231 4 : frange trange (float_type_node);
3232 :
3233 : // negate([-5, +10]) => [-10, 5]
3234 4 : r0 = frange_float ("-5", "10");
3235 4 : range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
3236 4 : ASSERT_EQ (r, frange_float ("-10", "5"));
3237 :
3238 : // negate([0, 1] -NAN) => [-1, -0] +NAN
3239 4 : r0 = frange_float ("0", "1");
3240 4 : r0.update_nan (true);
3241 4 : range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
3242 4 : r1 = frange_float ("-1", "-0");
3243 4 : r1.update_nan (false);
3244 4 : ASSERT_EQ (r, r1);
3245 :
3246 : // [-INF,+INF] + [-INF,+INF] could be a NAN.
3247 4 : range_op_handler plus (PLUS_EXPR);
3248 4 : r0.set_varying (float_type_node);
3249 4 : r1.set_varying (float_type_node);
3250 4 : r0.clear_nan ();
3251 4 : r1.clear_nan ();
3252 4 : plus.fold_range (r, float_type_node, r0, r1);
3253 4 : if (HONOR_NANS (float_type_node))
3254 8 : ASSERT_TRUE (r.maybe_isnan ());
3255 4 : }
3256 :
3257 : } // namespace selftest
3258 :
3259 : #endif // CHECKING_P
|