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 5608796 : range_operator::fold_range (frange &r, tree type,
54 : const frange &op1, const frange &op2,
55 : relation_trio trio) const
56 : {
57 5608796 : if (empty_range_varying (r, type, op1, op2))
58 6773 : return true;
59 5602023 : if (op1.known_isnan () || op2.known_isnan ())
60 : {
61 6742 : r.set_nan (type);
62 6742 : return true;
63 : }
64 :
65 5595281 : relation_kind rel = trio.op1_op2 ();
66 5595281 : r.set_undefined ();
67 5595281 : frange tmp;
68 11149338 : if (relation_equiv_p (rel) && op1 == op2)
69 : {
70 : // The operands are known equal (x op x). Fold each sub-range against
71 : // itself, the diagonal of the cross product, so a relation-aware rv_fold
72 : // like operator_mult's is_square stays valid.
73 : //
74 : // For x * x with x in [-3, -2] U [2, 3] the diagonal is
75 : //
76 : // [-3, -2] * [-3, -2] = [4, 9]
77 : // [ 2, 3] * [ 2, 3] = [4, 9]
78 : //
79 : // giving the exact [4, 9]. The full cross product would form:
80 : //
81 : // [-3, -2] * [-3, -2] = [4, 9]
82 : // [-3, -2] * [ 2, 3] = [-9, -4]
83 : // [ 2, 3] * [-3, -2] = [-9, -4]
84 : // [ 2, 3] * [ 2, 3] = [4, 9]
85 : //
86 : // whose union [-9, -4] U [4, 9] contains negative products that x * x
87 : // can never produce: the off-diagonal terms pair a value from one
88 : // sub-range with a value from the other, which x (a single value) can
89 : // never do.
90 83128 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
91 : {
92 41904 : rv_fold (tmp, type,
93 : op1.lower_bound (i), op1.upper_bound (i),
94 : op1.lower_bound (i), op1.upper_bound (i), rel);
95 41904 : r.union_ (tmp);
96 : }
97 : }
98 : else
99 : // Otherwise do the straight cross product.
100 11223696 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
101 11453519 : for (unsigned j = 0; j < op2.num_pairs (); ++j)
102 : {
103 5783880 : rv_fold (tmp, type,
104 : op1.lower_bound (i), op1.upper_bound (i),
105 : op2.lower_bound (j), op2.upper_bound (j), rel);
106 5783880 : r.union_ (tmp);
107 : }
108 :
109 5595281 : if (r.known_isnan ())
110 : return true;
111 9277566 : if (op1.maybe_isnan () || op2.maybe_isnan ())
112 3940071 : r.update_nan ();
113 :
114 : // If the result has overflowed and flag_trapping_math, folding this
115 : // operation could elide an overflow or division by zero exception.
116 : // Avoid returning a singleton +-INF, to keep the propagators (DOM
117 : // and substitute_and_fold_engine) from folding. See PR107608.
118 5594177 : if (flag_trapping_math
119 26321272 : && MODE_HAS_INFINITIES (TYPE_MODE (type))
120 10776357 : && r.known_isinf () && !op1.known_isinf () && !op2.known_isinf ())
121 : {
122 1625 : REAL_VALUE_TYPE inf = r.lower_bound ();
123 1625 : if (real_isneg (&inf))
124 : {
125 96 : REAL_VALUE_TYPE min = real_min_representable (type);
126 96 : r.set (type, inf, min);
127 : }
128 : else
129 : {
130 1529 : REAL_VALUE_TYPE max = real_max_representable (type);
131 1529 : r.set (type, max, inf);
132 : }
133 : }
134 :
135 5594177 : r.flush_denormals_to_zero ();
136 :
137 5594177 : return true;
138 : }
139 :
140 : // For a given operation, fold two sets of ranges into [lb, ub].
141 : // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
142 : // UB, the final range has the possibility of a NAN.
143 : void
144 514736 : range_operator::rv_fold (frange &r, tree type,
145 : const REAL_VALUE_TYPE &,
146 : const REAL_VALUE_TYPE &,
147 : const REAL_VALUE_TYPE &,
148 : const REAL_VALUE_TYPE &, relation_kind) const
149 : {
150 514736 : r.set (type, dconstninf, dconstinf, nan_state (true));
151 514736 : }
152 :
153 : bool
154 100047 : range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
155 : tree type ATTRIBUTE_UNUSED,
156 : const frange &lh ATTRIBUTE_UNUSED,
157 : const irange &rh ATTRIBUTE_UNUSED,
158 : relation_trio) const
159 : {
160 100047 : return false;
161 : }
162 :
163 : bool
164 0 : range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
165 : tree type ATTRIBUTE_UNUSED,
166 : const frange &lh ATTRIBUTE_UNUSED,
167 : const frange &rh ATTRIBUTE_UNUSED,
168 : relation_trio) const
169 : {
170 0 : return false;
171 : }
172 :
173 : bool
174 0 : range_operator::fold_range (frange &r ATTRIBUTE_UNUSED,
175 : tree type ATTRIBUTE_UNUSED,
176 : const irange &lh ATTRIBUTE_UNUSED,
177 : const irange &rh ATTRIBUTE_UNUSED,
178 : relation_trio) const
179 : {
180 0 : return false;
181 : }
182 :
183 : bool
184 5277 : range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
185 : tree type ATTRIBUTE_UNUSED,
186 : const frange &lhs ATTRIBUTE_UNUSED,
187 : const frange &op2 ATTRIBUTE_UNUSED,
188 : relation_trio) const
189 : {
190 5277 : return false;
191 : }
192 :
193 : bool
194 5619 : range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
195 : tree type ATTRIBUTE_UNUSED,
196 : const irange &lhs ATTRIBUTE_UNUSED,
197 : const frange &op2 ATTRIBUTE_UNUSED,
198 : relation_trio) const
199 : {
200 5619 : return false;
201 : }
202 :
203 : bool
204 2387 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
205 : tree type ATTRIBUTE_UNUSED,
206 : const frange &lhs ATTRIBUTE_UNUSED,
207 : const frange &op1 ATTRIBUTE_UNUSED,
208 : relation_trio) const
209 : {
210 2387 : return false;
211 : }
212 :
213 : bool
214 0 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
215 : tree type ATTRIBUTE_UNUSED,
216 : const irange &lhs ATTRIBUTE_UNUSED,
217 : const frange &op1 ATTRIBUTE_UNUSED,
218 : relation_trio) const
219 : {
220 0 : return false;
221 : }
222 :
223 : relation_kind
224 5609502 : range_operator::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
225 : const frange &op1 ATTRIBUTE_UNUSED,
226 : const frange &op2 ATTRIBUTE_UNUSED,
227 : relation_kind) const
228 : {
229 5609502 : return VREL_VARYING;
230 : }
231 :
232 : relation_kind
233 1072166 : range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
234 : const frange &op1 ATTRIBUTE_UNUSED,
235 : const frange &op2 ATTRIBUTE_UNUSED,
236 : relation_kind) const
237 : {
238 1072166 : return VREL_VARYING;
239 : }
240 :
241 : relation_kind
242 184546 : range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
243 : const frange &op1 ATTRIBUTE_UNUSED,
244 : const frange &op2 ATTRIBUTE_UNUSED,
245 : relation_kind) const
246 : {
247 184546 : return VREL_VARYING;
248 : }
249 :
250 : relation_kind
251 3337910 : range_operator::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
252 : const frange &op1 ATTRIBUTE_UNUSED,
253 : const frange &op2 ATTRIBUTE_UNUSED,
254 : relation_kind) const
255 : {
256 3337910 : return VREL_VARYING;
257 : }
258 :
259 : relation_kind
260 369522 : range_operator::op1_op2_relation (const irange &,
261 : const frange &,
262 : const frange &) const
263 : {
264 369522 : return VREL_VARYING;
265 : }
266 :
267 :
268 : relation_kind
269 698304 : range_operator::op1_op2_relation (const frange &,
270 : const frange &,
271 : const frange &) const
272 : {
273 698304 : return VREL_VARYING;
274 : }
275 :
276 : // Return TRUE if OP1 and OP2 may be a NAN.
277 :
278 : static inline bool
279 3701783 : maybe_isnan (const frange &op1, const frange &op2)
280 : {
281 6475569 : return op1.maybe_isnan () || op2.maybe_isnan ();
282 : }
283 :
284 : // Floating point version of relop_early_resolve that takes NANs into
285 : // account.
286 : //
287 : // For relation opcodes, first try to see if the supplied relation
288 : // forces a true or false result, and return that.
289 : // Then check for undefined operands. If none of this applies,
290 : // return false.
291 : //
292 : // TRIO are the relations between operands as they appear in the IL.
293 : // MY_REL is the relation that corresponds to the operator being
294 : // folded. For example, when attempting to fold x_3 == y_5, MY_REL is
295 : // VREL_EQ, and if the statement is dominated by x_3 > y_5, then
296 : // TRIO.op1_op2() is VREL_GT.
297 :
298 : static inline bool
299 2146293 : frelop_early_resolve (irange &r, tree type,
300 : const frange &op1, const frange &op2,
301 : relation_trio trio, relation_kind my_rel)
302 : {
303 2146293 : relation_kind rel = trio.op1_op2 ();
304 :
305 : // If known relation is a complete subset of this relation, always
306 : // return true. However, avoid doing this when NAN is a possibility
307 : // as we'll incorrectly fold conditions:
308 : //
309 : // if (x_3 >= y_5)
310 : // ;
311 : // else
312 : // ;; With NANs the relation here is basically VREL_UNLT, so we
313 : // ;; can't fold the following:
314 : // if (x_3 < y_5)
315 2146293 : if (!maybe_isnan (op1, op2) && relation_union (rel, my_rel) == my_rel)
316 : {
317 1885 : r = range_true (type);
318 1885 : return true;
319 : }
320 :
321 : // If known relation has no subset of this relation, always false.
322 2144408 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
323 : {
324 1003 : r = range_false (type);
325 1003 : return true;
326 : }
327 :
328 : // If either operand is undefined, return VARYING.
329 2143405 : if (empty_range_varying (r, type, op1, op2))
330 3901 : return true;
331 :
332 : return false;
333 : }
334 :
335 : // Set VALUE to its next real value, or INF if the operation overflows.
336 :
337 : void
338 14136667 : frange_nextafter (enum machine_mode mode,
339 : REAL_VALUE_TYPE &value,
340 : const REAL_VALUE_TYPE &inf)
341 : {
342 98956669 : if (MODE_COMPOSITE_P (mode)
343 0 : && (real_isdenormal (&value, mode) || real_iszero (&value)))
344 : {
345 : // IBM extended denormals only have DFmode precision.
346 0 : REAL_VALUE_TYPE tmp, tmp2;
347 0 : real_convert (&tmp2, DFmode, &value);
348 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
349 0 : real_convert (&value, mode, &tmp);
350 : }
351 : else
352 : {
353 14136667 : REAL_VALUE_TYPE tmp;
354 14136667 : real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
355 14136667 : value = tmp;
356 : }
357 14136667 : }
358 :
359 : // Like real_arithmetic, but round the result to INF if the operation
360 : // produced inexact results.
361 : //
362 : // ?? There is still one problematic case, i387. With
363 : // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
364 : // XFmode (long_double_type_node), so that case is OK. But without
365 : // -mfpmath=sse, all the SF/DFmode computations are in XFmode
366 : // precision (64-bit mantissa) and only occasionally rounded to
367 : // SF/DFmode (when storing into memory from the 387 stack). Maybe
368 : // this is ok as well though it is just occasionally more precise. ??
369 :
370 : void
371 16554892 : frange_arithmetic (enum tree_code code, tree type,
372 : REAL_VALUE_TYPE &result,
373 : const REAL_VALUE_TYPE &op1,
374 : const REAL_VALUE_TYPE &op2,
375 : const REAL_VALUE_TYPE &inf)
376 : {
377 16554892 : REAL_VALUE_TYPE value;
378 16554892 : enum machine_mode mode = TYPE_MODE (type);
379 115884244 : bool mode_composite = MODE_COMPOSITE_P (mode);
380 :
381 16554892 : bool inexact = real_arithmetic (&value, code, &op1, &op2);
382 16554892 : real_convert (&result, mode, &value);
383 :
384 : /* When rounding towards negative infinity, x + (-x) and
385 : x - x is -0 rather than +0 real_arithmetic computes.
386 : So, when we are looking for lower bound (inf is negative),
387 : use -0 rather than +0. */
388 16554892 : if (flag_rounding_math
389 17100 : && (code == PLUS_EXPR || code == MINUS_EXPR)
390 5144 : && !inexact
391 5144 : && real_iszero (&result)
392 144 : && !real_isneg (&result)
393 16555036 : && real_isneg (&inf))
394 : {
395 88 : REAL_VALUE_TYPE op2a = op2;
396 88 : if (code == PLUS_EXPR)
397 82 : op2a.sign ^= 1;
398 88 : if (real_isneg (&op1) == real_isneg (&op2a) && real_equal (&op1, &op2a))
399 36 : result.sign = 1;
400 : }
401 :
402 : // Be extra careful if there may be discrepancies between the
403 : // compile and runtime results.
404 16554892 : bool round = false;
405 16554892 : if (mode_composite)
406 : round = true;
407 : else
408 : {
409 16554892 : bool low = real_isneg (&inf);
410 16554892 : round = (low ? !real_less (&result, &value)
411 8277514 : : !real_less (&value, &result));
412 16554892 : if (real_isinf (&result, !low)
413 1779580 : && !real_isinf (&value)
414 16989613 : && !flag_rounding_math)
415 : {
416 : // Use just [+INF, +INF] rather than [MAX, +INF]
417 : // even if value is larger than MAX and rounds to
418 : // nearest to +INF. Similarly just [-INF, -INF]
419 : // rather than [-INF, +MAX] even if value is smaller
420 : // than -MAX and rounds to nearest to -INF.
421 : // Unless INEXACT is true, in that case we need some
422 : // extra buffer.
423 432820 : if (!inexact)
424 : round = false;
425 : else
426 : {
427 57394 : REAL_VALUE_TYPE tmp = result, tmp2;
428 57394 : frange_nextafter (mode, tmp, inf);
429 : // TMP is at this point the maximum representable
430 : // number.
431 57394 : real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp);
432 57394 : if (real_isneg (&tmp2) != low
433 57394 : && (REAL_EXP (&tmp2) - REAL_EXP (&tmp)
434 57394 : >= 2 - REAL_MODE_FORMAT (mode)->p))
435 57393 : round = false;
436 : }
437 : }
438 : }
439 16179466 : if (round && (inexact || !real_identical (&result, &value)))
440 : {
441 1567703 : if (mode_composite
442 1567703 : && (real_isdenormal (&result, mode) || real_iszero (&result)))
443 : {
444 : // IBM extended denormals only have DFmode precision.
445 0 : REAL_VALUE_TYPE tmp, tmp2;
446 0 : real_convert (&tmp2, DFmode, &value);
447 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
448 0 : real_convert (&result, mode, &tmp);
449 : }
450 : else
451 1567703 : frange_nextafter (mode, result, inf);
452 : }
453 16554892 : if (mode_composite)
454 0 : switch (code)
455 : {
456 0 : case PLUS_EXPR:
457 0 : case MINUS_EXPR:
458 : // ibm-ldouble-format documents 1ulp for + and -.
459 0 : frange_nextafter (mode, result, inf);
460 0 : break;
461 0 : case MULT_EXPR:
462 : // ibm-ldouble-format documents 2ulps for *.
463 0 : frange_nextafter (mode, result, inf);
464 0 : frange_nextafter (mode, result, inf);
465 0 : break;
466 0 : case RDIV_EXPR:
467 : // ibm-ldouble-format documents 3ulps for /.
468 0 : frange_nextafter (mode, result, inf);
469 0 : frange_nextafter (mode, result, inf);
470 0 : frange_nextafter (mode, result, inf);
471 0 : break;
472 : default:
473 : break;
474 : }
475 16554892 : }
476 :
477 : // Crop R to [-INF, MAX] where MAX is the maximum representable number
478 : // for TYPE.
479 :
480 : static inline void
481 190450 : frange_drop_inf (frange &r, tree type)
482 : {
483 190450 : REAL_VALUE_TYPE max = real_max_representable (type);
484 190450 : frange tmp (type, r.lower_bound (), max);
485 190450 : r.intersect (tmp);
486 190450 : }
487 :
488 : // Crop R to [MIN, +INF] where MIN is the minimum representable number
489 : // for TYPE.
490 :
491 : static inline void
492 96633 : frange_drop_ninf (frange &r, tree type)
493 : {
494 96633 : REAL_VALUE_TYPE min = real_min_representable (type);
495 96633 : frange tmp (type, min, r.upper_bound ());
496 96633 : r.intersect (tmp);
497 96633 : }
498 :
499 : // Crop R to [MIN, MAX] where MAX is the maximum representable number
500 : // for TYPE and MIN the minimum representable number for TYPE.
501 :
502 : static inline void
503 544878 : frange_drop_infs (frange &r, tree type)
504 : {
505 544878 : REAL_VALUE_TYPE max = real_max_representable (type);
506 544878 : REAL_VALUE_TYPE min = real_min_representable (type);
507 544878 : frange tmp (type, min, max);
508 544878 : r.intersect (tmp);
509 544878 : }
510 :
511 : // If zero is in R, make sure both -0.0 and +0.0 are in the range.
512 :
513 : static inline void
514 947606 : frange_add_zeros (frange &r, tree type)
515 : {
516 947606 : if (r.undefined_p () || r.known_isnan ())
517 : return;
518 :
519 947606 : if (HONOR_SIGNED_ZEROS (type) && r.contains_zero_p ())
520 : {
521 658732 : frange zero;
522 658732 : zero.set_zero (type);
523 658732 : r.union_ (zero);
524 658732 : }
525 : }
526 :
527 : // Build a range that is <= VAL and store it in R. Return TRUE if
528 : // further changes may be needed for R, or FALSE if R is in its final
529 : // form.
530 :
531 : static bool
532 260558 : build_le (frange &r, tree type, const frange &val)
533 : {
534 260558 : gcc_checking_assert (!val.known_isnan ());
535 :
536 260558 : REAL_VALUE_TYPE ninf = frange_val_min (type);
537 260558 : r.set (type, ninf, val.upper_bound ());
538 :
539 : // Add both zeros if there's the possibility of zero equality.
540 260558 : frange_add_zeros (r, type);
541 :
542 260558 : return true;
543 : }
544 :
545 : // Build a range that is < VAL and store it in R. Return TRUE if
546 : // further changes may be needed for R, or FALSE if R is in its final
547 : // form.
548 :
549 : static bool
550 320058 : build_lt (frange &r, tree type, const frange &val)
551 : {
552 320058 : gcc_checking_assert (!val.known_isnan ());
553 :
554 : // < -INF is outside the range.
555 320058 : if (real_isinf (&val.upper_bound (), 1))
556 : {
557 1216 : if (HONOR_NANS (type))
558 1216 : r.set_nan (type);
559 : else
560 0 : r.set_undefined ();
561 : return false;
562 : }
563 :
564 318842 : REAL_VALUE_TYPE ninf = frange_val_min (type);
565 318842 : REAL_VALUE_TYPE prev = val.upper_bound ();
566 318842 : machine_mode mode = TYPE_MODE (type);
567 : // Default to the conservatively correct closed ranges for
568 : // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
569 : // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
570 : // will crop the range appropriately.
571 2231894 : if (!MODE_COMPOSITE_P (mode))
572 318842 : frange_nextafter (mode, prev, ninf);
573 318842 : r.set (type, ninf, prev);
574 318842 : return true;
575 : }
576 :
577 : // Build a range that is >= VAL and store it in R. Return TRUE if
578 : // further changes may be needed for R, or FALSE if R is in its final
579 : // form.
580 :
581 : static bool
582 397478 : build_ge (frange &r, tree type, const frange &val)
583 : {
584 397478 : gcc_checking_assert (!val.known_isnan ());
585 :
586 397478 : REAL_VALUE_TYPE inf = frange_val_max (type);
587 397478 : r.set (type, val.lower_bound (), inf);
588 :
589 : // Add both zeros if there's the possibility of zero equality.
590 397478 : frange_add_zeros (r, type);
591 :
592 397478 : return true;
593 : }
594 :
595 : // Build a range that is > VAL and store it in R. Return TRUE if
596 : // further changes may be needed for R, or FALSE if R is in its final
597 : // form.
598 :
599 : static bool
600 205226 : build_gt (frange &r, tree type, const frange &val)
601 : {
602 205226 : gcc_checking_assert (!val.known_isnan ());
603 :
604 : // > +INF is outside the range.
605 205226 : if (real_isinf (&val.lower_bound (), 0))
606 : {
607 1846 : if (HONOR_NANS (type))
608 1846 : r.set_nan (type);
609 : else
610 0 : r.set_undefined ();
611 : return false;
612 : }
613 :
614 203380 : REAL_VALUE_TYPE inf = frange_val_max (type);
615 203380 : REAL_VALUE_TYPE next = val.lower_bound ();
616 203380 : machine_mode mode = TYPE_MODE (type);
617 : // Default to the conservatively correct closed ranges for
618 : // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
619 : // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
620 : // will crop the range appropriately.
621 1423660 : if (!MODE_COMPOSITE_P (mode))
622 203380 : frange_nextafter (mode, next, inf);
623 203380 : r.set (type, next, inf);
624 203380 : return true;
625 : }
626 :
627 :
628 : bool
629 74781 : operator_identity::fold_range (frange &r, tree, const frange &op1,
630 : const frange &, relation_trio) const
631 : {
632 74781 : r = op1;
633 74781 : return true;
634 : }
635 :
636 : bool
637 18701 : operator_identity::op1_range (frange &r, tree, const frange &lhs,
638 : const frange &, relation_trio) const
639 : {
640 18701 : r = lhs;
641 18701 : return true;
642 : }
643 :
644 : bool
645 8101 : operator_cst::fold_range (frange &r, tree, const frange &op1,
646 : const frange &, relation_trio) const
647 : {
648 8101 : r = op1;
649 8101 : return true;
650 : }
651 :
652 : bool
653 28458 : operator_equal::op2_range (frange &r, tree type,
654 : const irange &lhs, const frange &op1,
655 : relation_trio rel) const
656 : {
657 28458 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
658 : }
659 :
660 : bool
661 193215 : operator_equal::fold_range (irange &r, tree type,
662 : const frange &op1, const frange &op2,
663 : relation_trio rel) const
664 : {
665 193215 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
666 : return true;
667 :
668 190152 : if (op1.known_isnan () || op2.known_isnan ())
669 480 : r = range_false (type);
670 : // We can be sure the values are always equal or not if both ranges
671 : // consist of a single value, and then compare them.
672 189672 : else if (op1.singleton_p () && op2.singleton_p ())
673 : {
674 1372 : if (op1 == op2)
675 255 : r = range_true (type);
676 : // If one operand is -0.0 and other 0.0, they are still equal.
677 1117 : else if (real_iszero (&op1.lower_bound ())
678 1117 : && real_iszero (&op2.lower_bound ()))
679 29 : r = range_true (type);
680 : else
681 1088 : r = range_false (type);
682 : }
683 188300 : else if (real_iszero (&op1.lower_bound ())
684 6139 : && real_iszero (&op1.upper_bound ())
685 667 : && real_iszero (&op2.lower_bound ())
686 478 : && real_iszero (&op2.upper_bound ())
687 188778 : && !maybe_isnan (op1, op2))
688 : // [-0.0, 0.0] == [-0.0, 0.0] or similar.
689 329 : r = range_true (type);
690 : else
691 : {
692 : // If ranges do not intersect, we know the range is not equal,
693 : // otherwise we don't know anything for sure.
694 187971 : frange tmp = op1;
695 187971 : tmp.intersect (op2);
696 187971 : if (tmp.undefined_p ())
697 : {
698 : // If one range contains -0.0 and another +0.0, we don't know
699 : // anything either, because -0.0 == 0.0.
700 1698 : if (op1.contains_zero_p () && op2.contains_zero_p ())
701 13 : r = range_true_and_false (type);
702 : else
703 1685 : r = range_false (type);
704 : }
705 : else
706 186273 : r = range_true_and_false (type);
707 187971 : }
708 : return true;
709 : }
710 :
711 : bool
712 148241 : operator_equal::op1_range (frange &r, tree type,
713 : const irange &lhs,
714 : const frange &op2,
715 : relation_trio trio) const
716 : {
717 148241 : relation_kind rel = trio.op1_op2 ();
718 148241 : switch (get_bool_state (r, lhs, type))
719 : {
720 46676 : case BRS_TRUE:
721 : // The TRUE side of x == NAN is unreachable.
722 46676 : if (op2.known_isnan ())
723 0 : r.set_undefined ();
724 : else
725 : {
726 : // If it's true, the result is the same as OP2.
727 46676 : r = op2;
728 : // Add both zeros if there's the possibility of zero equality.
729 46676 : frange_add_zeros (r, type);
730 : // The TRUE side of op1 == op2 implies op1 is !NAN.
731 46676 : r.clear_nan ();
732 : }
733 : break;
734 :
735 98959 : case BRS_FALSE:
736 : // The FALSE side of op1 == op1 implies op1 is a NAN.
737 98959 : if (rel == VREL_EQ)
738 2871 : r.set_nan (type);
739 : // On the FALSE side of x == NAN, we know nothing about x.
740 96088 : else if (op2.known_isnan ())
741 2 : r.set_varying (type);
742 : // If the result is false, the only time we know anything is
743 : // if OP2 is a constant.
744 96086 : else if (op2.singleton_p ()
745 104386 : || (!op2.maybe_isnan () && op2.zero_p ()))
746 : {
747 61680 : REAL_VALUE_TYPE tmp = op2.lower_bound ();
748 61680 : r.set (type, tmp, tmp, VR_ANTI_RANGE);
749 : }
750 : else
751 34406 : r.set_varying (type);
752 : break;
753 :
754 : default:
755 : break;
756 : }
757 148241 : return true;
758 : }
759 :
760 : // Check if the LHS range indicates a relation between OP1 and OP2.
761 :
762 : relation_kind
763 149732 : operator_equal::op1_op2_relation (const irange &lhs, const frange &,
764 : const frange &) const
765 : {
766 149732 : if (lhs.undefined_p ())
767 : return VREL_UNDEFINED;
768 :
769 : // FALSE = op1 == op2 indicates NE_EXPR.
770 149732 : if (lhs.zero_p ())
771 : return VREL_NE;
772 :
773 : // TRUE = op1 == op2 indicates EQ_EXPR.
774 80877 : if (!lhs.contains_zero_p ())
775 77843 : return VREL_EQ;
776 : return VREL_VARYING;
777 : }
778 :
779 : bool
780 860524 : operator_not_equal::fold_range (irange &r, tree type,
781 : const frange &op1, const frange &op2,
782 : relation_trio trio) const
783 : {
784 860524 : relation_kind rel = trio.op1_op2 ();
785 :
786 : // VREL_NE & NE_EXPR is always true, even with NANs.
787 860524 : if (rel == VREL_NE)
788 : {
789 26 : r = range_true (type);
790 26 : return true;
791 : }
792 860498 : if (rel == VREL_EQ && maybe_isnan (op1, op2))
793 : {
794 : // Avoid frelop_early_resolve() below as it could fold to FALSE
795 : // without regards to NANs. This would be incorrect if trying
796 : // to fold x_5 != x_5 without prior knowledge of NANs.
797 : // Still, if either operand is undefined, return VARYING.
798 24137 : if (empty_range_varying (r, type, op1, op2))
799 5 : return true;
800 : }
801 836361 : else if (frelop_early_resolve (r, type, op1, op2, trio, VREL_NE))
802 : return true;
803 :
804 : // x != NAN is always TRUE.
805 859075 : if (op1.known_isnan () || op2.known_isnan ())
806 1296 : r = range_true (type);
807 : // We can be sure the values are always equal or not if both ranges
808 : // consist of a single value, and then compare them.
809 857779 : else if (op1.singleton_p () && op2.singleton_p ())
810 : {
811 1539 : if (op1 == op2)
812 1027 : r = range_false (type);
813 : // If one operand is -0.0 and other 0.0, they are still equal.
814 512 : else if (real_iszero (&op1.lower_bound ())
815 512 : && real_iszero (&op2.lower_bound ()))
816 1 : r = range_false (type);
817 : else
818 511 : r = range_true (type);
819 : }
820 856240 : else if (real_iszero (&op1.lower_bound ())
821 6972 : && real_iszero (&op1.upper_bound ())
822 471 : && real_iszero (&op2.lower_bound ())
823 212 : && real_iszero (&op2.upper_bound ())
824 856452 : && !maybe_isnan (op1, op2))
825 : // [-0.0, 0.0] != [-0.0, 0.0] or similar.
826 112 : r = range_false (type);
827 : else
828 : {
829 : // If ranges do not intersect, we know the range is not equal,
830 : // otherwise we don't know anything for sure.
831 856128 : frange tmp = op1;
832 856128 : tmp.intersect (op2);
833 856128 : if (tmp.undefined_p ())
834 : {
835 : // If one range contains -0.0 and another +0.0, we don't know
836 : // anything either, because -0.0 == 0.0.
837 832 : if (op1.contains_zero_p () && op2.contains_zero_p ())
838 2 : r = range_true_and_false (type);
839 : else
840 830 : r = range_true (type);
841 : }
842 : else
843 855296 : r = range_true_and_false (type);
844 856128 : }
845 : return true;
846 : }
847 :
848 : bool
849 292740 : operator_not_equal::op1_range (frange &r, tree type,
850 : const irange &lhs,
851 : const frange &op2,
852 : relation_trio trio) const
853 : {
854 292740 : relation_kind rel = trio.op1_op2 ();
855 292740 : switch (get_bool_state (r, lhs, type))
856 : {
857 46991 : case BRS_TRUE:
858 : // If the result is true, the only time we know anything is if
859 : // OP2 is a constant.
860 46991 : if (op2.singleton_p ())
861 : {
862 : // This is correct even if op1 is NAN, because the following
863 : // range would be ~[tmp, tmp] with the NAN property set to
864 : // maybe (VARYING).
865 23718 : REAL_VALUE_TYPE tmp = op2.lower_bound ();
866 23718 : r.set (type, tmp, tmp, VR_ANTI_RANGE);
867 : }
868 : // The TRUE side of op1 != op1 implies op1 is NAN.
869 23273 : else if (rel == VREL_EQ)
870 5628 : r.set_nan (type);
871 : else
872 17645 : r.set_varying (type);
873 : break;
874 :
875 243057 : case BRS_FALSE:
876 : // The FALSE side of x != NAN is impossible.
877 243057 : if (op2.known_isnan ())
878 182 : r.set_undefined ();
879 : else
880 : {
881 : // If it's false, the result is the same as OP2.
882 242875 : r = op2;
883 : // Add both zeros if there's the possibility of zero equality.
884 242875 : frange_add_zeros (r, type);
885 : // The FALSE side of op1 != op2 implies op1 is !NAN.
886 242875 : r.clear_nan ();
887 : }
888 : break;
889 :
890 : default:
891 : break;
892 : }
893 292740 : return true;
894 : }
895 :
896 : bool
897 193538 : operator_not_equal::op2_range (frange &r, tree type,
898 : const irange &lhs,
899 : const frange &op1,
900 : relation_trio trio) const
901 : {
902 193538 : return op1_range (r, type, lhs, op1, trio);
903 : }
904 :
905 : // Check if the LHS range indicates a relation between OP1 and OP2.
906 :
907 : relation_kind
908 663677 : operator_not_equal::op1_op2_relation (const irange &lhs, const frange &,
909 : const frange &) const
910 : {
911 663677 : if (lhs.undefined_p ())
912 : return VREL_UNDEFINED;
913 :
914 : // FALSE = op1 != op2 indicates EQ_EXPR.
915 663677 : if (lhs.zero_p ())
916 : return VREL_EQ;
917 :
918 : // TRUE = op1 != op2 indicates NE_EXPR.
919 119696 : if (!lhs.contains_zero_p ())
920 116655 : return VREL_NE;
921 : return VREL_VARYING;
922 : }
923 :
924 : bool
925 283908 : operator_lt::fold_range (irange &r, tree type,
926 : const frange &op1, const frange &op2,
927 : relation_trio trio) const
928 : {
929 283908 : if (frelop_early_resolve (r, type, op1, op2, trio, VREL_LT))
930 : return true;
931 :
932 283310 : if (op1.known_isnan ()
933 282858 : || op2.known_isnan ()
934 565906 : || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
935 3062 : r = range_false (type);
936 280248 : else if (!maybe_isnan (op1, op2)
937 280248 : && real_less (&op1.upper_bound (), &op2.lower_bound ()))
938 1376 : r = range_true (type);
939 : else
940 278872 : r = range_true_and_false (type);
941 : return true;
942 : }
943 :
944 : bool
945 458073 : operator_lt::op1_range (frange &r,
946 : tree type,
947 : const irange &lhs,
948 : const frange &op2,
949 : relation_trio) const
950 : {
951 458073 : switch (get_bool_state (r, lhs, type))
952 : {
953 160018 : case BRS_TRUE:
954 : // The TRUE side of x < NAN is unreachable.
955 160018 : if (op2.known_isnan ())
956 68 : r.set_undefined ();
957 159950 : else if (op2.undefined_p ())
958 : return false;
959 159950 : else if (build_lt (r, type, op2))
960 : {
961 159946 : r.clear_nan ();
962 : // x < y implies x is not +INF.
963 159946 : frange_drop_inf (r, type);
964 : }
965 : break;
966 :
967 297146 : case BRS_FALSE:
968 : // On the FALSE side of x < NAN, we know nothing about x.
969 563458 : if (op2.maybe_isnan ())
970 30834 : r.set_varying (type);
971 : else
972 266312 : build_ge (r, type, op2);
973 : break;
974 :
975 : default:
976 : break;
977 : }
978 : return true;
979 : }
980 :
981 : bool
982 67312 : operator_lt::op2_range (frange &r,
983 : tree type,
984 : const irange &lhs,
985 : const frange &op1,
986 : relation_trio) const
987 : {
988 67312 : switch (get_bool_state (r, lhs, type))
989 : {
990 27043 : case BRS_TRUE:
991 : // The TRUE side of NAN < x is unreachable.
992 27043 : if (op1.known_isnan ())
993 22 : r.set_undefined ();
994 27021 : else if (op1.undefined_p ())
995 : return false;
996 27021 : else if (build_gt (r, type, op1))
997 : {
998 27021 : r.clear_nan ();
999 : // x < y implies y is not -INF.
1000 27021 : frange_drop_ninf (r, type);
1001 : }
1002 : break;
1003 :
1004 40059 : case BRS_FALSE:
1005 : // On the FALSE side of NAN < x, we know nothing about x.
1006 44101 : if (op1.maybe_isnan ())
1007 36017 : r.set_varying (type);
1008 : else
1009 4042 : build_le (r, type, op1);
1010 : break;
1011 :
1012 : default:
1013 : break;
1014 : }
1015 : return true;
1016 : }
1017 :
1018 :
1019 : // Check if the LHS range indicates a relation between OP1 and OP2.
1020 :
1021 : relation_kind
1022 269774 : operator_lt::op1_op2_relation (const irange &lhs, const frange &,
1023 : const frange &) const
1024 : {
1025 269774 : if (lhs.undefined_p ())
1026 : return VREL_UNDEFINED;
1027 :
1028 : // FALSE = op1 < op2 indicates GE_EXPR.
1029 269774 : if (lhs.zero_p ())
1030 : return VREL_GE;
1031 :
1032 : // TRUE = op1 < op2 indicates LT_EXPR.
1033 124933 : if (!lhs.contains_zero_p ())
1034 124543 : return VREL_LT;
1035 : return VREL_VARYING;
1036 : }
1037 :
1038 : bool
1039 272941 : operator_le::fold_range (irange &r, tree type,
1040 : const frange &op1, const frange &op2,
1041 : relation_trio rel) const
1042 : {
1043 272941 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
1044 : return true;
1045 :
1046 272399 : if (op1.known_isnan ()
1047 271351 : || op2.known_isnan ()
1048 543716 : || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1049 2953 : r = range_false (type);
1050 269446 : else if (!maybe_isnan (op1, op2)
1051 269446 : && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1052 873 : r = range_true (type);
1053 : else
1054 268573 : r = range_true_and_false (type);
1055 : return true;
1056 : }
1057 :
1058 : bool
1059 99034 : operator_le::op1_range (frange &r,
1060 : tree type,
1061 : const irange &lhs,
1062 : const frange &op2,
1063 : relation_trio) const
1064 : {
1065 99034 : switch (get_bool_state (r, lhs, type))
1066 : {
1067 69217 : case BRS_TRUE:
1068 : // The TRUE side of x <= NAN is unreachable.
1069 69217 : if (op2.known_isnan ())
1070 0 : r.set_undefined ();
1071 69217 : else if (op2.undefined_p ())
1072 : return false;
1073 69217 : else if (build_le (r, type, op2))
1074 69217 : r.clear_nan ();
1075 : break;
1076 :
1077 29616 : case BRS_FALSE:
1078 : // On the FALSE side of x <= NAN, we know nothing about x.
1079 54711 : if (op2.maybe_isnan ())
1080 4521 : r.set_varying (type);
1081 : else
1082 25095 : build_gt (r, type, op2);
1083 : break;
1084 :
1085 : default:
1086 : break;
1087 : }
1088 : return true;
1089 : }
1090 :
1091 : bool
1092 15255 : operator_le::op2_range (frange &r,
1093 : tree type,
1094 : const irange &lhs,
1095 : const frange &op1,
1096 : relation_trio) const
1097 : {
1098 15255 : switch (get_bool_state (r, lhs, type))
1099 : {
1100 3999 : case BRS_TRUE:
1101 : // The TRUE side of NAN <= x is unreachable.
1102 3999 : if (op1.known_isnan ())
1103 0 : r.set_undefined ();
1104 3999 : else if (op1.undefined_p ())
1105 : return false;
1106 3999 : else if (build_ge (r, type, op1))
1107 3999 : r.clear_nan ();
1108 : break;
1109 :
1110 11118 : case BRS_FALSE:
1111 : // On the FALSE side of NAN <= x, we know nothing about x.
1112 11874 : if (op1.maybe_isnan ())
1113 10362 : r.set_varying (type);
1114 756 : else if (op1.undefined_p ())
1115 : return false;
1116 : else
1117 756 : build_lt (r, type, op1);
1118 : break;
1119 :
1120 : default:
1121 : break;
1122 : }
1123 : return true;
1124 : }
1125 :
1126 : // Check if the LHS range indicates a relation between OP1 and OP2.
1127 :
1128 : relation_kind
1129 65751 : operator_le::op1_op2_relation (const irange &lhs, const frange &,
1130 : const frange &) const
1131 : {
1132 65751 : if (lhs.undefined_p ())
1133 : return VREL_UNDEFINED;
1134 :
1135 : // FALSE = op1 <= op2 indicates GT_EXPR.
1136 65751 : if (lhs.zero_p ())
1137 : return VREL_GT;
1138 :
1139 : // TRUE = op1 <= op2 indicates LE_EXPR.
1140 32919 : if (!lhs.contains_zero_p ())
1141 32639 : return VREL_LE;
1142 : return VREL_VARYING;
1143 : }
1144 :
1145 : bool
1146 290793 : operator_gt::fold_range (irange &r, tree type,
1147 : const frange &op1, const frange &op2,
1148 : relation_trio trio) const
1149 : {
1150 290793 : if (frelop_early_resolve (r, type, op1, op2, trio, VREL_GT))
1151 : return true;
1152 :
1153 289985 : if (op1.known_isnan ()
1154 289471 : || op2.known_isnan ()
1155 579134 : || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1156 4676 : r = range_false (type);
1157 285309 : else if (!maybe_isnan (op1, op2)
1158 285309 : && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1159 1112 : r = range_true (type);
1160 : else
1161 284197 : r = range_true_and_false (type);
1162 : return true;
1163 : }
1164 :
1165 : bool
1166 178946 : operator_gt::op1_range (frange &r,
1167 : tree type,
1168 : const irange &lhs,
1169 : const frange &op2,
1170 : relation_trio) const
1171 : {
1172 178946 : switch (get_bool_state (r, lhs, type))
1173 : {
1174 69640 : case BRS_TRUE:
1175 : // The TRUE side of x > NAN is unreachable.
1176 69640 : if (op2.known_isnan ())
1177 28 : r.set_undefined ();
1178 69612 : else if (op2.undefined_p ())
1179 : return false;
1180 69612 : else if (build_gt (r, type, op2))
1181 : {
1182 69612 : r.clear_nan ();
1183 : // x > y implies x is not -INF.
1184 69612 : frange_drop_ninf (r, type);
1185 : }
1186 : break;
1187 :
1188 108732 : case BRS_FALSE:
1189 : // On the FALSE side of x > NAN, we know nothing about x.
1190 187159 : if (op2.maybe_isnan ())
1191 30305 : r.set_varying (type);
1192 78427 : else if (op2.undefined_p ())
1193 : return false;
1194 : else
1195 78427 : build_le (r, type, op2);
1196 : break;
1197 :
1198 : default:
1199 : break;
1200 : }
1201 : return true;
1202 : }
1203 :
1204 : bool
1205 79519 : operator_gt::op2_range (frange &r,
1206 : tree type,
1207 : const irange &lhs,
1208 : const frange &op1,
1209 : relation_trio) const
1210 : {
1211 79519 : switch (get_bool_state (r, lhs, type))
1212 : {
1213 30526 : case BRS_TRUE:
1214 : // The TRUE side of NAN > x is unreachable.
1215 30526 : if (op1.known_isnan ())
1216 22 : r.set_undefined ();
1217 30504 : else if (op1.undefined_p ())
1218 : return false;
1219 30504 : else if (build_lt (r, type, op1))
1220 : {
1221 30504 : r.clear_nan ();
1222 : // x > y implies y is not +INF.
1223 30504 : frange_drop_inf (r, type);
1224 : }
1225 : break;
1226 :
1227 48761 : case BRS_FALSE:
1228 : // On The FALSE side of NAN > x, we know nothing about x.
1229 52440 : if (op1.maybe_isnan ())
1230 45082 : r.set_varying (type);
1231 3679 : else if (op1.undefined_p ())
1232 : return false;
1233 : else
1234 3679 : build_ge (r, type, op1);
1235 : break;
1236 :
1237 : default:
1238 : break;
1239 : }
1240 : return true;
1241 : }
1242 :
1243 : // Check if the LHS range indicates a relation between OP1 and OP2.
1244 :
1245 : relation_kind
1246 290522 : operator_gt::op1_op2_relation (const irange &lhs, const frange &,
1247 : const frange &) const
1248 : {
1249 290522 : if (lhs.undefined_p ())
1250 : return VREL_UNDEFINED;
1251 :
1252 : // FALSE = op1 > op2 indicates LE_EXPR.
1253 290522 : if (lhs.zero_p ())
1254 : return VREL_LE;
1255 :
1256 : // TRUE = op1 > op2 indicates GT_EXPR.
1257 129096 : if (!lhs.contains_zero_p ())
1258 128596 : return VREL_GT;
1259 : return VREL_VARYING;
1260 : }
1261 :
1262 : bool
1263 269075 : operator_ge::fold_range (irange &r, tree type,
1264 : const frange &op1, const frange &op2,
1265 : relation_trio rel) const
1266 : {
1267 269075 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
1268 : return true;
1269 :
1270 268715 : if (op1.known_isnan ()
1271 267861 : || op2.known_isnan ()
1272 536526 : || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1273 1610 : r = range_false (type);
1274 267105 : else if (!maybe_isnan (op1, op2)
1275 267105 : && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1276 3130 : r = range_true (type);
1277 : else
1278 263975 : r = range_true_and_false (type);
1279 : return true;
1280 : }
1281 :
1282 : bool
1283 110605 : operator_ge::op1_range (frange &r,
1284 : tree type,
1285 : const irange &lhs,
1286 : const frange &op2,
1287 : relation_trio) const
1288 : {
1289 110605 : switch (get_bool_state (r, lhs, type))
1290 : {
1291 61898 : case BRS_TRUE:
1292 : // The TRUE side of x >= NAN is unreachable.
1293 61898 : if (op2.known_isnan ())
1294 0 : r.set_undefined ();
1295 61898 : else if (op2.undefined_p ())
1296 : return false;
1297 61898 : else if (build_ge (r, type, op2))
1298 61898 : r.clear_nan ();
1299 : break;
1300 :
1301 48545 : case BRS_FALSE:
1302 : // On the FALSE side of x >= NAN, we know nothing about x.
1303 90414 : if (op2.maybe_isnan ())
1304 6676 : r.set_varying (type);
1305 41869 : else if (op2.undefined_p ())
1306 : return false;
1307 : else
1308 41869 : build_lt (r, type, op2);
1309 : break;
1310 :
1311 : default:
1312 : break;
1313 : }
1314 : return true;
1315 : }
1316 :
1317 : bool
1318 13661 : operator_ge::op2_range (frange &r, tree type,
1319 : const irange &lhs,
1320 : const frange &op1,
1321 : relation_trio) const
1322 : {
1323 13661 : switch (get_bool_state (r, lhs, type))
1324 : {
1325 5560 : case BRS_TRUE:
1326 : // The TRUE side of NAN >= x is unreachable.
1327 5560 : if (op1.known_isnan ())
1328 0 : r.set_undefined ();
1329 5560 : else if (op1.undefined_p ())
1330 : return false;
1331 5560 : else if (build_le (r, type, op1))
1332 5560 : r.clear_nan ();
1333 : break;
1334 :
1335 7999 : case BRS_FALSE:
1336 : // On the FALSE side of NAN >= x, we know nothing about x.
1337 8767 : if (op1.maybe_isnan ())
1338 7231 : r.set_varying (type);
1339 768 : else if (op1.undefined_p ())
1340 : return false;
1341 : else
1342 768 : build_gt (r, type, op1);
1343 : break;
1344 :
1345 : default:
1346 : break;
1347 : }
1348 : return true;
1349 : }
1350 :
1351 : // Check if the LHS range indicates a relation between OP1 and OP2.
1352 :
1353 : relation_kind
1354 65051 : operator_ge::op1_op2_relation (const irange &lhs, const frange &,
1355 : const frange &) const
1356 : {
1357 65051 : if (lhs.undefined_p ())
1358 : return VREL_UNDEFINED;
1359 :
1360 : // FALSE = op1 >= op2 indicates LT_EXPR.
1361 65051 : if (lhs.zero_p ())
1362 : return VREL_LT;
1363 :
1364 : // TRUE = op1 >= op2 indicates GE_EXPR.
1365 34316 : if (!lhs.contains_zero_p ())
1366 34099 : return VREL_GE;
1367 : return VREL_VARYING;
1368 : }
1369 :
1370 : // UNORDERED_EXPR comparison.
1371 :
1372 : class foperator_unordered : public range_operator
1373 : {
1374 : using range_operator::fold_range;
1375 : using range_operator::op1_range;
1376 : using range_operator::op2_range;
1377 : public:
1378 : bool fold_range (irange &r, tree type,
1379 : const frange &op1, const frange &op2,
1380 : relation_trio = TRIO_VARYING) const final override;
1381 : bool op1_range (frange &r, tree type,
1382 : const irange &lhs, const frange &op2,
1383 : relation_trio = TRIO_VARYING) const final override;
1384 64576 : bool op2_range (frange &r, tree type,
1385 : const irange &lhs, const frange &op1,
1386 : relation_trio rel = TRIO_VARYING) const final override
1387 : {
1388 64576 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1389 : }
1390 : };
1391 : static const foperator_unordered fop_unordered;
1392 :
1393 : bool
1394 60530 : foperator_unordered::fold_range (irange &r, tree type,
1395 : const frange &op1, const frange &op2,
1396 : relation_trio) const
1397 : {
1398 : // UNORDERED is TRUE if either operand is a NAN.
1399 60530 : if (op1.known_isnan () || op2.known_isnan ())
1400 221 : r = range_true (type);
1401 : // UNORDERED is FALSE if neither operand is a NAN.
1402 63281 : else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1403 1490 : r = range_false (type);
1404 : else
1405 58819 : r = range_true_and_false (type);
1406 60530 : return true;
1407 : }
1408 :
1409 : bool
1410 117206 : foperator_unordered::op1_range (frange &r, tree type,
1411 : const irange &lhs,
1412 : const frange &op2,
1413 : relation_trio trio) const
1414 : {
1415 117206 : relation_kind rel = trio.op1_op2 ();
1416 117206 : switch (get_bool_state (r, lhs, type))
1417 : {
1418 44140 : case BRS_TRUE:
1419 : // Since at least one operand must be NAN, if one of them is
1420 : // not, the other must be.
1421 44140 : if (rel == VREL_EQ || !op2.maybe_isnan ())
1422 10707 : r.set_nan (type);
1423 : else
1424 33433 : r.set_varying (type);
1425 : break;
1426 :
1427 64421 : case BRS_FALSE:
1428 : // A false UNORDERED means both operands are !NAN, so it's
1429 : // impossible for op2 to be a NAN.
1430 64421 : if (op2.known_isnan ())
1431 0 : r.set_undefined ();
1432 : else
1433 : {
1434 64421 : r.set_varying (type);
1435 64421 : r.clear_nan ();
1436 : }
1437 : break;
1438 :
1439 : default:
1440 : break;
1441 : }
1442 117206 : return true;
1443 : }
1444 :
1445 : // ORDERED_EXPR comparison.
1446 :
1447 : class foperator_ordered : public range_operator
1448 : {
1449 : using range_operator::fold_range;
1450 : using range_operator::op1_range;
1451 : using range_operator::op2_range;
1452 : public:
1453 : bool fold_range (irange &r, tree type,
1454 : const frange &op1, const frange &op2,
1455 : relation_trio = TRIO_VARYING) const final override;
1456 : bool op1_range (frange &r, tree type,
1457 : const irange &lhs, const frange &op2,
1458 : relation_trio = TRIO_VARYING) const final override;
1459 31961 : bool op2_range (frange &r, tree type,
1460 : const irange &lhs, const frange &op1,
1461 : relation_trio rel = TRIO_VARYING) const final override
1462 : {
1463 31961 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1464 : }
1465 : };
1466 : static const foperator_ordered fop_ordered;
1467 :
1468 : bool
1469 33224 : foperator_ordered::fold_range (irange &r, tree type,
1470 : const frange &op1, const frange &op2,
1471 : relation_trio) const
1472 : {
1473 33224 : if (op1.known_isnan () || op2.known_isnan ())
1474 360 : r = range_false (type);
1475 36092 : else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1476 1607 : r = range_true (type);
1477 : else
1478 31257 : r = range_true_and_false (type);
1479 33224 : return true;
1480 : }
1481 :
1482 : bool
1483 67783 : foperator_ordered::op1_range (frange &r, tree type,
1484 : const irange &lhs,
1485 : const frange &op2,
1486 : relation_trio trio) const
1487 : {
1488 67783 : relation_kind rel = trio.op1_op2 ();
1489 67783 : switch (get_bool_state (r, lhs, type))
1490 : {
1491 58025 : case BRS_TRUE:
1492 : // The TRUE side of ORDERED means both operands are !NAN, so
1493 : // it's impossible for op2 to be a NAN.
1494 58025 : if (op2.known_isnan ())
1495 10 : r.set_undefined ();
1496 : else
1497 : {
1498 58015 : r.set_varying (type);
1499 58015 : r.clear_nan ();
1500 : }
1501 : break;
1502 :
1503 4971 : case BRS_FALSE:
1504 : // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1505 4971 : if (rel == VREL_EQ)
1506 2122 : r.set_nan (type);
1507 : else
1508 2849 : r.set_varying (type);
1509 : break;
1510 :
1511 : default:
1512 : break;
1513 : }
1514 67783 : return true;
1515 : }
1516 :
1517 : bool
1518 246153 : operator_negate::fold_range (frange &r, tree type,
1519 : const frange &op1, const frange &op2,
1520 : relation_trio) const
1521 : {
1522 246153 : if (empty_range_varying (r, type, op1, op2))
1523 403 : return true;
1524 245750 : if (op1.known_isnan ())
1525 : {
1526 436 : bool sign;
1527 436 : if (op1.nan_signbit_p (sign))
1528 38 : r.set_nan (type, !sign);
1529 : else
1530 398 : r.set_nan (type);
1531 : return true;
1532 : }
1533 :
1534 245314 : r.set_undefined ();
1535 737549 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
1536 : {
1537 246921 : REAL_VALUE_TYPE lb = op1.lower_bound (i);
1538 246921 : REAL_VALUE_TYPE ub = op1.upper_bound (i);
1539 246921 : lb = real_value_negate (&lb);
1540 246921 : ub = real_value_negate (&ub);
1541 246921 : frange tmp (type, ub, lb);
1542 246921 : r.union_ (tmp);
1543 246921 : }
1544 439473 : if (op1.maybe_isnan ())
1545 : {
1546 51159 : bool sign;
1547 51159 : if (op1.nan_signbit_p (sign))
1548 2207 : r.update_nan (!sign);
1549 : else
1550 48952 : r.update_nan ();
1551 : }
1552 : else
1553 194155 : r.clear_nan ();
1554 : return true;
1555 : }
1556 :
1557 : bool
1558 3774 : operator_negate::op1_range (frange &r, tree type,
1559 : const frange &lhs, const frange &op2,
1560 : relation_trio rel) const
1561 : {
1562 3774 : return fold_range (r, type, lhs, op2, rel);
1563 : }
1564 :
1565 : bool
1566 597359 : operator_abs::fold_range (frange &r, tree type,
1567 : const frange &op1, const frange &op2,
1568 : relation_trio) const
1569 : {
1570 597359 : if (empty_range_varying (r, type, op1, op2))
1571 130 : return true;
1572 597229 : if (op1.known_isnan ())
1573 : {
1574 738 : r.set_nan (type, /*sign=*/false);
1575 738 : return true;
1576 : }
1577 :
1578 596491 : const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1579 : // Handle the easy case where everything is positive.
1580 596491 : if (real_compare (GE_EXPR, &lh_lb, &dconst0)
1581 160354 : && !real_iszero (&lh_lb, /*sign=*/true)
1582 754453 : && !op1.maybe_isnan (/*sign=*/true))
1583 : {
1584 157353 : r = op1;
1585 157353 : return true;
1586 : }
1587 :
1588 : // Take the absolute value of each sub-range and union the results.
1589 439138 : r.set_undefined ();
1590 1327096 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
1591 : {
1592 448820 : const REAL_VALUE_TYPE lb = op1.lower_bound (i);
1593 448820 : const REAL_VALUE_TYPE ub = op1.upper_bound (i);
1594 448820 : REAL_VALUE_TYPE min = real_value_abs (&lb);
1595 448820 : REAL_VALUE_TYPE max = real_value_abs (&ub);
1596 : // If the range contains zero then we know that the minimum value in the
1597 : // range will be zero.
1598 448820 : if (real_compare (LE_EXPR, &lb, &dconst0)
1599 448820 : && real_compare (GE_EXPR, &ub, &dconst0))
1600 : {
1601 430341 : if (real_compare (GT_EXPR, &min, &max))
1602 6714 : max = min;
1603 430341 : min = dconst0;
1604 : }
1605 : else
1606 : {
1607 : // If the range was reversed, swap MIN and MAX.
1608 18479 : if (real_compare (GT_EXPR, &min, &max))
1609 8642 : std::swap (min, max);
1610 : }
1611 448820 : frange tmp (type, min, max);
1612 448820 : r.union_ (tmp);
1613 448820 : }
1614 466081 : if (op1.maybe_isnan ())
1615 414290 : r.update_nan (/*sign=*/false);
1616 : else
1617 24848 : r.clear_nan ();
1618 : return true;
1619 : }
1620 :
1621 : bool
1622 341216 : operator_abs::op1_range (frange &r, tree type,
1623 : const frange &lhs, const frange &op2,
1624 : relation_trio) const
1625 : {
1626 341216 : if (empty_range_varying (r, type, lhs, op2))
1627 0 : return true;
1628 341216 : if (lhs.known_isnan ())
1629 : {
1630 1518 : r.set_nan (type);
1631 1518 : return true;
1632 : }
1633 :
1634 : // Start with the positives because negatives are an impossible result.
1635 339698 : frange positives (type, dconst0, frange_val_max (type));
1636 339698 : positives.update_nan (/*sign=*/false);
1637 339698 : positives.intersect (lhs);
1638 339698 : r = positives;
1639 : // Add -NAN if relevant.
1640 513812 : if (r.maybe_isnan ())
1641 : {
1642 165524 : frange neg_nan;
1643 165524 : neg_nan.set_nan (type, true);
1644 165524 : r.union_ (neg_nan);
1645 165524 : }
1646 339698 : if (r.known_isnan () || r.undefined_p ())
1647 : return true;
1648 : // Then add the negative of each pair:
1649 : // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1650 339630 : frange negatives (type, real_value_negate (&positives.upper_bound ()),
1651 339630 : real_value_negate (&positives.lower_bound ()));
1652 339630 : negatives.clear_nan ();
1653 339630 : r.union_ (negatives);
1654 339630 : return true;
1655 339630 : }
1656 :
1657 : class foperator_unordered_lt : public range_operator
1658 : {
1659 : using range_operator::fold_range;
1660 : using range_operator::op1_range;
1661 : using range_operator::op2_range;
1662 : public:
1663 13291 : bool fold_range (irange &r, tree type,
1664 : const frange &op1, const frange &op2,
1665 : relation_trio trio = TRIO_VARYING) const final override
1666 : {
1667 13291 : if (op1.known_isnan () || op2.known_isnan ())
1668 : {
1669 33 : r = range_true (type);
1670 33 : return true;
1671 : }
1672 13258 : frange op1_no_nan = op1;
1673 13258 : frange op2_no_nan = op2;
1674 16484 : if (op1.maybe_isnan ())
1675 10015 : op1_no_nan.clear_nan ();
1676 21488 : if (op2.maybe_isnan ())
1677 5028 : op2_no_nan.clear_nan ();
1678 13258 : if (!range_op_handler (LT_EXPR).fold_range (r, type, op1_no_nan,
1679 : op2_no_nan, trio))
1680 : return false;
1681 : // The result is the same as the ordered version when the
1682 : // comparison is true or when the operands cannot be NANs.
1683 13258 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1684 : return true;
1685 : else
1686 : {
1687 10076 : r = range_true_and_false (type);
1688 10076 : return true;
1689 : }
1690 : }
1691 : bool op1_range (frange &r, tree type,
1692 : const irange &lhs,
1693 : const frange &op2,
1694 : relation_trio trio) const final override;
1695 : bool op2_range (frange &r, tree type,
1696 : const irange &lhs,
1697 : const frange &op1,
1698 : relation_trio trio) const final override;
1699 : };
1700 : static const foperator_unordered_lt fop_unordered_lt;
1701 :
1702 : bool
1703 5245 : foperator_unordered_lt::op1_range (frange &r, tree type,
1704 : const irange &lhs,
1705 : const frange &op2,
1706 : relation_trio) const
1707 : {
1708 5245 : switch (get_bool_state (r, lhs, type))
1709 : {
1710 2083 : case BRS_TRUE:
1711 3864 : if (op2.maybe_isnan ())
1712 302 : r.set_varying (type);
1713 1781 : else if (op2.undefined_p ())
1714 : return false;
1715 : else
1716 1781 : build_lt (r, type, op2);
1717 : break;
1718 :
1719 1502 : case BRS_FALSE:
1720 : // A false UNORDERED_LT means both operands are !NAN, so it's
1721 : // impossible for op2 to be a NAN.
1722 1502 : if (op2.known_isnan ())
1723 0 : r.set_undefined ();
1724 1502 : else if (op2.undefined_p ())
1725 : return false;
1726 1502 : else if (build_ge (r, type, op2))
1727 1502 : r.clear_nan ();
1728 : break;
1729 :
1730 : default:
1731 : break;
1732 : }
1733 : return true;
1734 : }
1735 :
1736 : bool
1737 3147 : foperator_unordered_lt::op2_range (frange &r, tree type,
1738 : const irange &lhs,
1739 : const frange &op1,
1740 : relation_trio) const
1741 : {
1742 3147 : switch (get_bool_state (r, lhs, type))
1743 : {
1744 1354 : case BRS_TRUE:
1745 2005 : if (op1.maybe_isnan ())
1746 703 : r.set_varying (type);
1747 651 : else if (op1.undefined_p ())
1748 : return false;
1749 : else
1750 651 : build_gt (r, type, op1);
1751 : break;
1752 :
1753 133 : case BRS_FALSE:
1754 : // A false UNORDERED_LT means both operands are !NAN, so it's
1755 : // impossible for op1 to be a NAN.
1756 133 : if (op1.known_isnan ())
1757 0 : r.set_undefined ();
1758 133 : else if (op1.undefined_p ())
1759 : return false;
1760 133 : else if (build_le (r, type, op1))
1761 133 : r.clear_nan ();
1762 : break;
1763 :
1764 : default:
1765 : break;
1766 : }
1767 : return true;
1768 : }
1769 :
1770 : class foperator_unordered_le : public range_operator
1771 : {
1772 : using range_operator::fold_range;
1773 : using range_operator::op1_range;
1774 : using range_operator::op2_range;
1775 : public:
1776 180613 : bool fold_range (irange &r, tree type,
1777 : const frange &op1, const frange &op2,
1778 : relation_trio trio = TRIO_VARYING) const final override
1779 : {
1780 180613 : if (op1.known_isnan () || op2.known_isnan ())
1781 : {
1782 94 : r = range_true (type);
1783 94 : return true;
1784 : }
1785 180519 : frange op1_no_nan = op1;
1786 180519 : frange op2_no_nan = op2;
1787 205740 : if (op1.maybe_isnan ())
1788 155274 : op1_no_nan.clear_nan ();
1789 353920 : if (op2.maybe_isnan ())
1790 7112 : op2_no_nan.clear_nan ();
1791 180519 : if (!range_op_handler (LE_EXPR).fold_range (r, type, op1_no_nan,
1792 : op2_no_nan, trio))
1793 : return false;
1794 : // The result is the same as the ordered version when the
1795 : // comparison is true or when the operands cannot be NANs.
1796 180519 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1797 : return true;
1798 : else
1799 : {
1800 156655 : r = range_true_and_false (type);
1801 156655 : return true;
1802 : }
1803 : }
1804 : bool op1_range (frange &r, tree type,
1805 : const irange &lhs, const frange &op2,
1806 : relation_trio = TRIO_VARYING) const final override;
1807 : bool op2_range (frange &r, tree type,
1808 : const irange &lhs, const frange &op1,
1809 : relation_trio = TRIO_VARYING) const final override;
1810 : };
1811 : static const foperator_unordered_le fop_unordered_le;
1812 :
1813 : bool
1814 167325 : foperator_unordered_le::op1_range (frange &r, tree type,
1815 : const irange &lhs, const frange &op2,
1816 : relation_trio) const
1817 : {
1818 167325 : switch (get_bool_state (r, lhs, type))
1819 : {
1820 91750 : case BRS_TRUE:
1821 179515 : if (op2.maybe_isnan ())
1822 3985 : r.set_varying (type);
1823 87765 : else if (op2.undefined_p ())
1824 : return false;
1825 : else
1826 87765 : build_le (r, type, op2);
1827 : break;
1828 :
1829 73965 : case BRS_FALSE:
1830 : // A false UNORDERED_LE means both operands are !NAN, so it's
1831 : // impossible for op2 to be a NAN.
1832 73965 : if (op2.known_isnan ())
1833 0 : r.set_undefined ();
1834 73965 : else if (build_gt (r, type, op2))
1835 73963 : r.clear_nan ();
1836 : break;
1837 :
1838 : default:
1839 : break;
1840 : }
1841 : return true;
1842 : }
1843 :
1844 : bool
1845 10767 : foperator_unordered_le::op2_range (frange &r,
1846 : tree type,
1847 : const irange &lhs,
1848 : const frange &op1,
1849 : relation_trio) const
1850 : {
1851 10767 : switch (get_bool_state (r, lhs, type))
1852 : {
1853 6374 : case BRS_TRUE:
1854 9694 : if (op1.maybe_isnan ())
1855 3054 : r.set_varying (type);
1856 3320 : else if (op1.undefined_p ())
1857 : return false;
1858 : else
1859 3320 : build_ge (r, type, op1);
1860 : break;
1861 :
1862 2783 : case BRS_FALSE:
1863 : // A false UNORDERED_LE means both operands are !NAN, so it's
1864 : // impossible for op1 to be a NAN.
1865 2783 : if (op1.known_isnan ())
1866 0 : r.set_undefined ();
1867 2783 : else if (op1.undefined_p ())
1868 : return false;
1869 2783 : else if (build_lt (r, type, op1))
1870 2783 : r.clear_nan ();
1871 : break;
1872 :
1873 : default:
1874 : break;
1875 : }
1876 : return true;
1877 : }
1878 :
1879 : class foperator_unordered_gt : public range_operator
1880 : {
1881 : using range_operator::fold_range;
1882 : using range_operator::op1_range;
1883 : using range_operator::op2_range;
1884 : public:
1885 54649 : bool fold_range (irange &r, tree type,
1886 : const frange &op1, const frange &op2,
1887 : relation_trio trio = TRIO_VARYING) const final override
1888 : {
1889 54649 : if (op1.known_isnan () || op2.known_isnan ())
1890 : {
1891 152 : r = range_true (type);
1892 152 : return true;
1893 : }
1894 54497 : frange op1_no_nan = op1;
1895 54497 : frange op2_no_nan = op2;
1896 58858 : if (op1.maybe_isnan ())
1897 50117 : op1_no_nan.clear_nan ();
1898 103752 : if (op2.maybe_isnan ())
1899 5242 : op2_no_nan.clear_nan ();
1900 54497 : if (!range_op_handler (GT_EXPR).fold_range (r, type, op1_no_nan,
1901 : op2_no_nan, trio))
1902 : return false;
1903 : // The result is the same as the ordered version when the
1904 : // comparison is true or when the operands cannot be NANs.
1905 54497 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1906 : return true;
1907 : else
1908 : {
1909 50185 : r = range_true_and_false (type);
1910 50185 : return true;
1911 : }
1912 : }
1913 : bool op1_range (frange &r, tree type,
1914 : const irange &lhs, const frange &op2,
1915 : relation_trio = TRIO_VARYING) const final override;
1916 : bool op2_range (frange &r, tree type,
1917 : const irange &lhs, const frange &op1,
1918 : relation_trio = TRIO_VARYING) const final override;
1919 : };
1920 : static const foperator_unordered_gt fop_unordered_gt;
1921 :
1922 : bool
1923 18753 : foperator_unordered_gt::op1_range (frange &r,
1924 : tree type,
1925 : const irange &lhs,
1926 : const frange &op2,
1927 : relation_trio) const
1928 : {
1929 18753 : switch (get_bool_state (r, lhs, type))
1930 : {
1931 4663 : case BRS_TRUE:
1932 9120 : if (op2.maybe_isnan ())
1933 206 : r.set_varying (type);
1934 4457 : else if (op2.undefined_p ())
1935 : return false;
1936 : else
1937 4457 : build_gt (r, type, op2);
1938 : break;
1939 :
1940 12460 : case BRS_FALSE:
1941 : // A false UNORDERED_GT means both operands are !NAN, so it's
1942 : // impossible for op2 to be a NAN.
1943 12460 : if (op2.known_isnan ())
1944 0 : r.set_undefined ();
1945 12460 : else if (op2.undefined_p ())
1946 : return false;
1947 12460 : else if (build_le (r, type, op2))
1948 12460 : r.clear_nan ();
1949 : break;
1950 :
1951 : default:
1952 : break;
1953 : }
1954 : return true;
1955 : }
1956 :
1957 : bool
1958 2951 : foperator_unordered_gt::op2_range (frange &r,
1959 : tree type,
1960 : const irange &lhs,
1961 : const frange &op1,
1962 : relation_trio) const
1963 : {
1964 2951 : switch (get_bool_state (r, lhs, type))
1965 : {
1966 1045 : case BRS_TRUE:
1967 1524 : if (op1.maybe_isnan ())
1968 566 : r.set_varying (type);
1969 479 : else if (op1.undefined_p ())
1970 : return false;
1971 : else
1972 479 : build_lt (r, type, op1);
1973 : break;
1974 :
1975 276 : case BRS_FALSE:
1976 : // A false UNORDERED_GT means both operands are !NAN, so it's
1977 : // impossible for op1 to be a NAN.
1978 276 : if (op1.known_isnan ())
1979 0 : r.set_undefined ();
1980 276 : else if (op1.undefined_p ())
1981 : return false;
1982 276 : else if (build_ge (r, type, op1))
1983 276 : r.clear_nan ();
1984 : break;
1985 :
1986 : default:
1987 : break;
1988 : }
1989 : return true;
1990 : }
1991 :
1992 : class foperator_unordered_ge : public range_operator
1993 : {
1994 : using range_operator::fold_range;
1995 : using range_operator::op1_range;
1996 : using range_operator::op2_range;
1997 : public:
1998 173370 : bool fold_range (irange &r, tree type,
1999 : const frange &op1, const frange &op2,
2000 : relation_trio trio = TRIO_VARYING) const final override
2001 : {
2002 173370 : if (op1.known_isnan () || op2.known_isnan ())
2003 : {
2004 52 : r = range_true (type);
2005 52 : return true;
2006 : }
2007 173318 : frange op1_no_nan = op1;
2008 173318 : frange op2_no_nan = op2;
2009 186722 : if (op1.maybe_isnan ())
2010 159874 : op1_no_nan.clear_nan ();
2011 338812 : if (op2.maybe_isnan ())
2012 7818 : op2_no_nan.clear_nan ();
2013 173318 : if (!range_op_handler (GE_EXPR).fold_range (r, type, op1_no_nan,
2014 : op2_no_nan, trio))
2015 : return false;
2016 : // The result is the same as the ordered version when the
2017 : // comparison is true or when the operands cannot be NANs.
2018 173318 : if (!maybe_isnan (op1, op2) || r == range_true (type))
2019 : return true;
2020 : else
2021 : {
2022 159245 : r = range_true_and_false (type);
2023 159245 : return true;
2024 : }
2025 : }
2026 : bool op1_range (frange &r, tree type,
2027 : const irange &lhs, const frange &op2,
2028 : relation_trio = TRIO_VARYING) const final override;
2029 : bool op2_range (frange &r, tree type,
2030 : const irange &lhs, const frange &op1,
2031 : relation_trio = TRIO_VARYING) const final override;
2032 : };
2033 : static const foperator_unordered_ge fop_unordered_ge;
2034 :
2035 : bool
2036 143996 : foperator_unordered_ge::op1_range (frange &r,
2037 : tree type,
2038 : const irange &lhs,
2039 : const frange &op2,
2040 : relation_trio) const
2041 : {
2042 143996 : switch (get_bool_state (r, lhs, type))
2043 : {
2044 60388 : case BRS_TRUE:
2045 116880 : if (op2.maybe_isnan ())
2046 3896 : r.set_varying (type);
2047 56492 : else if (op2.undefined_p ())
2048 : return false;
2049 : else
2050 56492 : build_ge (r, type, op2);
2051 : break;
2052 :
2053 81936 : case BRS_FALSE:
2054 : // A false UNORDERED_GE means both operands are !NAN, so it's
2055 : // impossible for op2 to be a NAN.
2056 81936 : if (op2.known_isnan ())
2057 0 : r.set_undefined ();
2058 81936 : else if (op2.undefined_p ())
2059 : return false;
2060 81936 : else if (build_lt (r, type, op2))
2061 81932 : r.clear_nan ();
2062 : break;
2063 :
2064 : default:
2065 : break;
2066 : }
2067 : return true;
2068 : }
2069 :
2070 : bool
2071 11346 : foperator_unordered_ge::op2_range (frange &r, tree type,
2072 : const irange &lhs,
2073 : const frange &op1,
2074 : relation_trio) const
2075 : {
2076 11346 : switch (get_bool_state (r, lhs, type))
2077 : {
2078 6137 : case BRS_TRUE:
2079 9091 : if (op1.maybe_isnan ())
2080 3183 : r.set_varying (type);
2081 2954 : else if (op1.undefined_p ())
2082 : return false;
2083 : else
2084 2954 : build_le (r, type, op1);
2085 : break;
2086 :
2087 3657 : case BRS_FALSE:
2088 : // A false UNORDERED_GE means both operands are !NAN, so it's
2089 : // impossible for op1 to be a NAN.
2090 3657 : if (op1.known_isnan ())
2091 0 : r.set_undefined ();
2092 3657 : else if (op1.undefined_p ())
2093 : return false;
2094 3657 : else if (build_gt (r, type, op1))
2095 3657 : r.clear_nan ();
2096 : break;
2097 :
2098 : default:
2099 : break;
2100 : }
2101 : return true;
2102 : }
2103 :
2104 : class foperator_unordered_equal : public range_operator
2105 : {
2106 : using range_operator::fold_range;
2107 : using range_operator::op1_range;
2108 : using range_operator::op2_range;
2109 : public:
2110 3900 : bool fold_range (irange &r, tree type,
2111 : const frange &op1, const frange &op2,
2112 : relation_trio trio = TRIO_VARYING) const final override
2113 : {
2114 3900 : if (op1.known_isnan () || op2.known_isnan ())
2115 : {
2116 0 : r = range_true (type);
2117 0 : return true;
2118 : }
2119 3900 : frange op1_no_nan = op1;
2120 3900 : frange op2_no_nan = op2;
2121 4316 : if (op1.maybe_isnan ())
2122 3484 : op1_no_nan.clear_nan ();
2123 4417 : if (op2.maybe_isnan ())
2124 3383 : op2_no_nan.clear_nan ();
2125 3900 : if (!range_op_handler (EQ_EXPR).fold_range (r, type, op1_no_nan,
2126 : op2_no_nan, trio))
2127 : return false;
2128 : // The result is the same as the ordered version when the
2129 : // comparison is true or when the operands cannot be NANs.
2130 3900 : if (!maybe_isnan (op1, op2) || r == range_true (type))
2131 : return true;
2132 : else
2133 : {
2134 3483 : r = range_true_and_false (type);
2135 3483 : return true;
2136 : }
2137 : }
2138 : bool op1_range (frange &r, tree type,
2139 : const irange &lhs, const frange &op2,
2140 : relation_trio = TRIO_VARYING) const final override;
2141 1738 : bool op2_range (frange &r, tree type,
2142 : const irange &lhs, const frange &op1,
2143 : relation_trio rel = TRIO_VARYING) const final override
2144 : {
2145 1738 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2146 : }
2147 : };
2148 : static const foperator_unordered_equal fop_unordered_equal;
2149 :
2150 : bool
2151 3479 : foperator_unordered_equal::op1_range (frange &r, tree type,
2152 : const irange &lhs,
2153 : const frange &op2,
2154 : relation_trio) const
2155 : {
2156 3479 : switch (get_bool_state (r, lhs, type))
2157 : {
2158 3 : case BRS_TRUE:
2159 : // If it's true, the result is the same as OP2 plus a NAN.
2160 3 : r = op2;
2161 : // Add both zeros if there's the possibility of zero equality.
2162 3 : frange_add_zeros (r, type);
2163 : // Add the possibility of a NAN.
2164 3 : r.update_nan ();
2165 3 : break;
2166 :
2167 0 : case BRS_FALSE:
2168 : // A false UNORDERED_EQ means both operands are !NAN, so it's
2169 : // impossible for op2 to be a NAN.
2170 0 : if (op2.known_isnan ())
2171 0 : r.set_undefined ();
2172 : else
2173 : {
2174 : // The false side indicates !NAN and not equal. We can at least
2175 : // represent !NAN.
2176 0 : r.set_varying (type);
2177 0 : r.clear_nan ();
2178 : }
2179 : break;
2180 :
2181 : default:
2182 : break;
2183 : }
2184 3479 : return true;
2185 : }
2186 :
2187 : class foperator_ltgt : public range_operator
2188 : {
2189 : using range_operator::fold_range;
2190 : using range_operator::op1_range;
2191 : using range_operator::op2_range;
2192 : public:
2193 2397 : bool fold_range (irange &r, tree type,
2194 : const frange &op1, const frange &op2,
2195 : relation_trio trio = TRIO_VARYING) const final override
2196 : {
2197 2397 : if (op1.known_isnan () || op2.known_isnan ())
2198 : {
2199 6 : r = range_false (type);
2200 6 : return true;
2201 : }
2202 2391 : frange op1_no_nan = op1;
2203 2391 : frange op2_no_nan = op2;
2204 2809 : if (op1.maybe_isnan ())
2205 1962 : op1_no_nan.clear_nan ();
2206 2809 : if (op2.maybe_isnan ())
2207 1962 : op2_no_nan.clear_nan ();
2208 2391 : if (!range_op_handler (NE_EXPR).fold_range (r, type, op1_no_nan,
2209 : op2_no_nan, trio))
2210 : return false;
2211 : // The result is the same as the ordered version when the
2212 : // comparison is true or when the operands cannot be NANs.
2213 2391 : if (!maybe_isnan (op1, op2) || r == range_false (type))
2214 : return true;
2215 : else
2216 : {
2217 1952 : r = range_true_and_false (type);
2218 1952 : return true;
2219 : }
2220 : }
2221 : bool op1_range (frange &r, tree type,
2222 : const irange &lhs, const frange &op2,
2223 : relation_trio = TRIO_VARYING) const final override;
2224 1962 : bool op2_range (frange &r, tree type,
2225 : const irange &lhs, const frange &op1,
2226 : relation_trio rel = TRIO_VARYING) const final override
2227 : {
2228 1962 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2229 : }
2230 : };
2231 : static const foperator_ltgt fop_ltgt;
2232 :
2233 : bool
2234 3920 : foperator_ltgt::op1_range (frange &r, tree type,
2235 : const irange &lhs,
2236 : const frange &op2,
2237 : relation_trio) const
2238 : {
2239 3920 : switch (get_bool_state (r, lhs, type))
2240 : {
2241 0 : case BRS_TRUE:
2242 : // A true LTGT means both operands are !NAN, so it's
2243 : // impossible for op2 to be a NAN.
2244 0 : if (op2.known_isnan ())
2245 0 : r.set_undefined ();
2246 : else
2247 : {
2248 : // The true side indicates !NAN and not equal. We can at least
2249 : // represent !NAN.
2250 0 : r.set_varying (type);
2251 0 : r.clear_nan ();
2252 : }
2253 : break;
2254 :
2255 16 : case BRS_FALSE:
2256 : // If it's false, the result is the same as OP2 plus a NAN.
2257 16 : r = op2;
2258 : // Add both zeros if there's the possibility of zero equality.
2259 16 : frange_add_zeros (r, type);
2260 : // Add the possibility of a NAN.
2261 16 : r.update_nan ();
2262 16 : break;
2263 :
2264 : default:
2265 : break;
2266 : }
2267 3920 : return true;
2268 : }
2269 :
2270 : // Final tweaks for float binary op op1_range/op2_range.
2271 : // Return TRUE if the operation is performed and a valid range is available.
2272 :
2273 : static bool
2274 961828 : float_binary_op_range_finish (bool ret, frange &r, tree type,
2275 : const frange &lhs, bool div_op2 = false)
2276 : {
2277 961828 : if (!ret)
2278 : return false;
2279 :
2280 : // If we get a known NAN from reverse op, it means either that
2281 : // the other operand was known NAN (in that case we know nothing),
2282 : // or the reverse operation introduced a known NAN.
2283 : // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
2284 : // 0 / 0 is known NAN. Just punt in that case.
2285 : // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
2286 : // Or if lhs is a known NAN, we also don't know anything.
2287 961828 : if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
2288 : {
2289 5487 : r.set_varying (type);
2290 5487 : return true;
2291 : }
2292 :
2293 : // If lhs isn't NAN, then neither operand could be NAN,
2294 : // even if the reverse operation does introduce a maybe_nan.
2295 1706101 : if (!lhs.maybe_isnan ())
2296 : {
2297 749760 : r.clear_nan ();
2298 38715 : if (div_op2
2299 749760 : ? !lhs.contains_zero_p ()
2300 1280050 : : !(real_isinf (&lhs.lower_bound ())
2301 569005 : || real_isinf (&lhs.upper_bound ())))
2302 : // For reverse + or - or * or op1 of /, if result is finite, then
2303 : // r must be finite too, as X + INF or X - INF or X * INF or
2304 : // INF / X is always +-INF or NAN. For op2 of /, if result is
2305 : // non-zero and not NAN, r must be finite, as X / INF is always
2306 : // 0 or NAN.
2307 544878 : frange_drop_infs (r, type);
2308 : }
2309 : // If lhs is a maybe or known NAN, the operand could be
2310 : // NAN.
2311 : else
2312 206581 : r.update_nan ();
2313 : return true;
2314 : }
2315 :
2316 : // True if [lb, ub] is [+-0, +-0].
2317 : static bool
2318 5929327 : zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2319 : {
2320 5929327 : return real_iszero (&lb) && real_iszero (&ub);
2321 : }
2322 :
2323 : // True if +0 or -0 is in [lb, ub] range.
2324 : static bool
2325 4915287 : contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2326 : {
2327 4915287 : return (real_compare (LE_EXPR, &lb, &dconst0)
2328 4915287 : && real_compare (GE_EXPR, &ub, &dconst0));
2329 : }
2330 :
2331 : // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
2332 : static bool
2333 3436102 : singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2334 : {
2335 3436102 : return real_isinf (&lb) && real_isinf (&ub, real_isneg (&lb));
2336 : }
2337 :
2338 : // Return -1 if binary op result must have sign bit set,
2339 : // 1 if binary op result must have sign bit clear,
2340 : // 0 otherwise.
2341 : // Sign bit of binary op result is exclusive or of the
2342 : // operand's sign bits.
2343 : static int
2344 1528061 : signbit_known_p (const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
2345 : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub)
2346 : {
2347 1528061 : if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
2348 1528061 : && real_isneg (&rh_lb) == real_isneg (&rh_ub))
2349 : {
2350 196855 : if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
2351 : return 1;
2352 : else
2353 37328 : return -1;
2354 : }
2355 : return 0;
2356 : }
2357 :
2358 : // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
2359 : // signbit_known.
2360 : static void
2361 7199 : zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2362 : {
2363 7199 : ub = lb = dconst0;
2364 7199 : if (signbit_known <= 0)
2365 6952 : lb = dconstm0;
2366 6952 : if (signbit_known < 0)
2367 66 : ub = lb;
2368 7199 : }
2369 :
2370 : // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
2371 : // signbit_known.
2372 : static void
2373 4623 : inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2374 : {
2375 4623 : if (signbit_known > 0)
2376 1025 : ub = lb = dconstinf;
2377 3598 : else if (signbit_known < 0)
2378 157 : ub = lb = dconstninf;
2379 : else
2380 : {
2381 3441 : lb = dconstninf;
2382 3441 : ub = dconstinf;
2383 : }
2384 4623 : }
2385 :
2386 : // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
2387 : // signbit_known.
2388 : static void
2389 1073209 : zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2390 : {
2391 1073209 : if (signbit_known > 0)
2392 : {
2393 18434 : lb = dconst0;
2394 18434 : ub = dconstinf;
2395 : }
2396 1054775 : else if (signbit_known < 0)
2397 : {
2398 6653 : lb = dconstninf;
2399 6653 : ub = dconstm0;
2400 : }
2401 : else
2402 : {
2403 1048122 : lb = dconstninf;
2404 1048122 : ub = dconstinf;
2405 : }
2406 1073209 : }
2407 :
2408 : bool
2409 187813 : operator_plus::op1_range (frange &r, tree type, const frange &lhs,
2410 : const frange &op2, relation_trio) const
2411 : {
2412 187813 : if (lhs.undefined_p ())
2413 : return false;
2414 187813 : range_op_handler minus (MINUS_EXPR);
2415 187813 : if (!minus)
2416 : return false;
2417 187813 : frange wlhs = lhs;
2418 187813 : wlhs.widen (type);
2419 187813 : return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
2420 : r, type, wlhs);
2421 187813 : }
2422 :
2423 : bool
2424 80248 : operator_plus::op2_range (frange &r, tree type,
2425 : const frange &lhs, const frange &op1,
2426 : relation_trio) const
2427 : {
2428 80248 : return op1_range (r, type, lhs, op1);
2429 : }
2430 :
2431 : void
2432 2165568 : operator_plus::rv_fold (frange &r, tree type,
2433 : const REAL_VALUE_TYPE &lh_lb,
2434 : const REAL_VALUE_TYPE &lh_ub,
2435 : const REAL_VALUE_TYPE &rh_lb,
2436 : const REAL_VALUE_TYPE &rh_ub,
2437 : relation_kind) const
2438 : {
2439 2165568 : REAL_VALUE_TYPE lb, ub;
2440 2165568 : bool maybe_nan = false;
2441 :
2442 2165568 : frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
2443 2165568 : frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
2444 :
2445 : // [-INF] + [+INF] = NAN
2446 2165568 : if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
2447 : maybe_nan = true;
2448 : // [+INF] + [-INF] = NAN
2449 816343 : else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
2450 : maybe_nan = true;
2451 :
2452 : // Handle possible NANs by saturating to the appropriate INF if only
2453 : // one end is a NAN. If both ends are a NAN, just return a NAN.
2454 2165568 : bool lb_nan = real_isnan (&lb);
2455 2165568 : bool ub_nan = real_isnan (&ub);
2456 2165568 : if (lb_nan && ub_nan)
2457 : {
2458 0 : r.set_nan (type);
2459 0 : return;
2460 : }
2461 2165568 : if (lb_nan)
2462 360 : lb = dconstninf;
2463 2165208 : else if (ub_nan)
2464 0 : ub = dconstinf;
2465 2165568 : r.set (type, lb, ub, nan_state (maybe_nan));
2466 : }
2467 :
2468 :
2469 : bool
2470 99263 : operator_minus::op1_range (frange &r, tree type,
2471 : const frange &lhs, const frange &op2,
2472 : relation_trio) const
2473 : {
2474 99263 : if (lhs.undefined_p ())
2475 : return false;
2476 99263 : frange wlhs = lhs;
2477 99263 : wlhs.widen (type);
2478 99263 : return float_binary_op_range_finish (
2479 198526 : range_op_handler (PLUS_EXPR).fold_range (r, type, wlhs, op2),
2480 : r, type, wlhs);
2481 99263 : }
2482 :
2483 : bool
2484 141730 : operator_minus::op2_range (frange &r, tree type,
2485 : const frange &lhs, const frange &op1,
2486 : relation_trio) const
2487 : {
2488 141730 : if (lhs.undefined_p ())
2489 : return false;
2490 141730 : frange wlhs = lhs;
2491 141730 : wlhs.widen (type);
2492 141730 : return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
2493 : r, type, wlhs);
2494 141730 : }
2495 :
2496 : void
2497 1006286 : operator_minus::rv_fold (frange &r, tree type,
2498 : const REAL_VALUE_TYPE &lh_lb,
2499 : const REAL_VALUE_TYPE &lh_ub,
2500 : const REAL_VALUE_TYPE &rh_lb,
2501 : const REAL_VALUE_TYPE &rh_ub,
2502 : relation_kind) const
2503 : {
2504 1006286 : REAL_VALUE_TYPE lb, ub;
2505 1006286 : bool maybe_nan = false;
2506 :
2507 1006286 : frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
2508 1006286 : frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
2509 :
2510 : // [+INF] - [+INF] = NAN
2511 1006286 : if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
2512 : maybe_nan = true;
2513 : // [-INF] - [-INF] = NAN
2514 708353 : else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
2515 : maybe_nan = true;
2516 :
2517 : // Handle possible NANs by saturating to the appropriate INF if only
2518 : // one end is a NAN. If both ends are a NAN, just return a NAN.
2519 1006286 : bool lb_nan = real_isnan (&lb);
2520 1006286 : bool ub_nan = real_isnan (&ub);
2521 1006286 : if (lb_nan && ub_nan)
2522 : {
2523 826 : r.set_nan (type);
2524 826 : return;
2525 : }
2526 1005460 : if (lb_nan)
2527 1443 : lb = dconstninf;
2528 1004017 : else if (ub_nan)
2529 1738 : ub = dconstinf;
2530 1005460 : r.set (type, lb, ub, nan_state (maybe_nan));
2531 : }
2532 :
2533 :
2534 : // Given CP[0] to CP[3] floating point values rounded to -INF,
2535 : // set LB to the smallest of them (treating -0 as smaller to +0).
2536 : // Given CP[4] to CP[7] floating point values rounded to +INF,
2537 : // set UB to the largest of them (treating -0 as smaller to +0).
2538 :
2539 : static void
2540 1295756 : find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
2541 : const REAL_VALUE_TYPE (&cp)[8])
2542 : {
2543 1295756 : lb = cp[0];
2544 1295756 : ub = cp[4];
2545 5183024 : for (int i = 1; i < 4; ++i)
2546 : {
2547 3887268 : if (real_less (&cp[i], &lb)
2548 3887268 : || (real_iszero (&lb) && real_isnegzero (&cp[i])))
2549 439288 : lb = cp[i];
2550 3887268 : if (real_less (&ub, &cp[i + 4])
2551 3887268 : || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
2552 1196590 : ub = cp[i + 4];
2553 : }
2554 1295756 : }
2555 :
2556 :
2557 : bool
2558 380249 : operator_mult::op1_range (frange &r, tree type,
2559 : const frange &lhs, const frange &op2,
2560 : relation_trio) const
2561 : {
2562 380249 : if (lhs.undefined_p ())
2563 : return false;
2564 380249 : range_op_handler rdiv (RDIV_EXPR);
2565 380249 : if (!rdiv)
2566 : return false;
2567 380249 : frange wlhs = lhs;
2568 380249 : wlhs.widen (type);
2569 380249 : bool ret = rdiv.fold_range (r, type, wlhs, op2);
2570 380249 : if (ret == false)
2571 : return false;
2572 380249 : if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2573 16 : return float_binary_op_range_finish (ret, r, type, wlhs);
2574 380233 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2575 380233 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2576 380233 : const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2577 380233 : const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2578 704915 : if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
2579 545498 : || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2580 46281 : && (real_isinf (&op2_lb) || real_isinf (&op2_ub))))
2581 : {
2582 : // If both lhs and op2 could be zeros or both could be infinities,
2583 : // we don't know anything about op1 except maybe for the sign
2584 : // and perhaps if it can be NAN or not.
2585 168453 : REAL_VALUE_TYPE lb, ub;
2586 168453 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2587 168453 : zero_to_inf_range (lb, ub, signbit_known);
2588 168453 : r.set (type, lb, ub);
2589 : }
2590 : // Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
2591 : // or if lhs must be zero and op2 doesn't include zero, it would be
2592 : // UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
2593 : // range. Those are supersets of UNDEFINED, so let's keep that way.
2594 380233 : return float_binary_op_range_finish (ret, r, type, wlhs);
2595 : }
2596 :
2597 : bool
2598 91403 : operator_mult::op2_range (frange &r, tree type,
2599 : const frange &lhs, const frange &op1,
2600 : relation_trio) const
2601 : {
2602 91403 : return op1_range (r, type, lhs, op1);
2603 : }
2604 :
2605 : void
2606 1299251 : operator_mult::rv_fold (frange &r, tree type,
2607 : const REAL_VALUE_TYPE &lh_lb,
2608 : const REAL_VALUE_TYPE &lh_ub,
2609 : const REAL_VALUE_TYPE &rh_lb,
2610 : const REAL_VALUE_TYPE &rh_ub,
2611 : relation_kind kind) const
2612 : {
2613 1299251 : bool is_square
2614 : = (kind == VREL_EQ
2615 38826 : && real_equal (&lh_lb, &rh_lb)
2616 38823 : && real_equal (&lh_ub, &rh_ub)
2617 38823 : && real_isneg (&lh_lb) == real_isneg (&rh_lb)
2618 1338074 : && real_isneg (&lh_ub) == real_isneg (&rh_ub));
2619 1260428 : REAL_VALUE_TYPE lb, ub;
2620 2113154 : bool maybe_nan = false;
2621 : // x * x never produces a new NAN and we only multiply the same
2622 : // values, so the 0 * INF problematic cases never appear there.
2623 1260428 : if (!is_square)
2624 : {
2625 : // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2626 1284094 : if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
2627 1284064 : || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
2628 : {
2629 85 : r.set_nan (type);
2630 446525 : return;
2631 : }
2632 :
2633 : // Otherwise, if one range includes zero and the other ends with +-INF,
2634 : // it is a maybe NAN.
2635 1260343 : if ((contains_zero_p (lh_lb, lh_ub)
2636 1041168 : && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2637 1906414 : || (contains_zero_p (rh_lb, rh_ub)
2638 237036 : && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
2639 : {
2640 446440 : maybe_nan = true;
2641 :
2642 446440 : int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2643 :
2644 : // If one of the ranges that includes INF is singleton
2645 : // and the other range includes zero, the resulting
2646 : // range is INF and NAN, because the 0 * INF boundary
2647 : // case will be NAN, but already nextafter (0, 1) * INF
2648 : // is INF.
2649 446440 : if (singleton_inf_p (lh_lb, lh_ub)
2650 446440 : || singleton_inf_p (rh_lb, rh_ub))
2651 : {
2652 1312 : inf_range (lb, ub, signbit_known);
2653 1312 : r.set (type, lb, ub, nan_state (true));
2654 1312 : return;
2655 : }
2656 :
2657 : // If one of the multiplicands must be zero, the resulting
2658 : // range is +-0 and NAN.
2659 445128 : if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
2660 : {
2661 6364 : zero_range (lb, ub, signbit_known);
2662 6364 : r.set (type, lb, ub, nan_state (true));
2663 6364 : return;
2664 : }
2665 :
2666 : // Otherwise one of the multiplicands could be
2667 : // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
2668 : // or similarly with different signs. 0.0 * DBL_MAX
2669 : // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
2670 : // so if the signs are always the same or always different,
2671 : // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
2672 438764 : zero_to_inf_range (lb, ub, signbit_known);
2673 438764 : r.set (type, lb, ub, nan_state (true));
2674 438764 : return;
2675 : }
2676 : }
2677 :
2678 852726 : REAL_VALUE_TYPE cp[8];
2679 : // Do a cross-product. At this point none of the multiplications
2680 : // should produce a NAN.
2681 852726 : frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2682 852726 : frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2683 852726 : if (is_square)
2684 : {
2685 : // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
2686 : // as maximum and -0.0 as minimum if 0.0 is in the range,
2687 : // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
2688 : // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
2689 : // x and y are bitwise equal, just that they compare equal.
2690 38823 : if (contains_zero_p (lh_lb, lh_ub))
2691 : {
2692 35154 : if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
2693 1514 : cp[1] = dconst0;
2694 : else
2695 33640 : cp[1] = dconstm0;
2696 : }
2697 : else
2698 3669 : cp[1] = cp[0];
2699 38823 : cp[2] = cp[0];
2700 38823 : cp[5] = cp[4];
2701 38823 : cp[6] = cp[4];
2702 : }
2703 : else
2704 : {
2705 813903 : frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2706 813903 : frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2707 813903 : frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2708 813903 : frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2709 : }
2710 852726 : frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2711 852726 : frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2712 :
2713 852726 : find_range (lb, ub, cp);
2714 :
2715 852726 : gcc_checking_assert (!real_isnan (&lb));
2716 852726 : gcc_checking_assert (!real_isnan (&ub));
2717 852726 : r.set (type, lb, ub, nan_state (maybe_nan));
2718 : }
2719 :
2720 :
2721 : class foperator_div : public range_operator
2722 : {
2723 : using range_operator::op1_range;
2724 : using range_operator::op2_range;
2725 : public:
2726 33711 : virtual bool op1_range (frange &r, tree type,
2727 : const frange &lhs,
2728 : const frange &op2,
2729 : relation_trio = TRIO_VARYING) const final override
2730 : {
2731 33711 : if (lhs.undefined_p ())
2732 : return false;
2733 33711 : frange wlhs = lhs;
2734 33711 : wlhs.widen (type);
2735 33711 : bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
2736 33711 : if (!ret)
2737 : return ret;
2738 33711 : if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2739 338 : return float_binary_op_range_finish (ret, r, type, wlhs);
2740 33373 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2741 33373 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2742 33373 : const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2743 33373 : const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2744 33373 : if ((contains_zero_p (lhs_lb, lhs_ub)
2745 25133 : && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
2746 40503 : || ((contains_zero_p (op2_lb, op2_ub))
2747 8491 : && (real_isinf (&lhs_lb) || real_isinf (&lhs_ub))))
2748 : {
2749 : // If both lhs could be zero and op2 infinity or vice versa,
2750 : // we don't know anything about op1 except maybe for the sign
2751 : // and perhaps if it can be NAN or not.
2752 25893 : REAL_VALUE_TYPE lb, ub;
2753 25893 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2754 25893 : zero_to_inf_range (lb, ub, signbit_known);
2755 25893 : r.set (type, lb, ub);
2756 : }
2757 33373 : return float_binary_op_range_finish (ret, r, type, wlhs);
2758 : }
2759 58587 : virtual bool op2_range (frange &r, tree type,
2760 : const frange &lhs,
2761 : const frange &op1,
2762 : relation_trio = TRIO_VARYING) const final override
2763 : {
2764 58587 : if (lhs.undefined_p ())
2765 : return false;
2766 58587 : frange wlhs = lhs;
2767 58587 : wlhs.widen (type);
2768 58587 : bool ret = fold_range (r, type, op1, wlhs);
2769 58587 : if (!ret)
2770 : return ret;
2771 58587 : if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
2772 18 : return float_binary_op_range_finish (ret, r, type, wlhs, true);
2773 58569 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2774 58569 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2775 58569 : const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
2776 58569 : const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
2777 106005 : if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
2778 62424 : || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2779 7591 : && (real_isinf (&op1_lb) || real_isinf (&op1_ub))))
2780 : {
2781 : // If both lhs and op1 could be zeros or both could be infinities,
2782 : // we don't know anything about op2 except maybe for the sign
2783 : // and perhaps if it can be NAN or not.
2784 47973 : REAL_VALUE_TYPE lb, ub;
2785 47973 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
2786 47973 : zero_to_inf_range (lb, ub, signbit_known);
2787 47973 : r.set (type, lb, ub);
2788 : }
2789 58569 : return float_binary_op_range_finish (ret, r, type, wlhs, true);
2790 : }
2791 : private:
2792 839943 : void rv_fold (frange &r, tree type,
2793 : const REAL_VALUE_TYPE &lh_lb,
2794 : const REAL_VALUE_TYPE &lh_ub,
2795 : const REAL_VALUE_TYPE &rh_lb,
2796 : const REAL_VALUE_TYPE &rh_ub,
2797 : relation_kind) const final override
2798 : {
2799 : // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
2800 841403 : if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
2801 840768 : || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
2802 : {
2803 641 : r.set_nan (type);
2804 396913 : return;
2805 : }
2806 :
2807 839302 : REAL_VALUE_TYPE lb, ub;
2808 839302 : bool maybe_nan = false;
2809 : // If +-0.0 is in both ranges, it is a maybe NAN.
2810 839302 : if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
2811 : maybe_nan = true;
2812 : // If +-INF is in both ranges, it is a maybe NAN.
2813 932054 : else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
2814 587549 : && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2815 : maybe_nan = true;
2816 :
2817 839302 : int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2818 :
2819 : // If dividend must be zero, the range is just +-0
2820 : // (including if the divisor is +-INF).
2821 : // If divisor must be +-INF, the range is just +-0
2822 : // (including if the dividend is zero).
2823 839302 : if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
2824 : {
2825 835 : zero_range (lb, ub, signbit_known);
2826 835 : r.set (type, lb, ub, nan_state (maybe_nan));
2827 835 : return;
2828 : }
2829 :
2830 : // If divisor must be zero, the range is just +-INF
2831 : // (including if the dividend is +-INF).
2832 : // If dividend must be +-INF, the range is just +-INF
2833 : // (including if the dividend is zero).
2834 838467 : if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
2835 : {
2836 3311 : inf_range (lb, ub, signbit_known);
2837 3311 : r.set (type, lb, ub, nan_state (maybe_nan));
2838 3311 : return;
2839 : }
2840 :
2841 : // Otherwise if both operands may be zero, divisor could be
2842 : // nextafter(0.0, +-1.0) and dividend +-0.0
2843 : // in which case result is going to INF or vice versa and
2844 : // result +0.0. So, all we can say for that case is if the
2845 : // signs of divisor and dividend are always the same we have
2846 : // [+0.0, +INF], if they are always different we have
2847 : // [-INF, -0.0]. If they vary, VARYING.
2848 : // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
2849 : // in which case result is going to INF or vice versa and
2850 : // result +0.0. So, all we can say for that case is if the
2851 : // signs of divisor and dividend are always the same we have
2852 : // [+0.0, +INF], if they are always different we have
2853 : // [-INF, -0.0]. If they vary, VARYING.
2854 835156 : if (maybe_nan)
2855 : {
2856 392126 : zero_to_inf_range (lb, ub, signbit_known);
2857 392126 : r.set (type, lb, ub, nan_state (maybe_nan));
2858 392126 : return;
2859 : }
2860 :
2861 443030 : REAL_VALUE_TYPE cp[8];
2862 : // Do a cross-division. At this point none of the divisions should
2863 : // produce a NAN.
2864 443030 : frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2865 443030 : frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2866 443030 : frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2867 443030 : frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2868 443030 : frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2869 443030 : frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2870 443030 : frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2871 443030 : frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2872 :
2873 443030 : find_range (lb, ub, cp);
2874 :
2875 : // If divisor may be zero (but is not known to be only zero),
2876 : // and dividend can't be zero, the range can go up to -INF or +INF
2877 : // depending on the signs.
2878 443030 : if (contains_zero_p (rh_lb, rh_ub))
2879 : {
2880 44690 : if (signbit_known <= 0)
2881 39965 : real_inf (&lb, true);
2882 39965 : if (signbit_known >= 0)
2883 44670 : real_inf (&ub, false);
2884 : }
2885 :
2886 443030 : gcc_checking_assert (!real_isnan (&lb));
2887 443030 : gcc_checking_assert (!real_isnan (&ub));
2888 443030 : r.set (type, lb, ub, nan_state (maybe_nan));
2889 : }
2890 : };
2891 : static const foperator_div fop_div;
2892 :
2893 : bool
2894 946129 : operator_cast::fold_range (frange &r, tree type, const frange &op1,
2895 : const frange &, relation_trio) const
2896 : {
2897 946129 : enum machine_mode mode = TYPE_MODE (type);
2898 6622903 : bool mode_composite = MODE_COMPOSITE_P (mode);
2899 :
2900 946129 : if (empty_range_varying (r, type, op1, op1))
2901 1096 : return true;
2902 3780132 : if (!MODE_HAS_NANS (mode) && op1.maybe_isnan ())
2903 : {
2904 0 : r.set_varying (type);
2905 0 : return true;
2906 : }
2907 945033 : if (op1.known_isnan ())
2908 : {
2909 2766 : r.set_nan (type);
2910 2766 : return true;
2911 : }
2912 :
2913 942267 : r.set_undefined ();
2914 2854084 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
2915 : {
2916 969550 : REAL_VALUE_TYPE lb, ub;
2917 969550 : const REAL_VALUE_TYPE &lh_lb = op1.lower_bound (i);
2918 969550 : const REAL_VALUE_TYPE &lh_ub = op1.upper_bound (i);
2919 969550 : real_convert (&lb, mode, &lh_lb);
2920 969550 : real_convert (&ub, mode, &lh_ub);
2921 :
2922 969550 : if (flag_rounding_math)
2923 : {
2924 41466 : if (real_less (&lh_lb, &lb))
2925 : {
2926 3268 : if (mode_composite
2927 3268 : && (real_isdenormal (&lb, mode) || real_iszero (&lb)))
2928 : {
2929 : // IBM extended denormals only have DFmode precision.
2930 0 : REAL_VALUE_TYPE tmp, tmp2;
2931 0 : real_convert (&tmp2, DFmode, &lh_lb);
2932 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
2933 : &dconstninf);
2934 0 : real_convert (&lb, mode, &tmp);
2935 : }
2936 : else
2937 3268 : frange_nextafter (mode, lb, dconstninf);
2938 : }
2939 41466 : if (real_less (&ub, &lh_ub))
2940 : {
2941 1450 : if (mode_composite
2942 1450 : && (real_isdenormal (&ub, mode) || real_iszero (&ub)))
2943 : {
2944 : // IBM extended denormals only have DFmode precision.
2945 0 : REAL_VALUE_TYPE tmp, tmp2;
2946 0 : real_convert (&tmp2, DFmode, &lh_ub);
2947 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
2948 : &dconstinf);
2949 0 : real_convert (&ub, mode, &tmp);
2950 : }
2951 : else
2952 1450 : frange_nextafter (mode, ub, dconstinf);
2953 : }
2954 : }
2955 :
2956 969550 : frange tmp;
2957 969550 : tmp.set (type, lb, ub, op1.get_nan_state ());
2958 969550 : r.union_ (tmp);
2959 969550 : }
2960 :
2961 942267 : if (flag_trapping_math
2962 4268890 : && MODE_HAS_INFINITIES (TYPE_MODE (type))
2963 831656 : && r.known_isinf ()
2964 942351 : && !op1.known_isinf ())
2965 : {
2966 1 : REAL_VALUE_TYPE inf = r.lower_bound ();
2967 1 : if (real_isneg (&inf))
2968 : {
2969 0 : REAL_VALUE_TYPE min = real_min_representable (type);
2970 0 : r.set (type, inf, min);
2971 : }
2972 : else
2973 : {
2974 1 : REAL_VALUE_TYPE max = real_max_representable (type);
2975 1 : r.set (type, max, inf);
2976 : }
2977 : }
2978 :
2979 942267 : r.flush_denormals_to_zero ();
2980 942267 : return true;
2981 : }
2982 :
2983 : // Implement fold for a cast from float to another float.
2984 : bool
2985 60475 : operator_cast::op1_range (frange &r, tree type, const frange &lhs,
2986 : const frange &op2, relation_trio) const
2987 : {
2988 60475 : if (lhs.undefined_p ())
2989 : return false;
2990 60475 : tree lhs_type = lhs.type ();
2991 60475 : enum machine_mode mode = TYPE_MODE (type);
2992 60475 : enum machine_mode lhs_mode = TYPE_MODE (lhs_type);
2993 60475 : frange wlhs;
2994 60475 : bool rm;
2995 60475 : if (REAL_MODE_FORMAT (mode)->ieee_bits
2996 55295 : && REAL_MODE_FORMAT (lhs_mode)->ieee_bits
2997 50077 : && (REAL_MODE_FORMAT (lhs_mode)->ieee_bits
2998 : >= REAL_MODE_FORMAT (mode)->ieee_bits)
2999 81798 : && pow2p_hwi (REAL_MODE_FORMAT (mode)->ieee_bits))
3000 : {
3001 : /* If the cast is widening from IEEE exchange mode to
3002 : wider exchange mode or extended mode, no need to extend
3003 : the range on reverse operation. */
3004 21323 : rm = false;
3005 21323 : wlhs = lhs;
3006 : }
3007 : else
3008 : {
3009 39152 : rm = true;
3010 39152 : wlhs = lhs;
3011 39152 : wlhs.widen (lhs_type);
3012 : }
3013 60475 : auto save_flag_rounding_math = flag_rounding_math;
3014 60475 : flag_rounding_math = rm;
3015 60475 : bool ret = float_binary_op_range_finish (fold_range (r, type, wlhs, op2),
3016 : r, type, lhs);
3017 60475 : flag_rounding_math = save_flag_rounding_math;
3018 60475 : return ret;
3019 60475 : }
3020 :
3021 : // Implement fold for a cast from float to an int.
3022 : bool
3023 217209 : operator_cast::fold_range (irange &r, tree type, const frange &op1,
3024 : const irange &, relation_trio) const
3025 : {
3026 217209 : if (empty_range_varying (r, type, op1, op1))
3027 824 : return true;
3028 216385 : if (op1.maybe_isnan () || op1.maybe_isinf ())
3029 : {
3030 185248 : r.set_varying (type);
3031 185248 : return true;
3032 : }
3033 31137 : REAL_VALUE_TYPE l, u;
3034 31137 : l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
3035 31137 : u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
3036 :
3037 31137 : r.set_undefined ();
3038 73075 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
3039 : {
3040 31843 : REAL_VALUE_TYPE lb, ub;
3041 31843 : real_trunc (&lb, VOIDmode, &op1.lower_bound (i));
3042 31843 : real_trunc (&ub, VOIDmode, &op1.upper_bound (i));
3043 31843 : if (real_less (&lb, &l))
3044 : {
3045 11903 : r.set_varying (type);
3046 21042 : return true;
3047 : }
3048 19940 : if (real_less (&u, &ub))
3049 : {
3050 9139 : r.set_varying (type);
3051 9139 : return true;
3052 : }
3053 10801 : bool fail = false;
3054 10801 : wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
3055 10801 : wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
3056 10801 : if (fail)
3057 : {
3058 0 : r.set_varying (type);
3059 0 : return true;
3060 : }
3061 10801 : int_range<2> tmp (type, wlb, wub);
3062 10801 : r.union_ (tmp);
3063 10801 : }
3064 : return true;
3065 : }
3066 :
3067 : // Implement op1_range for a cast from float to an int.
3068 : bool
3069 10103 : operator_cast::op1_range (frange &r, tree type, const irange &lhs,
3070 : const frange &, relation_trio) const
3071 : {
3072 10103 : if (lhs.undefined_p ())
3073 : return false;
3074 10103 : REAL_VALUE_TYPE lb, lbo, ub, ubo;
3075 10103 : wide_int lhs_lb = lhs.lower_bound ();
3076 10103 : wide_int lhs_ub = lhs.upper_bound ();
3077 10103 : tree lhs_type = lhs.type ();
3078 10103 : enum machine_mode mode = TYPE_MODE (type);
3079 10103 : real_from_integer (&lbo, VOIDmode, lhs_lb, TYPE_SIGN (lhs_type));
3080 10103 : real_from_integer (&ubo, VOIDmode, lhs_ub, TYPE_SIGN (lhs_type));
3081 10103 : real_convert (&lb, mode, &lbo);
3082 10103 : real_convert (&ub, mode, &ubo);
3083 10103 : if (real_identical (&lb, &lbo))
3084 : {
3085 : /* If low bound is exactly representable in type,
3086 : use nextafter (lb - 1., +inf). */
3087 9869 : real_arithmetic (&lb, PLUS_EXPR, &lbo, &dconstm1);
3088 9869 : real_convert (&lb, mode, &lb);
3089 9869 : if (!real_identical (&lb, &lbo))
3090 8423 : frange_nextafter (mode, lb, dconstinf);
3091 9869 : if (real_identical (&lb, &lbo))
3092 1448 : frange_nextafter (mode, lb, dconstninf);
3093 : }
3094 234 : else if (real_less (&lbo, &lb))
3095 9 : frange_nextafter (mode, lb, dconstninf);
3096 10103 : if (real_identical (&ub, &ubo))
3097 : {
3098 : /* If upper bound is exactly representable in type,
3099 : use nextafter (ub + 1., -inf). */
3100 6308 : real_arithmetic (&ub, PLUS_EXPR, &ubo, &dconst1);
3101 6308 : real_convert (&ub, mode, &ub);
3102 6308 : if (!real_identical (&ub, &ubo))
3103 6154 : frange_nextafter (mode, ub, dconstninf);
3104 6308 : if (real_identical (&ub, &ubo))
3105 154 : frange_nextafter (mode, ub, dconstinf);
3106 : }
3107 3795 : else if (real_less (&ub, &ubo))
3108 0 : frange_nextafter (mode, ub, dconstinf);
3109 10103 : r.set (type, lb, ub, nan_state (false));
3110 10103 : return true;
3111 10103 : }
3112 :
3113 : // Implement fold for a cast from int to a float.
3114 : bool
3115 877619 : operator_cast::fold_range (frange &r, tree type, const irange &op1,
3116 : const frange &, relation_trio) const
3117 : {
3118 877619 : if (empty_range_varying (r, type, op1, op1))
3119 1491 : return true;
3120 876128 : tree op1_type = op1.type ();
3121 876128 : r.set_undefined ();
3122 2700936 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
3123 : {
3124 948680 : REAL_VALUE_TYPE lb, ub;
3125 948680 : wide_int op1_lb = op1.lower_bound (i);
3126 948680 : wide_int op1_ub = op1.upper_bound (i);
3127 948680 : enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
3128 948680 : real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
3129 948680 : real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
3130 948680 : if (flag_rounding_math)
3131 : {
3132 1363 : REAL_VALUE_TYPE lbo = lb, ubo = ub;
3133 1363 : mode = TYPE_MODE (type);
3134 1363 : real_convert (&lb, mode, &lb);
3135 1363 : real_convert (&ub, mode, &ub);
3136 1363 : if (real_less (&lbo, &lb))
3137 316 : frange_nextafter (mode, lb, dconstninf);
3138 1363 : if (real_less (&ub, &ubo))
3139 186 : frange_nextafter (mode, ub, dconstinf);
3140 : }
3141 948680 : frange tmp;
3142 948680 : tmp.set (type, lb, ub, nan_state (false));
3143 948680 : r.union_ (tmp);
3144 948710 : }
3145 876128 : if (r.undefined_p ())
3146 0 : r.set_varying (type);
3147 : return true;
3148 : }
3149 :
3150 : // Implement op1_range for a cast from int to a float.
3151 : bool
3152 246893 : operator_cast::op1_range (irange &r, tree type, const frange &lhs,
3153 : const irange &, relation_trio) const
3154 : {
3155 246893 : if (lhs.undefined_p ())
3156 : return false;
3157 246893 : if (lhs.known_isnan ())
3158 : {
3159 0 : r.set_varying (type);
3160 0 : return true;
3161 : }
3162 246893 : REAL_VALUE_TYPE lb = lhs.lower_bound ();
3163 246893 : REAL_VALUE_TYPE ub = lhs.upper_bound ();
3164 246893 : enum machine_mode mode = TYPE_MODE (lhs.type ());
3165 246893 : frange_nextafter (mode, lb, dconstninf);
3166 246893 : frange_nextafter (mode, ub, dconstinf);
3167 246893 : if (flag_rounding_math)
3168 : {
3169 37 : real_floor (&lb, mode, &lb);
3170 37 : real_ceil (&ub, mode, &ub);
3171 : }
3172 : else
3173 : {
3174 246856 : real_trunc (&lb, mode, &lb);
3175 246856 : real_trunc (&ub, mode, &ub);
3176 : }
3177 246893 : REAL_VALUE_TYPE l, u;
3178 246893 : wide_int wlb, wub;
3179 246893 : l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
3180 246893 : if (real_less (&lb, &l))
3181 31056 : wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3182 : else
3183 : {
3184 215837 : bool fail = false;
3185 215837 : wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
3186 215837 : if (fail)
3187 0 : wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3188 : }
3189 246893 : u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
3190 246893 : if (real_less (&u, &ub))
3191 48158 : wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3192 : else
3193 : {
3194 198735 : bool fail = false;
3195 198735 : wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
3196 198735 : if (fail)
3197 0 : wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3198 : }
3199 246893 : r.set (type, wlb, wub);
3200 246893 : return true;
3201 246893 : }
3202 :
3203 : // Initialize any float operators to the primary table
3204 :
3205 : void
3206 293366 : range_op_table::initialize_float_ops ()
3207 : {
3208 293366 : set (UNLE_EXPR, fop_unordered_le);
3209 293366 : set (UNLT_EXPR, fop_unordered_lt);
3210 293366 : set (UNGE_EXPR, fop_unordered_ge);
3211 293366 : set (UNGT_EXPR, fop_unordered_gt);
3212 293366 : set (UNEQ_EXPR, fop_unordered_equal);
3213 293366 : set (ORDERED_EXPR, fop_ordered);
3214 293366 : set (UNORDERED_EXPR, fop_unordered);
3215 293366 : set (LTGT_EXPR, fop_ltgt);
3216 293366 : set (RDIV_EXPR, fop_div);
3217 293366 : }
3218 :
3219 : #if CHECKING_P
3220 : #include "selftest.h"
3221 :
3222 : namespace selftest
3223 : {
3224 :
3225 : // Build an frange from string endpoints.
3226 :
3227 : static inline frange
3228 84 : frange_float (const char *lb, const char *ub, tree type = float_type_node)
3229 : {
3230 84 : REAL_VALUE_TYPE min, max;
3231 84 : gcc_assert (real_from_string (&min, lb) == 0);
3232 84 : gcc_assert (real_from_string (&max, ub) == 0);
3233 84 : return frange (type, min, max);
3234 : }
3235 :
3236 : void
3237 4 : range_op_float_tests ()
3238 : {
3239 4 : frange r, r0, r1;
3240 4 : frange trange (float_type_node);
3241 :
3242 : // negate([-5, +10]) => [-10, 5]
3243 4 : r0 = frange_float ("-5", "10");
3244 4 : range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
3245 4 : ASSERT_EQ (r, frange_float ("-10", "5"));
3246 :
3247 : // negate([0, 1] -NAN) => [-1, -0] +NAN
3248 4 : r0 = frange_float ("0", "1");
3249 4 : r0.update_nan (true);
3250 4 : range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
3251 4 : r1 = frange_float ("-1", "-0");
3252 4 : r1.update_nan (false);
3253 4 : ASSERT_EQ (r, r1);
3254 :
3255 : // [-INF,+INF] + [-INF,+INF] could be a NAN.
3256 4 : range_op_handler plus (PLUS_EXPR);
3257 4 : r0.set_varying (float_type_node);
3258 4 : r1.set_varying (float_type_node);
3259 4 : r0.clear_nan ();
3260 4 : r1.clear_nan ();
3261 4 : plus.fold_range (r, float_type_node, r0, r1);
3262 4 : if (HONOR_NANS (float_type_node))
3263 8 : ASSERT_TRUE (r.maybe_isnan ());
3264 :
3265 : // r.widen widens each sub-range and keeps the gap between
3266 : // them.
3267 4 : r0 = frange_float ("1.0", "2.0");
3268 4 : r1 = frange_float ("10.0", "11.0");
3269 4 : r0.union_ (r1);
3270 4 : r0.clear_nan ();
3271 4 : ASSERT_EQ (r0.num_pairs (), 2);
3272 4 : r = r0;
3273 4 : r.widen (float_type_node);
3274 4 : ASSERT_EQ (r.num_pairs (), 2);
3275 4 : REAL_VALUE_TYPE five;
3276 4 : real_from_string (&five, "5.0");
3277 4 : ASSERT_FALSE (r.contains_p (five));
3278 :
3279 : // op1_range for "op1 == op2" where op2 = [-1.0,-0.0][1.0,1.0] holds -0.0 but
3280 : // not +0.0 must still admit +0.0 for op1, since -0.0 == +0.0.
3281 4 : if (HONOR_SIGNED_ZEROS (float_type_node))
3282 : {
3283 4 : r0 = frange_float ("-1.0", "-0.0");
3284 4 : r1 = frange_float ("1.0", "1.0");
3285 4 : r0.union_ (r1);
3286 4 : r0.clear_nan ();
3287 4 : ASSERT_FALSE (r0.contains_p (dconst0));
3288 4 : ASSERT_TRUE (r0.contains_p (dconstm0));
3289 4 : int_range<2> bool_true = range_true ();
3290 4 : range_op_handler (EQ_EXPR).op1_range (r, float_type_node, bool_true, r0);
3291 4 : ASSERT_TRUE (r.contains_p (dconst0));
3292 4 : }
3293 :
3294 : // negate([1, 2] U [10, 11]) => [-11, -10] U [-2, -1], keeping the gap.
3295 4 : r0 = frange_float ("1.0", "2.0");
3296 4 : r1 = frange_float ("10.0", "11.0");
3297 4 : r0.union_ (r1);
3298 4 : r0.clear_nan ();
3299 4 : range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
3300 4 : ASSERT_EQ (r.num_pairs (), 2);
3301 :
3302 : // abs([-6, -5] U [1, 2]) => [1, 2] U [5, 6], keeping the gap rather than
3303 : // collapsing to [0, 6].
3304 4 : r0 = frange_float ("-6.0", "-5.0");
3305 4 : r1 = frange_float ("1.0", "2.0");
3306 4 : r0.union_ (r1);
3307 4 : r0.clear_nan ();
3308 4 : range_op_handler (ABS_EXPR).fold_range (r, float_type_node, r0, trange);
3309 4 : ASSERT_EQ (r.num_pairs (), 2);
3310 :
3311 : // (float)([1, 4] U [6, 10]) keeps the gap.
3312 4 : unsigned iprec = TYPE_PRECISION (integer_type_node);
3313 4 : int_range<2> i0 (integer_type_node,
3314 4 : wi::shwi (1, iprec), wi::shwi (4, iprec));
3315 4 : int_range<2> i1 (integer_type_node,
3316 4 : wi::shwi (6, iprec), wi::shwi (10, iprec));
3317 4 : i0.union_ (i1);
3318 4 : range_op_handler (FLOAT_EXPR).fold_range (r, float_type_node, i0, trange);
3319 4 : ASSERT_EQ (r.num_pairs (), 2);
3320 :
3321 : // Casting the double range [1,2] U [10,11] to float stays two pieces rather
3322 : // than collapsing to the hull [1, 11].
3323 4 : r0 = frange_float ("1.0", "2.0", double_type_node);
3324 4 : r1 = frange_float ("10.0", "11.0", double_type_node);
3325 4 : r0.union_ (r1);
3326 4 : r0.clear_nan ();
3327 4 : range_op_handler (CONVERT_EXPR).fold_range (r, float_type_node, r0, r0);
3328 4 : ASSERT_EQ (r.num_pairs (), 2);
3329 :
3330 : // Cast conversion of (int)([1.0,2.0] U [10.0,11.0]) stays two pieces.
3331 4 : r0 = frange_float ("1.0", "2.0");
3332 4 : r1 = frange_float ("10.0", "11.0");
3333 4 : r0.union_ (r1);
3334 4 : r0.clear_nan ();
3335 4 : int_range<2> ir, ir_op2;
3336 4 : range_op_handler (FIX_TRUNC_EXPR).fold_range (ir, integer_type_node,
3337 : r0, ir_op2);
3338 4 : ASSERT_EQ (ir.num_pairs (), 2);
3339 :
3340 : // ([1, 2] U [10, 11]) + 0 stays two pieces.
3341 4 : r0 = frange_float ("1.0", "2.0");
3342 4 : r1 = frange_float ("10.0", "11.0");
3343 4 : r0.union_ (r1);
3344 4 : r0.clear_nan ();
3345 4 : r1 = frange_float ("0.0", "0.0");
3346 4 : r1.clear_nan ();
3347 4 : range_op_handler (PLUS_EXPR).fold_range (r, float_type_node, r0, r1);
3348 4 : ASSERT_EQ (r.num_pairs (), 2);
3349 :
3350 : // x * x (VREL_EQ) with a two-piece x: the diagonal fold gives the exact
3351 : // [4, 9], not the full cross product's [-9, -4] U [4, 9], nor the hull's
3352 : // looser [0, 9].
3353 4 : r0 = frange_float ("-3.0", "-2.0");
3354 4 : r1 = frange_float ("2.0", "3.0");
3355 4 : r0.union_ (r1);
3356 4 : r0.clear_nan ();
3357 4 : range_op_handler (MULT_EXPR).fold_range (r, float_type_node, r0, r0,
3358 : relation_trio (VREL_VARYING,
3359 : VREL_VARYING,
3360 4 : VREL_EQ));
3361 4 : REAL_VALUE_TYPE val;
3362 4 : real_from_string (&val, "5.0");
3363 4 : ASSERT_TRUE (r.contains_p (val)); // the result is [4, 9]
3364 4 : real_from_string (&val, "-5.0");
3365 4 : ASSERT_FALSE (r.contains_p (val)); // not the cross product's negatives
3366 4 : real_from_string (&val, "3.0");
3367 4 : ASSERT_FALSE (r.contains_p (val)); // tighter than the hull [0, 9]
3368 4 : }
3369 :
3370 : } // namespace selftest
3371 :
3372 : #endif // CHECKING_P
|