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 5561630 : range_operator::fold_range (frange &r, tree type,
54 : const frange &op1, const frange &op2,
55 : relation_trio trio) const
56 : {
57 5561630 : if (empty_range_varying (r, type, op1, op2))
58 6724 : return true;
59 5554906 : if (op1.known_isnan () || op2.known_isnan ())
60 : {
61 7729 : r.set_nan (type);
62 7729 : return true;
63 : }
64 :
65 5547177 : relation_kind rel = trio.op1_op2 ();
66 5547177 : r.set_undefined ();
67 5547177 : frange tmp;
68 11054110 : 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 81182 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
91 : {
92 40938 : rv_fold (tmp, type,
93 : op1.lower_bound (i), op1.upper_bound (i),
94 : op1.lower_bound (i), op1.upper_bound (i), rel);
95 40938 : r.union_ (tmp);
96 : }
97 : }
98 : else
99 : // Otherwise do the straight cross product.
100 11126254 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
101 11346374 : for (unsigned j = 0; j < op2.num_pairs (); ++j)
102 : {
103 5727053 : rv_fold (tmp, type,
104 : op1.lower_bound (i), op1.upper_bound (i),
105 : op2.lower_bound (j), op2.upper_bound (j), rel);
106 5727053 : r.union_ (tmp);
107 : }
108 :
109 5547177 : if (r.known_isnan ())
110 : return true;
111 9148368 : if (op1.maybe_isnan () || op2.maybe_isnan ())
112 3926897 : 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 5546062 : if (flag_trapping_math
119 26067883 : && MODE_HAS_INFINITIES (TYPE_MODE (type))
120 10676929 : && r.known_isinf () && !op1.known_isinf () && !op2.known_isinf ())
121 : {
122 1647 : REAL_VALUE_TYPE inf = r.lower_bound ();
123 1647 : 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 1551 : REAL_VALUE_TYPE max = real_max_representable (type);
131 1551 : r.set (type, max, inf);
132 : }
133 : }
134 :
135 5546062 : r.flush_denormals_to_zero ();
136 :
137 5546062 : 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 513697 : 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 513697 : r.set (type, dconstninf, dconstinf, nan_state (true));
151 513697 : }
152 :
153 : bool
154 101684 : 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 101684 : 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 648 : 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 648 : return false;
191 : }
192 :
193 : bool
194 5573 : 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 5573 : return false;
201 : }
202 :
203 : bool
204 2371 : 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 2371 : 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 5557666 : 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 5557666 : return VREL_VARYING;
230 : }
231 :
232 : relation_kind
233 1083731 : 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 1083731 : return VREL_VARYING;
239 : }
240 :
241 : relation_kind
242 196518 : 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 196518 : return VREL_VARYING;
248 : }
249 :
250 : relation_kind
251 3344891 : 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 3344891 : return VREL_VARYING;
257 : }
258 :
259 : relation_kind
260 367818 : range_operator::op1_op2_relation (const irange &,
261 : const frange &,
262 : const frange &) const
263 : {
264 367818 : return VREL_VARYING;
265 : }
266 :
267 :
268 : relation_kind
269 657758 : range_operator::op1_op2_relation (const frange &,
270 : const frange &,
271 : const frange &) const
272 : {
273 657758 : return VREL_VARYING;
274 : }
275 :
276 : // Return TRUE if OP1 and OP2 may be a NAN.
277 :
278 : static inline bool
279 3659879 : maybe_isnan (const frange &op1, const frange &op2)
280 : {
281 6382057 : 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 2128403 : frelop_early_resolve (irange &r, tree type,
300 : const frange &op1, const frange &op2,
301 : relation_trio trio, relation_kind my_rel)
302 : {
303 2128403 : 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 2128403 : if (!maybe_isnan (op1, op2) && relation_union (rel, my_rel) == my_rel)
316 : {
317 2003 : r = range_true (type);
318 2003 : return true;
319 : }
320 :
321 : // If known relation has no subset of this relation, always false.
322 2126400 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
323 : {
324 1043 : r = range_false (type);
325 1043 : return true;
326 : }
327 :
328 : // If either operand is undefined, return VARYING.
329 2125357 : if (empty_range_varying (r, type, op1, op2))
330 3954 : 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 13317195 : frange_nextafter (enum machine_mode mode,
339 : REAL_VALUE_TYPE &value,
340 : const REAL_VALUE_TYPE &inf)
341 : {
342 93220365 : 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 13317195 : REAL_VALUE_TYPE tmp;
354 13317195 : real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
355 13317195 : value = tmp;
356 : }
357 13317195 : }
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 16304753 : 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 16304753 : REAL_VALUE_TYPE value;
378 16304753 : enum machine_mode mode = TYPE_MODE (type);
379 114133271 : bool mode_composite = MODE_COMPOSITE_P (mode);
380 :
381 16304753 : bool inexact = real_arithmetic (&value, code, &op1, &op2);
382 16304753 : 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 16304753 : if (flag_rounding_math
389 16796 : && (code == PLUS_EXPR || code == MINUS_EXPR)
390 4824 : && !inexact
391 4824 : && real_iszero (&result)
392 66 : && !real_isneg (&result)
393 16304819 : && real_isneg (&inf))
394 : {
395 36 : REAL_VALUE_TYPE op2a = op2;
396 36 : if (code == PLUS_EXPR)
397 30 : op2a.sign ^= 1;
398 36 : 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 16304753 : bool round = false;
405 16304753 : if (mode_composite)
406 : round = true;
407 : else
408 : {
409 16304753 : bool low = real_isneg (&inf);
410 16304753 : round = (low ? !real_less (&result, &value)
411 8152440 : : !real_less (&value, &result));
412 16304753 : if (real_isinf (&result, !low)
413 1772958 : && !real_isinf (&value)
414 16724712 : && !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 418058 : if (!inexact)
424 : round = false;
425 : else
426 : {
427 57402 : REAL_VALUE_TYPE tmp = result, tmp2;
428 57402 : frange_nextafter (mode, tmp, inf);
429 : // TMP is at this point the maximum representable
430 : // number.
431 57402 : real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp);
432 57402 : if (real_isneg (&tmp2) != low
433 57402 : && (REAL_EXP (&tmp2) - REAL_EXP (&tmp)
434 57402 : >= 2 - REAL_MODE_FORMAT (mode)->p))
435 57401 : round = false;
436 : }
437 : }
438 : }
439 15944097 : if (round && (inexact || !real_identical (&result, &value)))
440 : {
441 1499498 : if (mode_composite
442 1499498 : && (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 1499498 : frange_nextafter (mode, result, inf);
452 : }
453 16304753 : 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 16304753 : }
476 :
477 : // Crop R to [-INF, MAX] where MAX is the maximum representable number
478 : // for TYPE.
479 :
480 : static inline void
481 180973 : frange_drop_inf (frange &r, tree type)
482 : {
483 180973 : REAL_VALUE_TYPE max = real_max_representable (type);
484 180973 : frange tmp (type, r.lower_bound (), max);
485 180973 : r.intersect (tmp);
486 180973 : }
487 :
488 : // Crop R to [MIN, +INF] where MIN is the minimum representable number
489 : // for TYPE.
490 :
491 : static inline void
492 91740 : frange_drop_ninf (frange &r, tree type)
493 : {
494 91740 : REAL_VALUE_TYPE min = real_min_representable (type);
495 91740 : frange tmp (type, min, r.upper_bound ());
496 91740 : r.intersect (tmp);
497 91740 : }
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 519467 : frange_drop_infs (frange &r, tree type)
504 : {
505 519467 : REAL_VALUE_TYPE max = real_max_representable (type);
506 519467 : REAL_VALUE_TYPE min = real_min_representable (type);
507 519467 : frange tmp (type, min, max);
508 519467 : r.intersect (tmp);
509 519467 : }
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 926805 : frange_add_zeros (frange &r, tree type)
515 : {
516 926805 : if (r.undefined_p () || r.known_isnan ())
517 : return;
518 :
519 926805 : if (HONOR_SIGNED_ZEROS (type) && r.contains_zero_p ())
520 : {
521 642113 : frange zero;
522 642113 : zero.set_zero (type);
523 642113 : r.union_ (zero);
524 642113 : }
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 252106 : build_le (frange &r, tree type, const frange &val)
533 : {
534 252106 : gcc_checking_assert (!val.known_isnan ());
535 :
536 252106 : REAL_VALUE_TYPE ninf = frange_val_min (type);
537 252106 : r.set (type, ninf, val.upper_bound ());
538 :
539 : // Add both zeros if there's the possibility of zero equality.
540 252106 : frange_add_zeros (r, type);
541 :
542 252106 : 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 309082 : build_lt (frange &r, tree type, const frange &val)
551 : {
552 309082 : gcc_checking_assert (!val.known_isnan ());
553 :
554 : // < -INF is outside the range.
555 309082 : if (real_isinf (&val.upper_bound (), 1))
556 : {
557 1350 : if (HONOR_NANS (type))
558 1350 : r.set_nan (type);
559 : else
560 0 : r.set_undefined ();
561 : return false;
562 : }
563 :
564 307732 : REAL_VALUE_TYPE ninf = frange_val_min (type);
565 307732 : REAL_VALUE_TYPE prev = val.upper_bound ();
566 307732 : 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 2154124 : if (!MODE_COMPOSITE_P (mode))
572 307732 : frange_nextafter (mode, prev, ninf);
573 307732 : r.set (type, ninf, prev);
574 307732 : 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 386196 : build_ge (frange &r, tree type, const frange &val)
583 : {
584 386196 : gcc_checking_assert (!val.known_isnan ());
585 :
586 386196 : REAL_VALUE_TYPE inf = frange_val_max (type);
587 386196 : r.set (type, val.lower_bound (), inf);
588 :
589 : // Add both zeros if there's the possibility of zero equality.
590 386196 : frange_add_zeros (r, type);
591 :
592 386196 : 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 199731 : build_gt (frange &r, tree type, const frange &val)
601 : {
602 199731 : gcc_checking_assert (!val.known_isnan ());
603 :
604 : // > +INF is outside the range.
605 199731 : if (real_isinf (&val.lower_bound (), 0))
606 : {
607 2982 : if (HONOR_NANS (type))
608 2982 : r.set_nan (type);
609 : else
610 0 : r.set_undefined ();
611 : return false;
612 : }
613 :
614 196749 : REAL_VALUE_TYPE inf = frange_val_max (type);
615 196749 : REAL_VALUE_TYPE next = val.lower_bound ();
616 196749 : 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 1377243 : if (!MODE_COMPOSITE_P (mode))
622 196749 : frange_nextafter (mode, next, inf);
623 196749 : r.set (type, next, inf);
624 196749 : return true;
625 : }
626 :
627 :
628 : bool
629 58804 : operator_identity::fold_range (frange &r, tree, const frange &op1,
630 : const frange &, relation_trio) const
631 : {
632 58804 : r = op1;
633 58804 : return true;
634 : }
635 :
636 : bool
637 18168 : operator_identity::op1_range (frange &r, tree, const frange &lhs,
638 : const frange &, relation_trio) const
639 : {
640 18168 : r = lhs;
641 18168 : return true;
642 : }
643 :
644 : bool
645 1561 : operator_cst::fold_range (frange &r, tree, const frange &op1,
646 : const frange &, relation_trio) const
647 : {
648 1561 : r = op1;
649 1561 : return true;
650 : }
651 :
652 : bool
653 27902 : operator_equal::op2_range (frange &r, tree type,
654 : const irange &lhs, const frange &op1,
655 : relation_trio rel) const
656 : {
657 27902 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
658 : }
659 :
660 : bool
661 195611 : operator_equal::fold_range (irange &r, tree type,
662 : const frange &op1, const frange &op2,
663 : relation_trio rel) const
664 : {
665 195611 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
666 : return true;
667 :
668 192391 : if (op1.known_isnan () || op2.known_isnan ())
669 526 : 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 191865 : else if (op1.singleton_p () && op2.singleton_p ())
673 : {
674 1394 : 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 1139 : else if (real_iszero (&op1.lower_bound ())
678 1139 : && real_iszero (&op2.lower_bound ()))
679 29 : r = range_true (type);
680 : else
681 1110 : r = range_false (type);
682 : }
683 190471 : else if (real_iszero (&op1.lower_bound ())
684 5926 : && real_iszero (&op1.upper_bound ())
685 716 : && real_iszero (&op2.lower_bound ())
686 474 : && real_iszero (&op2.upper_bound ())
687 190945 : && !maybe_isnan (op1, op2))
688 : // [-0.0, 0.0] == [-0.0, 0.0] or similar.
689 327 : 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 190144 : frange tmp = op1;
695 190144 : tmp.intersect (op2);
696 190144 : 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 1714 : if (op1.contains_zero_p () && op2.contains_zero_p ())
701 15 : r = range_true_and_false (type);
702 : else
703 1699 : r = range_false (type);
704 : }
705 : else
706 188430 : r = range_true_and_false (type);
707 190144 : }
708 : return true;
709 : }
710 :
711 : bool
712 145705 : operator_equal::op1_range (frange &r, tree type,
713 : const irange &lhs,
714 : const frange &op2,
715 : relation_trio trio) const
716 : {
717 145705 : relation_kind rel = trio.op1_op2 ();
718 145705 : switch (get_bool_state (r, lhs, type))
719 : {
720 44956 : case BRS_TRUE:
721 : // The TRUE side of x == NAN is unreachable.
722 44956 : 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 44956 : r = op2;
728 : // Add both zeros if there's the possibility of zero equality.
729 44956 : frange_add_zeros (r, type);
730 : // The TRUE side of op1 == op2 implies op1 is !NAN.
731 44956 : r.clear_nan ();
732 : }
733 : break;
734 :
735 98035 : case BRS_FALSE:
736 : // The FALSE side of op1 == op1 implies op1 is a NAN.
737 98035 : if (rel == VREL_EQ)
738 2891 : r.set_nan (type);
739 : // On the FALSE side of x == NAN, we know nothing about x.
740 95144 : 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 95142 : else if (op2.singleton_p ()
745 103241 : || (!op2.maybe_isnan () && op2.zero_p ()))
746 : {
747 60396 : REAL_VALUE_TYPE tmp = op2.lower_bound ();
748 60396 : r.set (type, tmp, tmp, VR_ANTI_RANGE);
749 : }
750 : else
751 34746 : r.set_varying (type);
752 : break;
753 :
754 : default:
755 : break;
756 : }
757 145705 : return true;
758 : }
759 :
760 : // Check if the LHS range indicates a relation between OP1 and OP2.
761 :
762 : relation_kind
763 148313 : operator_equal::op1_op2_relation (const irange &lhs, const frange &,
764 : const frange &) const
765 : {
766 148313 : if (lhs.undefined_p ())
767 : return VREL_UNDEFINED;
768 :
769 : // FALSE = op1 == op2 indicates NE_EXPR.
770 148313 : if (lhs.zero_p ())
771 : return VREL_NE;
772 :
773 : // TRUE = op1 == op2 indicates EQ_EXPR.
774 79060 : if (!lhs.contains_zero_p ())
775 75764 : return VREL_EQ;
776 : return VREL_VARYING;
777 : }
778 :
779 : bool
780 865101 : operator_not_equal::fold_range (irange &r, tree type,
781 : const frange &op1, const frange &op2,
782 : relation_trio trio) const
783 : {
784 865101 : relation_kind rel = trio.op1_op2 ();
785 :
786 : // VREL_NE & NE_EXPR is always true, even with NANs.
787 865101 : if (rel == VREL_NE)
788 : {
789 26 : r = range_true (type);
790 26 : return true;
791 : }
792 865075 : 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 26156 : if (empty_range_varying (r, type, op1, op2))
799 5 : return true;
800 : }
801 838919 : else if (frelop_early_resolve (r, type, op1, op2, trio, VREL_NE))
802 : return true;
803 :
804 : // x != NAN is always TRUE.
805 863608 : if (op1.known_isnan () || op2.known_isnan ())
806 1305 : 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 862303 : else if (op1.singleton_p () && op2.singleton_p ())
810 : {
811 1557 : if (op1 == op2)
812 1042 : r = range_false (type);
813 : // If one operand is -0.0 and other 0.0, they are still equal.
814 515 : else if (real_iszero (&op1.lower_bound ())
815 515 : && real_iszero (&op2.lower_bound ()))
816 1 : r = range_false (type);
817 : else
818 514 : r = range_true (type);
819 : }
820 860746 : else if (real_iszero (&op1.lower_bound ())
821 6947 : && real_iszero (&op1.upper_bound ())
822 389 : && real_iszero (&op2.lower_bound ())
823 200 : && real_iszero (&op2.upper_bound ())
824 860946 : && !maybe_isnan (op1, op2))
825 : // [-0.0, 0.0] != [-0.0, 0.0] or similar.
826 106 : 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 860640 : frange tmp = op1;
832 860640 : tmp.intersect (op2);
833 860640 : 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 857 : if (op1.contains_zero_p () && op2.contains_zero_p ())
838 4 : r = range_true_and_false (type);
839 : else
840 853 : r = range_true (type);
841 : }
842 : else
843 859783 : r = range_true_and_false (type);
844 860640 : }
845 : return true;
846 : }
847 :
848 : bool
849 292453 : operator_not_equal::op1_range (frange &r, tree type,
850 : const irange &lhs,
851 : const frange &op2,
852 : relation_trio trio) const
853 : {
854 292453 : relation_kind rel = trio.op1_op2 ();
855 292453 : switch (get_bool_state (r, lhs, type))
856 : {
857 45755 : case BRS_TRUE:
858 : // If the result is true, the only time we know anything is if
859 : // OP2 is a constant.
860 45755 : 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 23144 : REAL_VALUE_TYPE tmp = op2.lower_bound ();
866 23144 : r.set (type, tmp, tmp, VR_ANTI_RANGE);
867 : }
868 : // The TRUE side of op1 != op1 implies op1 is NAN.
869 22611 : else if (rel == VREL_EQ)
870 6019 : r.set_nan (type);
871 : else
872 16592 : r.set_varying (type);
873 : break;
874 :
875 243698 : case BRS_FALSE:
876 : // The FALSE side of x != NAN is impossible.
877 243698 : if (op2.known_isnan ())
878 170 : r.set_undefined ();
879 : else
880 : {
881 : // If it's false, the result is the same as OP2.
882 243528 : r = op2;
883 : // Add both zeros if there's the possibility of zero equality.
884 243528 : frange_add_zeros (r, type);
885 : // The FALSE side of op1 != op2 implies op1 is !NAN.
886 243528 : r.clear_nan ();
887 : }
888 : break;
889 :
890 : default:
891 : break;
892 : }
893 292453 : return true;
894 : }
895 :
896 : bool
897 191577 : operator_not_equal::op2_range (frange &r, tree type,
898 : const irange &lhs,
899 : const frange &op1,
900 : relation_trio trio) const
901 : {
902 191577 : 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 661062 : operator_not_equal::op1_op2_relation (const irange &lhs, const frange &,
909 : const frange &) const
910 : {
911 661062 : if (lhs.undefined_p ())
912 : return VREL_UNDEFINED;
913 :
914 : // FALSE = op1 != op2 indicates EQ_EXPR.
915 661062 : if (lhs.zero_p ())
916 : return VREL_EQ;
917 :
918 : // TRUE = op1 != op2 indicates NE_EXPR.
919 118633 : if (!lhs.contains_zero_p ())
920 115192 : return VREL_NE;
921 : return VREL_VARYING;
922 : }
923 :
924 : bool
925 272125 : operator_lt::fold_range (irange &r, tree type,
926 : const frange &op1, const frange &op2,
927 : relation_trio trio) const
928 : {
929 272125 : if (frelop_early_resolve (r, type, op1, op2, trio, VREL_LT))
930 : return true;
931 :
932 271511 : if (op1.known_isnan ()
933 271038 : || op2.known_isnan ()
934 542299 : || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
935 3142 : r = range_false (type);
936 268369 : else if (!maybe_isnan (op1, op2)
937 268369 : && real_less (&op1.upper_bound (), &op2.lower_bound ()))
938 1307 : r = range_true (type);
939 : else
940 267062 : r = range_true_and_false (type);
941 : return true;
942 : }
943 :
944 : bool
945 440557 : operator_lt::op1_range (frange &r,
946 : tree type,
947 : const irange &lhs,
948 : const frange &op2,
949 : relation_trio) const
950 : {
951 440557 : switch (get_bool_state (r, lhs, type))
952 : {
953 152454 : case BRS_TRUE:
954 : // The TRUE side of x < NAN is unreachable.
955 152454 : if (op2.known_isnan ())
956 68 : r.set_undefined ();
957 152386 : else if (op2.undefined_p ())
958 : return false;
959 152386 : else if (build_lt (r, type, op2))
960 : {
961 152386 : r.clear_nan ();
962 : // x < y implies x is not +INF.
963 152386 : frange_drop_inf (r, type);
964 : }
965 : break;
966 :
967 287680 : case BRS_FALSE:
968 : // On the FALSE side of x < NAN, we know nothing about x.
969 546228 : if (op2.maybe_isnan ())
970 29132 : r.set_varying (type);
971 : else
972 258548 : build_ge (r, type, op2);
973 : break;
974 :
975 : default:
976 : break;
977 : }
978 : return true;
979 : }
980 :
981 : bool
982 64407 : operator_lt::op2_range (frange &r,
983 : tree type,
984 : const irange &lhs,
985 : const frange &op1,
986 : relation_trio) const
987 : {
988 64407 : switch (get_bool_state (r, lhs, type))
989 : {
990 26034 : case BRS_TRUE:
991 : // The TRUE side of NAN < x is unreachable.
992 26034 : if (op1.known_isnan ())
993 22 : r.set_undefined ();
994 26012 : else if (op1.undefined_p ())
995 : return false;
996 26012 : else if (build_gt (r, type, op1))
997 : {
998 26012 : r.clear_nan ();
999 : // x < y implies y is not -INF.
1000 26012 : frange_drop_ninf (r, type);
1001 : }
1002 : break;
1003 :
1004 38163 : case BRS_FALSE:
1005 : // On the FALSE side of NAN < x, we know nothing about x.
1006 41753 : if (op1.maybe_isnan ())
1007 34573 : r.set_varying (type);
1008 : else
1009 3590 : 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 249842 : operator_lt::op1_op2_relation (const irange &lhs, const frange &,
1023 : const frange &) const
1024 : {
1025 249842 : if (lhs.undefined_p ())
1026 : return VREL_UNDEFINED;
1027 :
1028 : // FALSE = op1 < op2 indicates GE_EXPR.
1029 249842 : if (lhs.zero_p ())
1030 : return VREL_GE;
1031 :
1032 : // TRUE = op1 < op2 indicates LT_EXPR.
1033 115623 : if (!lhs.contains_zero_p ())
1034 115233 : return VREL_LT;
1035 : return VREL_VARYING;
1036 : }
1037 :
1038 : bool
1039 272959 : operator_le::fold_range (irange &r, tree type,
1040 : const frange &op1, const frange &op2,
1041 : relation_trio rel) const
1042 : {
1043 272959 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
1044 : return true;
1045 :
1046 272415 : if (op1.known_isnan ()
1047 271417 : || op2.known_isnan ()
1048 543798 : || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1049 2911 : r = range_false (type);
1050 269504 : else if (!maybe_isnan (op1, op2)
1051 269504 : && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1052 866 : r = range_true (type);
1053 : else
1054 268638 : r = range_true_and_false (type);
1055 : return true;
1056 : }
1057 :
1058 : bool
1059 97051 : operator_le::op1_range (frange &r,
1060 : tree type,
1061 : const irange &lhs,
1062 : const frange &op2,
1063 : relation_trio) const
1064 : {
1065 97051 : switch (get_bool_state (r, lhs, type))
1066 : {
1067 67493 : case BRS_TRUE:
1068 : // The TRUE side of x <= NAN is unreachable.
1069 67493 : if (op2.known_isnan ())
1070 0 : r.set_undefined ();
1071 67493 : else if (op2.undefined_p ())
1072 : return false;
1073 67493 : else if (build_le (r, type, op2))
1074 67493 : r.clear_nan ();
1075 : break;
1076 :
1077 29357 : case BRS_FALSE:
1078 : // On the FALSE side of x <= NAN, we know nothing about x.
1079 54251 : if (op2.maybe_isnan ())
1080 4463 : r.set_varying (type);
1081 : else
1082 24894 : build_gt (r, type, op2);
1083 : break;
1084 :
1085 : default:
1086 : break;
1087 : }
1088 : return true;
1089 : }
1090 :
1091 : bool
1092 14607 : operator_le::op2_range (frange &r,
1093 : tree type,
1094 : const irange &lhs,
1095 : const frange &op1,
1096 : relation_trio) const
1097 : {
1098 14607 : switch (get_bool_state (r, lhs, type))
1099 : {
1100 3922 : case BRS_TRUE:
1101 : // The TRUE side of NAN <= x is unreachable.
1102 3922 : if (op1.known_isnan ())
1103 0 : r.set_undefined ();
1104 3922 : else if (op1.undefined_p ())
1105 : return false;
1106 3922 : else if (build_ge (r, type, op1))
1107 3922 : r.clear_nan ();
1108 : break;
1109 :
1110 10547 : case BRS_FALSE:
1111 : // On the FALSE side of NAN <= x, we know nothing about x.
1112 11287 : if (op1.maybe_isnan ())
1113 9807 : r.set_varying (type);
1114 740 : else if (op1.undefined_p ())
1115 : return false;
1116 : else
1117 740 : 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 64582 : operator_le::op1_op2_relation (const irange &lhs, const frange &,
1130 : const frange &) const
1131 : {
1132 64582 : if (lhs.undefined_p ())
1133 : return VREL_UNDEFINED;
1134 :
1135 : // FALSE = op1 <= op2 indicates GT_EXPR.
1136 64582 : if (lhs.zero_p ())
1137 : return VREL_GT;
1138 :
1139 : // TRUE = op1 <= op2 indicates LE_EXPR.
1140 32654 : if (!lhs.contains_zero_p ())
1141 32374 : return VREL_LE;
1142 : return VREL_VARYING;
1143 : }
1144 :
1145 : bool
1146 282408 : operator_gt::fold_range (irange &r, tree type,
1147 : const frange &op1, const frange &op2,
1148 : relation_trio trio) const
1149 : {
1150 282408 : if (frelop_early_resolve (r, type, op1, op2, trio, VREL_GT))
1151 : return true;
1152 :
1153 281603 : if (op1.known_isnan ()
1154 281062 : || op2.known_isnan ()
1155 562347 : || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1156 4595 : r = range_false (type);
1157 277008 : else if (!maybe_isnan (op1, op2)
1158 277008 : && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1159 1079 : r = range_true (type);
1160 : else
1161 275929 : r = range_true_and_false (type);
1162 : return true;
1163 : }
1164 :
1165 : bool
1166 170402 : operator_gt::op1_range (frange &r,
1167 : tree type,
1168 : const irange &lhs,
1169 : const frange &op2,
1170 : relation_trio) const
1171 : {
1172 170402 : switch (get_bool_state (r, lhs, type))
1173 : {
1174 65756 : case BRS_TRUE:
1175 : // The TRUE side of x > NAN is unreachable.
1176 65756 : if (op2.known_isnan ())
1177 28 : r.set_undefined ();
1178 65728 : else if (op2.undefined_p ())
1179 : return false;
1180 65728 : else if (build_gt (r, type, op2))
1181 : {
1182 65728 : r.clear_nan ();
1183 : // x > y implies x is not -INF.
1184 65728 : frange_drop_ninf (r, type);
1185 : }
1186 : break;
1187 :
1188 104072 : case BRS_FALSE:
1189 : // On the FALSE side of x > NAN, we know nothing about x.
1190 178607 : if (op2.maybe_isnan ())
1191 29537 : r.set_varying (type);
1192 74535 : else if (op2.undefined_p ())
1193 : return false;
1194 : else
1195 74535 : build_le (r, type, op2);
1196 : break;
1197 :
1198 : default:
1199 : break;
1200 : }
1201 : return true;
1202 : }
1203 :
1204 : bool
1205 73209 : operator_gt::op2_range (frange &r,
1206 : tree type,
1207 : const irange &lhs,
1208 : const frange &op1,
1209 : relation_trio) const
1210 : {
1211 73209 : switch (get_bool_state (r, lhs, type))
1212 : {
1213 28609 : case BRS_TRUE:
1214 : // The TRUE side of NAN > x is unreachable.
1215 28609 : if (op1.known_isnan ())
1216 22 : r.set_undefined ();
1217 28587 : else if (op1.undefined_p ())
1218 : return false;
1219 28587 : else if (build_lt (r, type, op1))
1220 : {
1221 28587 : r.clear_nan ();
1222 : // x > y implies y is not +INF.
1223 28587 : frange_drop_inf (r, type);
1224 : }
1225 : break;
1226 :
1227 44368 : case BRS_FALSE:
1228 : // On The FALSE side of NAN > x, we know nothing about x.
1229 47607 : if (op1.maybe_isnan ())
1230 41129 : r.set_varying (type);
1231 3239 : else if (op1.undefined_p ())
1232 : return false;
1233 : else
1234 3239 : 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 272369 : operator_gt::op1_op2_relation (const irange &lhs, const frange &,
1247 : const frange &) const
1248 : {
1249 272369 : if (lhs.undefined_p ())
1250 : return VREL_UNDEFINED;
1251 :
1252 : // FALSE = op1 > op2 indicates LE_EXPR.
1253 272369 : if (lhs.zero_p ())
1254 : return VREL_LE;
1255 :
1256 : // TRUE = op1 > op2 indicates GT_EXPR.
1257 122279 : if (!lhs.contains_zero_p ())
1258 121779 : return VREL_GT;
1259 : return VREL_VARYING;
1260 : }
1261 :
1262 : bool
1263 266381 : operator_ge::fold_range (irange &r, tree type,
1264 : const frange &op1, const frange &op2,
1265 : relation_trio rel) const
1266 : {
1267 266381 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
1268 : return true;
1269 :
1270 266026 : if (op1.known_isnan ()
1271 265207 : || op2.known_isnan ()
1272 531195 : || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1273 1570 : r = range_false (type);
1274 264456 : else if (!maybe_isnan (op1, op2)
1275 264456 : && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1276 2510 : r = range_true (type);
1277 : else
1278 261946 : r = range_true_and_false (type);
1279 : return true;
1280 : }
1281 :
1282 : bool
1283 106096 : operator_ge::op1_range (frange &r,
1284 : tree type,
1285 : const irange &lhs,
1286 : const frange &op2,
1287 : relation_trio) const
1288 : {
1289 106096 : switch (get_bool_state (r, lhs, type))
1290 : {
1291 59281 : case BRS_TRUE:
1292 : // The TRUE side of x >= NAN is unreachable.
1293 59281 : if (op2.known_isnan ())
1294 0 : r.set_undefined ();
1295 59281 : else if (op2.undefined_p ())
1296 : return false;
1297 59281 : else if (build_ge (r, type, op2))
1298 59281 : r.clear_nan ();
1299 : break;
1300 :
1301 46653 : case BRS_FALSE:
1302 : // On the FALSE side of x >= NAN, we know nothing about x.
1303 87191 : if (op2.maybe_isnan ())
1304 6115 : r.set_varying (type);
1305 40538 : else if (op2.undefined_p ())
1306 : return false;
1307 : else
1308 40538 : build_lt (r, type, op2);
1309 : break;
1310 :
1311 : default:
1312 : break;
1313 : }
1314 : return true;
1315 : }
1316 :
1317 : bool
1318 12630 : operator_ge::op2_range (frange &r, tree type,
1319 : const irange &lhs,
1320 : const frange &op1,
1321 : relation_trio) const
1322 : {
1323 12630 : switch (get_bool_state (r, lhs, type))
1324 : {
1325 5250 : case BRS_TRUE:
1326 : // The TRUE side of NAN >= x is unreachable.
1327 5250 : if (op1.known_isnan ())
1328 0 : r.set_undefined ();
1329 5250 : else if (op1.undefined_p ())
1330 : return false;
1331 5250 : else if (build_le (r, type, op1))
1332 5250 : r.clear_nan ();
1333 : break;
1334 :
1335 7278 : case BRS_FALSE:
1336 : // On the FALSE side of NAN >= x, we know nothing about x.
1337 7982 : if (op1.maybe_isnan ())
1338 6574 : r.set_varying (type);
1339 704 : else if (op1.undefined_p ())
1340 : return false;
1341 : else
1342 704 : 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 59550 : operator_ge::op1_op2_relation (const irange &lhs, const frange &,
1355 : const frange &) const
1356 : {
1357 59550 : if (lhs.undefined_p ())
1358 : return VREL_UNDEFINED;
1359 :
1360 : // FALSE = op1 >= op2 indicates LT_EXPR.
1361 59550 : if (lhs.zero_p ())
1362 : return VREL_LT;
1363 :
1364 : // TRUE = op1 >= op2 indicates GE_EXPR.
1365 31800 : if (!lhs.contains_zero_p ())
1366 31569 : 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 58760 : 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 58760 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1389 : }
1390 : };
1391 : static const foperator_unordered fop_unordered;
1392 :
1393 : bool
1394 62961 : 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 62961 : if (op1.known_isnan () || op2.known_isnan ())
1400 223 : r = range_true (type);
1401 : // UNORDERED is FALSE if neither operand is a NAN.
1402 65908 : else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1403 1587 : r = range_false (type);
1404 : else
1405 61151 : r = range_true_and_false (type);
1406 62961 : return true;
1407 : }
1408 :
1409 : bool
1410 109696 : foperator_unordered::op1_range (frange &r, tree type,
1411 : const irange &lhs,
1412 : const frange &op2,
1413 : relation_trio trio) const
1414 : {
1415 109696 : relation_kind rel = trio.op1_op2 ();
1416 109696 : switch (get_bool_state (r, lhs, type))
1417 : {
1418 40256 : case BRS_TRUE:
1419 : // Since at least one operand must be NAN, if one of them is
1420 : // not, the other must be.
1421 40256 : if (rel == VREL_EQ || !op2.maybe_isnan ())
1422 10725 : r.set_nan (type);
1423 : else
1424 29531 : r.set_varying (type);
1425 : break;
1426 :
1427 59831 : case BRS_FALSE:
1428 : // A false UNORDERED means both operands are !NAN, so it's
1429 : // impossible for op2 to be a NAN.
1430 59831 : if (op2.known_isnan ())
1431 0 : r.set_undefined ();
1432 : else
1433 : {
1434 59831 : r.set_varying (type);
1435 59831 : r.clear_nan ();
1436 : }
1437 : break;
1438 :
1439 : default:
1440 : break;
1441 : }
1442 109696 : 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 33347 : 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 33347 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1464 : }
1465 : };
1466 : static const foperator_ordered fop_ordered;
1467 :
1468 : bool
1469 33835 : foperator_ordered::fold_range (irange &r, tree type,
1470 : const frange &op1, const frange &op2,
1471 : relation_trio) const
1472 : {
1473 33835 : if (op1.known_isnan () || op2.known_isnan ())
1474 360 : r = range_false (type);
1475 36829 : else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1476 1670 : r = range_true (type);
1477 : else
1478 31805 : r = range_true_and_false (type);
1479 33835 : return true;
1480 : }
1481 :
1482 : bool
1483 70668 : foperator_ordered::op1_range (frange &r, tree type,
1484 : const irange &lhs,
1485 : const frange &op2,
1486 : relation_trio trio) const
1487 : {
1488 70668 : relation_kind rel = trio.op1_op2 ();
1489 70668 : switch (get_bool_state (r, lhs, type))
1490 : {
1491 57831 : 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 57831 : if (op2.known_isnan ())
1495 10 : r.set_undefined ();
1496 : else
1497 : {
1498 57821 : r.set_varying (type);
1499 57821 : r.clear_nan ();
1500 : }
1501 : break;
1502 :
1503 5570 : case BRS_FALSE:
1504 : // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1505 5570 : if (rel == VREL_EQ)
1506 2081 : r.set_nan (type);
1507 : else
1508 3489 : r.set_varying (type);
1509 : break;
1510 :
1511 : default:
1512 : break;
1513 : }
1514 70668 : return true;
1515 : }
1516 :
1517 : bool
1518 245149 : operator_negate::fold_range (frange &r, tree type,
1519 : const frange &op1, const frange &op2,
1520 : relation_trio) const
1521 : {
1522 245149 : if (empty_range_varying (r, type, op1, op2))
1523 429 : return true;
1524 244720 : if (op1.known_isnan ())
1525 : {
1526 426 : bool sign;
1527 426 : if (op1.nan_signbit_p (sign))
1528 38 : r.set_nan (type, !sign);
1529 : else
1530 388 : r.set_nan (type);
1531 : return true;
1532 : }
1533 :
1534 244294 : r.set_undefined ();
1535 734684 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
1536 : {
1537 246096 : REAL_VALUE_TYPE lb = op1.lower_bound (i);
1538 246096 : REAL_VALUE_TYPE ub = op1.upper_bound (i);
1539 246096 : lb = real_value_negate (&lb);
1540 246096 : ub = real_value_negate (&ub);
1541 246096 : frange tmp (type, ub, lb);
1542 246096 : r.union_ (tmp);
1543 246096 : }
1544 435032 : if (op1.maybe_isnan ())
1545 : {
1546 53560 : bool sign;
1547 53560 : if (op1.nan_signbit_p (sign))
1548 2498 : r.update_nan (!sign);
1549 : else
1550 51062 : r.update_nan ();
1551 : }
1552 : else
1553 190734 : r.clear_nan ();
1554 : return true;
1555 : }
1556 :
1557 : bool
1558 3375 : operator_negate::op1_range (frange &r, tree type,
1559 : const frange &lhs, const frange &op2,
1560 : relation_trio rel) const
1561 : {
1562 3375 : return fold_range (r, type, lhs, op2, rel);
1563 : }
1564 :
1565 : bool
1566 596752 : operator_abs::fold_range (frange &r, tree type,
1567 : const frange &op1, const frange &op2,
1568 : relation_trio) const
1569 : {
1570 596752 : if (empty_range_varying (r, type, op1, op2))
1571 114 : return true;
1572 596638 : if (op1.known_isnan ())
1573 : {
1574 762 : r.set_nan (type, /*sign=*/false);
1575 762 : return true;
1576 : }
1577 :
1578 595876 : const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1579 : // Handle the easy case where everything is positive.
1580 595876 : if (real_compare (GE_EXPR, &lh_lb, &dconst0)
1581 161223 : && !real_iszero (&lh_lb, /*sign=*/true)
1582 754614 : && !op1.maybe_isnan (/*sign=*/true))
1583 : {
1584 158129 : r = op1;
1585 158129 : return true;
1586 : }
1587 :
1588 : // Take the absolute value of each sub-range and union the results.
1589 437747 : r.set_undefined ();
1590 1322050 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
1591 : {
1592 446556 : const REAL_VALUE_TYPE lb = op1.lower_bound (i);
1593 446556 : const REAL_VALUE_TYPE ub = op1.upper_bound (i);
1594 446556 : REAL_VALUE_TYPE min = real_value_abs (&lb);
1595 446556 : 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 446556 : if (real_compare (LE_EXPR, &lb, &dconst0)
1599 446556 : && real_compare (GE_EXPR, &ub, &dconst0))
1600 : {
1601 429229 : if (real_compare (GT_EXPR, &min, &max))
1602 6389 : max = min;
1603 429229 : min = dconst0;
1604 : }
1605 : else
1606 : {
1607 : // If the range was reversed, swap MIN and MAX.
1608 17327 : if (real_compare (GT_EXPR, &min, &max))
1609 8297 : std::swap (min, max);
1610 : }
1611 446556 : frange tmp (type, min, max);
1612 446556 : r.union_ (tmp);
1613 446556 : }
1614 463635 : if (op1.maybe_isnan ())
1615 413893 : r.update_nan (/*sign=*/false);
1616 : else
1617 23854 : r.clear_nan ();
1618 : return true;
1619 : }
1620 :
1621 : bool
1622 335695 : operator_abs::op1_range (frange &r, tree type,
1623 : const frange &lhs, const frange &op2,
1624 : relation_trio) const
1625 : {
1626 335695 : if (empty_range_varying (r, type, lhs, op2))
1627 0 : return true;
1628 335695 : if (lhs.known_isnan ())
1629 : {
1630 2617 : r.set_nan (type);
1631 2617 : return true;
1632 : }
1633 :
1634 : // Start with the positives because negatives are an impossible result.
1635 333078 : frange positives (type, dconst0, frange_val_max (type));
1636 333078 : positives.update_nan (/*sign=*/false);
1637 333078 : positives.intersect (lhs);
1638 333078 : r = positives;
1639 : // Add -NAN if relevant.
1640 502121 : if (r.maybe_isnan ())
1641 : {
1642 163975 : frange neg_nan;
1643 163975 : neg_nan.set_nan (type, true);
1644 163975 : r.union_ (neg_nan);
1645 163975 : }
1646 333078 : 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 333010 : frange negatives (type, real_value_negate (&positives.upper_bound ()),
1651 333010 : real_value_negate (&positives.lower_bound ()));
1652 333010 : negatives.clear_nan ();
1653 333010 : r.union_ (negatives);
1654 333010 : return true;
1655 333010 : }
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 12585 : 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 12585 : if (op1.known_isnan () || op2.known_isnan ())
1668 : {
1669 33 : r = range_true (type);
1670 33 : return true;
1671 : }
1672 12552 : frange op1_no_nan = op1;
1673 12552 : frange op2_no_nan = op2;
1674 15667 : if (op1.maybe_isnan ())
1675 9421 : op1_no_nan.clear_nan ();
1676 20675 : if (op2.maybe_isnan ())
1677 4429 : op2_no_nan.clear_nan ();
1678 12552 : 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 12552 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1684 : return true;
1685 : else
1686 : {
1687 9481 : r = range_true_and_false (type);
1688 9481 : 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 5444 : foperator_unordered_lt::op1_range (frange &r, tree type,
1704 : const irange &lhs,
1705 : const frange &op2,
1706 : relation_trio) const
1707 : {
1708 5444 : switch (get_bool_state (r, lhs, type))
1709 : {
1710 1992 : case BRS_TRUE:
1711 3756 : if (op2.maybe_isnan ())
1712 228 : r.set_varying (type);
1713 1764 : else if (op2.undefined_p ())
1714 : return false;
1715 : else
1716 1764 : build_lt (r, type, op2);
1717 : break;
1718 :
1719 1450 : 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 1450 : if (op2.known_isnan ())
1723 0 : r.set_undefined ();
1724 1450 : else if (op2.undefined_p ())
1725 : return false;
1726 1450 : else if (build_ge (r, type, op2))
1727 1450 : r.clear_nan ();
1728 : break;
1729 :
1730 : default:
1731 : break;
1732 : }
1733 : return true;
1734 : }
1735 :
1736 : bool
1737 3338 : foperator_unordered_lt::op2_range (frange &r, tree type,
1738 : const irange &lhs,
1739 : const frange &op1,
1740 : relation_trio) const
1741 : {
1742 3338 : switch (get_bool_state (r, lhs, type))
1743 : {
1744 1251 : case BRS_TRUE:
1745 1870 : if (op1.maybe_isnan ())
1746 632 : r.set_varying (type);
1747 619 : else if (op1.undefined_p ())
1748 : return false;
1749 : else
1750 619 : build_gt (r, type, op1);
1751 : break;
1752 :
1753 85 : 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 85 : if (op1.known_isnan ())
1757 0 : r.set_undefined ();
1758 85 : else if (op1.undefined_p ())
1759 : return false;
1760 85 : else if (build_le (r, type, op1))
1761 85 : 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 181293 : 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 181293 : if (op1.known_isnan () || op2.known_isnan ())
1781 : {
1782 98 : r = range_true (type);
1783 98 : return true;
1784 : }
1785 181195 : frange op1_no_nan = op1;
1786 181195 : frange op2_no_nan = op2;
1787 206513 : if (op1.maybe_isnan ())
1788 155851 : op1_no_nan.clear_nan ();
1789 355412 : if (op2.maybe_isnan ())
1790 6972 : op2_no_nan.clear_nan ();
1791 181195 : 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 181195 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1797 : return true;
1798 : else
1799 : {
1800 157225 : r = range_true_and_false (type);
1801 157225 : 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 167264 : foperator_unordered_le::op1_range (frange &r, tree type,
1815 : const irange &lhs, const frange &op2,
1816 : relation_trio) const
1817 : {
1818 167264 : switch (get_bool_state (r, lhs, type))
1819 : {
1820 91448 : case BRS_TRUE:
1821 179025 : if (op2.maybe_isnan ())
1822 3871 : r.set_varying (type);
1823 87577 : else if (op2.undefined_p ())
1824 : return false;
1825 : else
1826 87577 : build_le (r, type, op2);
1827 : break;
1828 :
1829 73874 : 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 73874 : if (op2.known_isnan ())
1833 0 : r.set_undefined ();
1834 73874 : else if (build_gt (r, type, op2))
1835 73872 : r.clear_nan ();
1836 : break;
1837 :
1838 : default:
1839 : break;
1840 : }
1841 : return true;
1842 : }
1843 :
1844 : bool
1845 10875 : foperator_unordered_le::op2_range (frange &r,
1846 : tree type,
1847 : const irange &lhs,
1848 : const frange &op1,
1849 : relation_trio) const
1850 : {
1851 10875 : switch (get_bool_state (r, lhs, type))
1852 : {
1853 6228 : case BRS_TRUE:
1854 9497 : if (op1.maybe_isnan ())
1855 2959 : r.set_varying (type);
1856 3269 : else if (op1.undefined_p ())
1857 : return false;
1858 : else
1859 3269 : build_ge (r, type, op1);
1860 : break;
1861 :
1862 2705 : 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 2705 : if (op1.known_isnan ())
1866 0 : r.set_undefined ();
1867 2705 : else if (op1.undefined_p ())
1868 : return false;
1869 2705 : else if (build_lt (r, type, op1))
1870 2705 : 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 52935 : 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 52935 : if (op1.known_isnan () || op2.known_isnan ())
1890 : {
1891 158 : r = range_true (type);
1892 158 : return true;
1893 : }
1894 52777 : frange op1_no_nan = op1;
1895 52777 : frange op2_no_nan = op2;
1896 56879 : if (op1.maybe_isnan ())
1897 48656 : op1_no_nan.clear_nan ();
1898 101065 : if (op2.maybe_isnan ())
1899 4489 : op2_no_nan.clear_nan ();
1900 52777 : 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 52777 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1906 : return true;
1907 : else
1908 : {
1909 48722 : r = range_true_and_false (type);
1910 48722 : 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 17153 : foperator_unordered_gt::op1_range (frange &r,
1924 : tree type,
1925 : const irange &lhs,
1926 : const frange &op2,
1927 : relation_trio) const
1928 : {
1929 17153 : switch (get_bool_state (r, lhs, type))
1930 : {
1931 4480 : case BRS_TRUE:
1932 8799 : if (op2.maybe_isnan ())
1933 161 : r.set_varying (type);
1934 4319 : else if (op2.undefined_p ())
1935 : return false;
1936 : else
1937 4319 : build_gt (r, type, op2);
1938 : break;
1939 :
1940 10671 : 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 10671 : if (op2.known_isnan ())
1944 0 : r.set_undefined ();
1945 10671 : else if (op2.undefined_p ())
1946 : return false;
1947 10671 : else if (build_le (r, type, op2))
1948 10671 : r.clear_nan ();
1949 : break;
1950 :
1951 : default:
1952 : break;
1953 : }
1954 : return true;
1955 : }
1956 :
1957 : bool
1958 3231 : foperator_unordered_gt::op2_range (frange &r,
1959 : tree type,
1960 : const irange &lhs,
1961 : const frange &op1,
1962 : relation_trio) const
1963 : {
1964 3231 : switch (get_bool_state (r, lhs, type))
1965 : {
1966 973 : case BRS_TRUE:
1967 1422 : if (op1.maybe_isnan ())
1968 524 : r.set_varying (type);
1969 449 : else if (op1.undefined_p ())
1970 : return false;
1971 : else
1972 449 : build_lt (r, type, op1);
1973 : break;
1974 :
1975 256 : 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 256 : if (op1.known_isnan ())
1979 0 : r.set_undefined ();
1980 256 : else if (op1.undefined_p ())
1981 : return false;
1982 256 : else if (build_ge (r, type, op1))
1983 256 : 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 171646 : 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 171646 : if (op1.known_isnan () || op2.known_isnan ())
2003 : {
2004 45 : r = range_true (type);
2005 45 : return true;
2006 : }
2007 171601 : frange op1_no_nan = op1;
2008 171601 : frange op2_no_nan = op2;
2009 184519 : if (op1.maybe_isnan ())
2010 158631 : op1_no_nan.clear_nan ();
2011 336115 : if (op2.maybe_isnan ())
2012 7081 : op2_no_nan.clear_nan ();
2013 171601 : 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 171601 : if (!maybe_isnan (op1, op2) || r == range_true (type))
2019 : return true;
2020 : else
2021 : {
2022 158386 : r = range_true_and_false (type);
2023 158386 : 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 143994 : foperator_unordered_ge::op1_range (frange &r,
2037 : tree type,
2038 : const irange &lhs,
2039 : const frange &op2,
2040 : relation_trio) const
2041 : {
2042 143994 : switch (get_bool_state (r, lhs, type))
2043 : {
2044 60027 : case BRS_TRUE:
2045 116258 : if (op2.maybe_isnan ())
2046 3796 : r.set_varying (type);
2047 56231 : else if (op2.undefined_p ())
2048 : return false;
2049 : else
2050 56231 : build_ge (r, type, op2);
2051 : break;
2052 :
2053 81913 : 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 81913 : if (op2.known_isnan ())
2057 0 : r.set_undefined ();
2058 81913 : else if (op2.undefined_p ())
2059 : return false;
2060 81913 : else if (build_lt (r, type, op2))
2061 81909 : r.clear_nan ();
2062 : break;
2063 :
2064 : default:
2065 : break;
2066 : }
2067 : return true;
2068 : }
2069 :
2070 : bool
2071 11524 : foperator_unordered_ge::op2_range (frange &r, tree type,
2072 : const irange &lhs,
2073 : const frange &op1,
2074 : relation_trio) const
2075 : {
2076 11524 : switch (get_bool_state (r, lhs, type))
2077 : {
2078 6009 : case BRS_TRUE:
2079 8914 : if (op1.maybe_isnan ())
2080 3104 : r.set_varying (type);
2081 2905 : else if (op1.undefined_p ())
2082 : return false;
2083 : else
2084 2905 : build_le (r, type, op1);
2085 : break;
2086 :
2087 3581 : 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 3581 : if (op1.known_isnan ())
2091 0 : r.set_undefined ();
2092 3581 : else if (op1.undefined_p ())
2093 : return false;
2094 3581 : else if (build_gt (r, type, op1))
2095 3581 : 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 4076 : 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 4076 : if (op1.known_isnan () || op2.known_isnan ())
2115 : {
2116 0 : r = range_true (type);
2117 0 : return true;
2118 : }
2119 4076 : frange op1_no_nan = op1;
2120 4076 : frange op2_no_nan = op2;
2121 4468 : if (op1.maybe_isnan ())
2122 3684 : op1_no_nan.clear_nan ();
2123 4569 : if (op2.maybe_isnan ())
2124 3583 : op2_no_nan.clear_nan ();
2125 4076 : 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 4076 : if (!maybe_isnan (op1, op2) || r == range_true (type))
2131 : return true;
2132 : else
2133 : {
2134 3683 : r = range_true_and_false (type);
2135 3683 : 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 2124 : 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 2124 : 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 4251 : foperator_unordered_equal::op1_range (frange &r, tree type,
2152 : const irange &lhs,
2153 : const frange &op2,
2154 : relation_trio) const
2155 : {
2156 4251 : 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 4251 : 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 2399 : 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 2399 : if (op1.known_isnan () || op2.known_isnan ())
2198 : {
2199 6 : r = range_false (type);
2200 6 : return true;
2201 : }
2202 2393 : frange op1_no_nan = op1;
2203 2393 : frange op2_no_nan = op2;
2204 2793 : if (op1.maybe_isnan ())
2205 1982 : op1_no_nan.clear_nan ();
2206 2793 : if (op2.maybe_isnan ())
2207 1982 : op2_no_nan.clear_nan ();
2208 2393 : 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 2393 : if (!maybe_isnan (op1, op2) || r == range_false (type))
2214 : return true;
2215 : else
2216 : {
2217 1970 : r = range_true_and_false (type);
2218 1970 : 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 2522 : 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 2522 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2229 : }
2230 : };
2231 : static const foperator_ltgt fop_ltgt;
2232 :
2233 : bool
2234 5040 : foperator_ltgt::op1_range (frange &r, tree type,
2235 : const irange &lhs,
2236 : const frange &op2,
2237 : relation_trio) const
2238 : {
2239 5040 : 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 5040 : 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 913207 : float_binary_op_range_finish (bool ret, frange &r, tree type,
2275 : const frange &lhs, bool div_op2 = false)
2276 : {
2277 913207 : 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 913207 : if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
2288 : {
2289 6582 : r.set_varying (type);
2290 6582 : 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 1610206 : if (!lhs.maybe_isnan ())
2296 : {
2297 703581 : r.clear_nan ();
2298 35821 : if (div_op2
2299 703581 : ? !lhs.contains_zero_p ()
2300 1206959 : : !(real_isinf (&lhs.lower_bound ())
2301 539199 : || 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 519467 : frange_drop_infs (r, type);
2308 : }
2309 : // If lhs is a maybe or known NAN, the operand could be
2310 : // NAN.
2311 : else
2312 203044 : r.update_nan ();
2313 : return true;
2314 : }
2315 :
2316 : // True if [lb, ub] is [+-0, +-0].
2317 : static bool
2318 5813490 : zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2319 : {
2320 5813490 : return real_iszero (&lb) && real_iszero (&ub);
2321 : }
2322 :
2323 : // True if +0 or -0 is in [lb, ub] range.
2324 : static bool
2325 4773561 : contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2326 : {
2327 4773561 : return (real_compare (LE_EXPR, &lb, &dconst0)
2328 4773561 : && real_compare (GE_EXPR, &ub, &dconst0));
2329 : }
2330 :
2331 : // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
2332 : static bool
2333 3341779 : singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2334 : {
2335 3341779 : 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 1479783 : 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 1479783 : if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
2348 1479783 : && real_isneg (&rh_lb) == real_isneg (&rh_ub))
2349 : {
2350 180828 : if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
2351 : return 1;
2352 : else
2353 37030 : 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 7244 : zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2362 : {
2363 7244 : ub = lb = dconst0;
2364 7244 : if (signbit_known <= 0)
2365 7006 : lb = dconstm0;
2366 7006 : if (signbit_known < 0)
2367 64 : ub = lb;
2368 7244 : }
2369 :
2370 : // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
2371 : // signbit_known.
2372 : static void
2373 4882 : inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2374 : {
2375 4882 : if (signbit_known > 0)
2376 1024 : ub = lb = dconstinf;
2377 3858 : else if (signbit_known < 0)
2378 156 : ub = lb = dconstninf;
2379 : else
2380 : {
2381 3702 : lb = dconstninf;
2382 3702 : ub = dconstinf;
2383 : }
2384 4882 : }
2385 :
2386 : // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
2387 : // signbit_known.
2388 : static void
2389 1043935 : zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2390 : {
2391 1043935 : if (signbit_known > 0)
2392 : {
2393 16667 : lb = dconst0;
2394 16667 : ub = dconstinf;
2395 : }
2396 1027268 : else if (signbit_known < 0)
2397 : {
2398 6168 : lb = dconstninf;
2399 6168 : ub = dconstm0;
2400 : }
2401 : else
2402 : {
2403 1021100 : lb = dconstninf;
2404 1021100 : ub = dconstinf;
2405 : }
2406 1043935 : }
2407 :
2408 : bool
2409 172725 : operator_plus::op1_range (frange &r, tree type, const frange &lhs,
2410 : const frange &op2, relation_trio) const
2411 : {
2412 172725 : if (lhs.undefined_p ())
2413 : return false;
2414 172725 : range_op_handler minus (MINUS_EXPR);
2415 172725 : if (!minus)
2416 : return false;
2417 172725 : frange wlhs = lhs;
2418 172725 : wlhs.widen (type);
2419 172725 : return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
2420 : r, type, wlhs);
2421 172725 : }
2422 :
2423 : bool
2424 73186 : operator_plus::op2_range (frange &r, tree type,
2425 : const frange &lhs, const frange &op1,
2426 : relation_trio) const
2427 : {
2428 73186 : return op1_range (r, type, lhs, op1);
2429 : }
2430 :
2431 : void
2432 2169845 : 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 2169845 : REAL_VALUE_TYPE lb, ub;
2440 2169845 : bool maybe_nan = false;
2441 :
2442 2169845 : frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
2443 2169845 : frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
2444 :
2445 : // [-INF] + [+INF] = NAN
2446 2169845 : if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
2447 : maybe_nan = true;
2448 : // [+INF] + [-INF] = NAN
2449 828224 : 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 2169845 : bool lb_nan = real_isnan (&lb);
2455 2169845 : bool ub_nan = real_isnan (&ub);
2456 2169845 : if (lb_nan && ub_nan)
2457 : {
2458 0 : r.set_nan (type);
2459 0 : return;
2460 : }
2461 2169845 : if (lb_nan)
2462 374 : lb = dconstninf;
2463 2169471 : else if (ub_nan)
2464 0 : ub = dconstinf;
2465 2169845 : r.set (type, lb, ub, nan_state (maybe_nan));
2466 : }
2467 :
2468 :
2469 : bool
2470 95300 : operator_minus::op1_range (frange &r, tree type,
2471 : const frange &lhs, const frange &op2,
2472 : relation_trio) const
2473 : {
2474 95300 : if (lhs.undefined_p ())
2475 : return false;
2476 95300 : frange wlhs = lhs;
2477 95300 : wlhs.widen (type);
2478 95300 : return float_binary_op_range_finish (
2479 190600 : range_op_handler (PLUS_EXPR).fold_range (r, type, wlhs, op2),
2480 : r, type, wlhs);
2481 95300 : }
2482 :
2483 : bool
2484 140940 : operator_minus::op2_range (frange &r, tree type,
2485 : const frange &lhs, const frange &op1,
2486 : relation_trio) const
2487 : {
2488 140940 : if (lhs.undefined_p ())
2489 : return false;
2490 140940 : frange wlhs = lhs;
2491 140940 : wlhs.widen (type);
2492 140940 : return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
2493 : r, type, wlhs);
2494 140940 : }
2495 :
2496 : void
2497 986090 : 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 986090 : REAL_VALUE_TYPE lb, ub;
2505 986090 : bool maybe_nan = false;
2506 :
2507 986090 : frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
2508 986090 : frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
2509 :
2510 : // [+INF] - [+INF] = NAN
2511 986090 : if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
2512 : maybe_nan = true;
2513 : // [-INF] - [-INF] = NAN
2514 696305 : 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 986090 : bool lb_nan = real_isnan (&lb);
2520 986090 : bool ub_nan = real_isnan (&ub);
2521 986090 : if (lb_nan && ub_nan)
2522 : {
2523 826 : r.set_nan (type);
2524 826 : return;
2525 : }
2526 985264 : if (lb_nan)
2527 1425 : lb = dconstninf;
2528 983839 : else if (ub_nan)
2529 1750 : ub = dconstinf;
2530 985264 : 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 1267996 : find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
2541 : const REAL_VALUE_TYPE (&cp)[8])
2542 : {
2543 1267996 : lb = cp[0];
2544 1267996 : ub = cp[4];
2545 5071984 : for (int i = 1; i < 4; ++i)
2546 : {
2547 3803988 : if (real_less (&cp[i], &lb)
2548 3803988 : || (real_iszero (&lb) && real_isnegzero (&cp[i])))
2549 428928 : lb = cp[i];
2550 3803988 : if (real_less (&ub, &cp[i + 4])
2551 3803988 : || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
2552 1174826 : ub = cp[i + 4];
2553 : }
2554 1267996 : }
2555 :
2556 :
2557 : bool
2558 357191 : operator_mult::op1_range (frange &r, tree type,
2559 : const frange &lhs, const frange &op2,
2560 : relation_trio) const
2561 : {
2562 357191 : if (lhs.undefined_p ())
2563 : return false;
2564 357191 : range_op_handler rdiv (RDIV_EXPR);
2565 357191 : if (!rdiv)
2566 : return false;
2567 357191 : frange wlhs = lhs;
2568 357191 : wlhs.widen (type);
2569 357191 : bool ret = rdiv.fold_range (r, type, wlhs, op2);
2570 357191 : if (ret == false)
2571 : return false;
2572 357191 : if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2573 16 : return float_binary_op_range_finish (ret, r, type, wlhs);
2574 357175 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2575 357175 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2576 357175 : const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2577 357175 : const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2578 663004 : if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
2579 515205 : || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2580 43290 : && (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 155784 : REAL_VALUE_TYPE lb, ub;
2586 155784 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2587 155784 : zero_to_inf_range (lb, ub, signbit_known);
2588 155784 : 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 357175 : return float_binary_op_range_finish (ret, r, type, wlhs);
2595 : }
2596 :
2597 : bool
2598 86658 : operator_mult::op2_range (frange &r, tree type,
2599 : const frange &lhs, const frange &op1,
2600 : relation_trio) const
2601 : {
2602 86658 : return op1_range (r, type, lhs, op1);
2603 : }
2604 :
2605 : void
2606 1287675 : 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 1287675 : bool is_square
2614 : = (kind == VREL_EQ
2615 37876 : && real_equal (&lh_lb, &rh_lb)
2616 37873 : && real_equal (&lh_ub, &rh_ub)
2617 37873 : && real_isneg (&lh_lb) == real_isneg (&rh_lb)
2618 1325548 : && real_isneg (&lh_ub) == real_isneg (&rh_ub));
2619 1249802 : REAL_VALUE_TYPE lb, ub;
2620 2094076 : 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 1249802 : if (!is_square)
2624 : {
2625 : // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2626 1273423 : if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
2627 1273393 : || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
2628 : {
2629 85 : r.set_nan (type);
2630 443401 : return;
2631 : }
2632 :
2633 : // Otherwise, if one range includes zero and the other ends with +-INF,
2634 : // it is a maybe NAN.
2635 1249717 : if ((contains_zero_p (lh_lb, lh_ub)
2636 1033283 : && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2637 1890725 : || (contains_zero_p (rh_lb, rh_ub)
2638 230854 : && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
2639 : {
2640 443316 : maybe_nan = true;
2641 :
2642 443316 : 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 443316 : if (singleton_inf_p (lh_lb, lh_ub)
2650 443316 : || singleton_inf_p (rh_lb, rh_ub))
2651 : {
2652 1576 : inf_range (lb, ub, signbit_known);
2653 1576 : r.set (type, lb, ub, nan_state (true));
2654 1576 : return;
2655 : }
2656 :
2657 : // If one of the multiplicands must be zero, the resulting
2658 : // range is +-0 and NAN.
2659 441740 : if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
2660 : {
2661 6437 : zero_range (lb, ub, signbit_known);
2662 6437 : r.set (type, lb, ub, nan_state (true));
2663 6437 : 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 435303 : zero_to_inf_range (lb, ub, signbit_known);
2673 435303 : r.set (type, lb, ub, nan_state (true));
2674 435303 : return;
2675 : }
2676 : }
2677 :
2678 844274 : REAL_VALUE_TYPE cp[8];
2679 : // Do a cross-product. At this point none of the multiplications
2680 : // should produce a NAN.
2681 844274 : frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2682 844274 : frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2683 844274 : 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 37873 : if (contains_zero_p (lh_lb, lh_ub))
2691 : {
2692 34257 : if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
2693 1413 : cp[1] = dconst0;
2694 : else
2695 32844 : cp[1] = dconstm0;
2696 : }
2697 : else
2698 3616 : cp[1] = cp[0];
2699 37873 : cp[2] = cp[0];
2700 37873 : cp[5] = cp[4];
2701 37873 : cp[6] = cp[4];
2702 : }
2703 : else
2704 : {
2705 806401 : frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2706 806401 : frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2707 806401 : frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2708 806401 : frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2709 : }
2710 844274 : frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2711 844274 : frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2712 :
2713 844274 : find_range (lb, ub, cp);
2714 :
2715 844274 : gcc_checking_assert (!real_isnan (&lb));
2716 844274 : gcc_checking_assert (!real_isnan (&ub));
2717 844274 : 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 32741 : 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 32741 : if (lhs.undefined_p ())
2732 : return false;
2733 32741 : frange wlhs = lhs;
2734 32741 : wlhs.widen (type);
2735 32741 : bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
2736 32741 : if (!ret)
2737 : return ret;
2738 32741 : if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2739 340 : return float_binary_op_range_finish (ret, r, type, wlhs);
2740 32401 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2741 32401 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2742 32401 : const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2743 32401 : const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2744 32401 : if ((contains_zero_p (lhs_lb, lhs_ub)
2745 24382 : && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
2746 39031 : || ((contains_zero_p (op2_lb, op2_ub))
2747 8222 : && (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 25389 : REAL_VALUE_TYPE lb, ub;
2753 25389 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2754 25389 : zero_to_inf_range (lb, ub, signbit_known);
2755 25389 : r.set (type, lb, ub);
2756 : }
2757 32401 : return float_binary_op_range_finish (ret, r, type, wlhs);
2758 : }
2759 55577 : 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 55577 : if (lhs.undefined_p ())
2765 : return false;
2766 55577 : frange wlhs = lhs;
2767 55577 : wlhs.widen (type);
2768 55577 : bool ret = fold_range (r, type, op1, wlhs);
2769 55577 : if (!ret)
2770 : return ret;
2771 55577 : if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
2772 20 : return float_binary_op_range_finish (ret, r, type, wlhs, true);
2773 55557 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2774 55557 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2775 55557 : const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
2776 55557 : const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
2777 100204 : if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
2778 59278 : || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2779 7511 : && (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 45262 : REAL_VALUE_TYPE lb, ub;
2785 45262 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
2786 45262 : zero_to_inf_range (lb, ub, signbit_known);
2787 45262 : r.set (type, lb, ub);
2788 : }
2789 55557 : return float_binary_op_range_finish (ret, r, type, wlhs, true);
2790 : }
2791 : private:
2792 810684 : 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 812135 : if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
2801 811489 : || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
2802 : {
2803 652 : r.set_nan (type);
2804 386962 : return;
2805 : }
2806 :
2807 810032 : REAL_VALUE_TYPE lb, ub;
2808 810032 : bool maybe_nan = false;
2809 : // If +-0.0 is in both ranges, it is a maybe NAN.
2810 810032 : 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 890679 : else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
2814 564580 : && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2815 : maybe_nan = true;
2816 :
2817 810032 : 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 810032 : if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
2824 : {
2825 807 : zero_range (lb, ub, signbit_known);
2826 807 : r.set (type, lb, ub, nan_state (maybe_nan));
2827 807 : 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 809225 : if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
2835 : {
2836 3306 : inf_range (lb, ub, signbit_known);
2837 3306 : r.set (type, lb, ub, nan_state (maybe_nan));
2838 3306 : 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 805919 : if (maybe_nan)
2855 : {
2856 382197 : zero_to_inf_range (lb, ub, signbit_known);
2857 382197 : r.set (type, lb, ub, nan_state (maybe_nan));
2858 382197 : return;
2859 : }
2860 :
2861 423722 : REAL_VALUE_TYPE cp[8];
2862 : // Do a cross-division. At this point none of the divisions should
2863 : // produce a NAN.
2864 423722 : frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2865 423722 : frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2866 423722 : frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2867 423722 : frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2868 423722 : frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2869 423722 : frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2870 423722 : frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2871 423722 : frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2872 :
2873 423722 : 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 423722 : if (contains_zero_p (rh_lb, rh_ub))
2879 : {
2880 43644 : if (signbit_known <= 0)
2881 40684 : real_inf (&lb, true);
2882 40684 : if (signbit_known >= 0)
2883 43595 : real_inf (&ub, false);
2884 : }
2885 :
2886 423722 : gcc_checking_assert (!real_isnan (&lb));
2887 423722 : gcc_checking_assert (!real_isnan (&ub));
2888 423722 : r.set (type, lb, ub, nan_state (maybe_nan));
2889 : }
2890 : };
2891 : static const foperator_div fop_div;
2892 :
2893 : bool
2894 953154 : operator_cast::fold_range (frange &r, tree type, const frange &op1,
2895 : const frange &, relation_trio) const
2896 : {
2897 953154 : enum machine_mode mode = TYPE_MODE (type);
2898 6672078 : bool mode_composite = MODE_COMPOSITE_P (mode);
2899 :
2900 953154 : if (empty_range_varying (r, type, op1, op1))
2901 1105 : return true;
2902 3808196 : if (!MODE_HAS_NANS (mode) && op1.maybe_isnan ())
2903 : {
2904 0 : r.set_varying (type);
2905 0 : return true;
2906 : }
2907 952049 : if (op1.known_isnan ())
2908 : {
2909 2790 : r.set_nan (type);
2910 2790 : return true;
2911 : }
2912 :
2913 949259 : r.set_undefined ();
2914 2874940 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
2915 : {
2916 976422 : REAL_VALUE_TYPE lb, ub;
2917 976422 : const REAL_VALUE_TYPE &lh_lb = op1.lower_bound (i);
2918 976422 : const REAL_VALUE_TYPE &lh_ub = op1.upper_bound (i);
2919 976422 : real_convert (&lb, mode, &lh_lb);
2920 976422 : real_convert (&ub, mode, &lh_ub);
2921 :
2922 976422 : if (flag_rounding_math)
2923 : {
2924 40176 : if (real_less (&lh_lb, &lb))
2925 : {
2926 3098 : if (mode_composite
2927 3098 : && (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 3098 : frange_nextafter (mode, lb, dconstninf);
2938 : }
2939 40176 : if (real_less (&ub, &lh_ub))
2940 : {
2941 1384 : if (mode_composite
2942 1384 : && (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 1384 : frange_nextafter (mode, ub, dconstinf);
2953 : }
2954 : }
2955 :
2956 976422 : frange tmp;
2957 976422 : tmp.set (type, lb, ub, op1.get_nan_state ());
2958 976422 : r.union_ (tmp);
2959 976422 : }
2960 :
2961 949259 : if (flag_trapping_math
2962 4290022 : && MODE_HAS_INFINITIES (TYPE_MODE (type))
2963 835191 : && r.known_isinf ()
2964 949349 : && !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 949259 : r.flush_denormals_to_zero ();
2980 949259 : return true;
2981 : }
2982 :
2983 : // Implement fold for a cast from float to another float.
2984 : bool
2985 58733 : operator_cast::op1_range (frange &r, tree type, const frange &lhs,
2986 : const frange &op2, relation_trio) const
2987 : {
2988 58733 : if (lhs.undefined_p ())
2989 : return false;
2990 58733 : tree lhs_type = lhs.type ();
2991 58733 : enum machine_mode mode = TYPE_MODE (type);
2992 58733 : enum machine_mode lhs_mode = TYPE_MODE (lhs_type);
2993 58733 : frange wlhs;
2994 58733 : bool rm;
2995 58733 : if (REAL_MODE_FORMAT (mode)->ieee_bits
2996 53839 : && REAL_MODE_FORMAT (lhs_mode)->ieee_bits
2997 48869 : && (REAL_MODE_FORMAT (lhs_mode)->ieee_bits
2998 : >= REAL_MODE_FORMAT (mode)->ieee_bits)
2999 79472 : && 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 20739 : rm = false;
3005 20739 : wlhs = lhs;
3006 : }
3007 : else
3008 : {
3009 37994 : rm = true;
3010 37994 : wlhs = lhs;
3011 37994 : wlhs.widen (lhs_type);
3012 : }
3013 58733 : auto save_flag_rounding_math = flag_rounding_math;
3014 58733 : flag_rounding_math = rm;
3015 58733 : bool ret = float_binary_op_range_finish (fold_range (r, type, wlhs, op2),
3016 : r, type, lhs);
3017 58733 : flag_rounding_math = save_flag_rounding_math;
3018 58733 : return ret;
3019 58733 : }
3020 :
3021 : // Implement fold for a cast from float to an int.
3022 : bool
3023 214872 : operator_cast::fold_range (irange &r, tree type, const frange &op1,
3024 : const irange &, relation_trio) const
3025 : {
3026 214872 : if (empty_range_varying (r, type, op1, op1))
3027 828 : return true;
3028 214044 : if (op1.maybe_isnan () || op1.maybe_isinf ())
3029 : {
3030 183891 : r.set_varying (type);
3031 183891 : return true;
3032 : }
3033 30153 : REAL_VALUE_TYPE l, u;
3034 30153 : l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
3035 30153 : u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
3036 :
3037 30153 : r.set_undefined ();
3038 70872 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
3039 : {
3040 30863 : REAL_VALUE_TYPE lb, ub;
3041 30863 : real_trunc (&lb, VOIDmode, &op1.lower_bound (i));
3042 30863 : real_trunc (&ub, VOIDmode, &op1.upper_bound (i));
3043 30863 : if (real_less (&lb, &l))
3044 : {
3045 11514 : r.set_varying (type);
3046 20297 : return true;
3047 : }
3048 19349 : if (real_less (&u, &ub))
3049 : {
3050 8783 : r.set_varying (type);
3051 8783 : return true;
3052 : }
3053 10566 : bool fail = false;
3054 10566 : wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
3055 10566 : wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
3056 10566 : if (fail)
3057 : {
3058 0 : r.set_varying (type);
3059 0 : return true;
3060 : }
3061 10566 : int_range<2> tmp (type, wlb, wub);
3062 10566 : r.union_ (tmp);
3063 10566 : }
3064 : return true;
3065 : }
3066 :
3067 : // Implement op1_range for a cast from float to an int.
3068 : bool
3069 7956 : operator_cast::op1_range (frange &r, tree type, const irange &lhs,
3070 : const frange &, relation_trio) const
3071 : {
3072 7956 : if (lhs.undefined_p ())
3073 : return false;
3074 7956 : REAL_VALUE_TYPE lb, lbo, ub, ubo;
3075 7956 : wide_int lhs_lb = lhs.lower_bound ();
3076 7956 : wide_int lhs_ub = lhs.upper_bound ();
3077 7956 : tree lhs_type = lhs.type ();
3078 7956 : enum machine_mode mode = TYPE_MODE (type);
3079 7956 : real_from_integer (&lbo, VOIDmode, lhs_lb, TYPE_SIGN (lhs_type));
3080 7956 : real_from_integer (&ubo, VOIDmode, lhs_ub, TYPE_SIGN (lhs_type));
3081 7956 : real_convert (&lb, mode, &lbo);
3082 7956 : real_convert (&ub, mode, &ubo);
3083 7956 : if (real_identical (&lb, &lbo))
3084 : {
3085 : /* If low bound is exactly representable in type,
3086 : use nextafter (lb - 1., +inf). */
3087 7742 : real_arithmetic (&lb, PLUS_EXPR, &lbo, &dconstm1);
3088 7742 : real_convert (&lb, mode, &lb);
3089 7742 : if (!real_identical (&lb, &lbo))
3090 6361 : frange_nextafter (mode, lb, dconstinf);
3091 7742 : if (real_identical (&lb, &lbo))
3092 1383 : frange_nextafter (mode, lb, dconstninf);
3093 : }
3094 214 : else if (real_less (&lbo, &lb))
3095 9 : frange_nextafter (mode, lb, dconstninf);
3096 7956 : if (real_identical (&ub, &ubo))
3097 : {
3098 : /* If upper bound is exactly representable in type,
3099 : use nextafter (ub + 1., -inf). */
3100 6003 : real_arithmetic (&ub, PLUS_EXPR, &ubo, &dconst1);
3101 6003 : real_convert (&ub, mode, &ub);
3102 6003 : if (!real_identical (&ub, &ubo))
3103 5849 : frange_nextafter (mode, ub, dconstninf);
3104 6003 : if (real_identical (&ub, &ubo))
3105 154 : frange_nextafter (mode, ub, dconstinf);
3106 : }
3107 1953 : else if (real_less (&ub, &ubo))
3108 0 : frange_nextafter (mode, ub, dconstinf);
3109 7956 : r.set (type, lb, ub, nan_state (false));
3110 7956 : return true;
3111 7956 : }
3112 :
3113 : // Implement fold for a cast from int to a float.
3114 : bool
3115 857510 : operator_cast::fold_range (frange &r, tree type, const irange &op1,
3116 : const frange &, relation_trio) const
3117 : {
3118 857510 : if (empty_range_varying (r, type, op1, op1))
3119 1487 : return true;
3120 856023 : tree op1_type = op1.type ();
3121 856023 : r.set_undefined ();
3122 2639851 : for (unsigned i = 0; i < op1.num_pairs (); ++i)
3123 : {
3124 927805 : REAL_VALUE_TYPE lb, ub;
3125 927805 : wide_int op1_lb = op1.lower_bound (i);
3126 927805 : wide_int op1_ub = op1.upper_bound (i);
3127 927805 : enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
3128 927805 : real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
3129 927805 : real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
3130 927805 : if (flag_rounding_math)
3131 : {
3132 1395 : REAL_VALUE_TYPE lbo = lb, ubo = ub;
3133 1395 : mode = TYPE_MODE (type);
3134 1395 : real_convert (&lb, mode, &lb);
3135 1395 : real_convert (&ub, mode, &ub);
3136 1395 : if (real_less (&lbo, &lb))
3137 322 : frange_nextafter (mode, lb, dconstninf);
3138 1395 : if (real_less (&ub, &ubo))
3139 192 : frange_nextafter (mode, ub, dconstinf);
3140 : }
3141 927805 : frange tmp;
3142 927805 : tmp.set (type, lb, ub, nan_state (false));
3143 927805 : r.union_ (tmp);
3144 927835 : }
3145 856023 : 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 225358 : operator_cast::op1_range (irange &r, tree type, const frange &lhs,
3153 : const irange &, relation_trio) const
3154 : {
3155 225358 : if (lhs.undefined_p ())
3156 : return false;
3157 225358 : if (lhs.known_isnan ())
3158 : {
3159 0 : r.set_varying (type);
3160 0 : return true;
3161 : }
3162 225358 : REAL_VALUE_TYPE lb = lhs.lower_bound ();
3163 225358 : REAL_VALUE_TYPE ub = lhs.upper_bound ();
3164 225358 : enum machine_mode mode = TYPE_MODE (lhs.type ());
3165 225358 : frange_nextafter (mode, lb, dconstninf);
3166 225358 : frange_nextafter (mode, ub, dconstinf);
3167 225358 : if (flag_rounding_math)
3168 : {
3169 37 : real_floor (&lb, mode, &lb);
3170 37 : real_ceil (&ub, mode, &ub);
3171 : }
3172 : else
3173 : {
3174 225321 : real_trunc (&lb, mode, &lb);
3175 225321 : real_trunc (&ub, mode, &ub);
3176 : }
3177 225358 : REAL_VALUE_TYPE l, u;
3178 225358 : wide_int wlb, wub;
3179 225358 : l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
3180 225358 : if (real_less (&lb, &l))
3181 28242 : wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3182 : else
3183 : {
3184 197116 : bool fail = false;
3185 197116 : wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
3186 197116 : if (fail)
3187 0 : wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3188 : }
3189 225358 : u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
3190 225358 : if (real_less (&u, &ub))
3191 39311 : wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3192 : else
3193 : {
3194 186047 : bool fail = false;
3195 186047 : wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
3196 186047 : if (fail)
3197 0 : wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3198 : }
3199 225358 : r.set (type, wlb, wub);
3200 225358 : return true;
3201 225358 : }
3202 :
3203 : // Initialize any float operators to the primary table
3204 :
3205 : void
3206 293026 : range_op_table::initialize_float_ops ()
3207 : {
3208 293026 : set (UNLE_EXPR, fop_unordered_le);
3209 293026 : set (UNLT_EXPR, fop_unordered_lt);
3210 293026 : set (UNGE_EXPR, fop_unordered_ge);
3211 293026 : set (UNGT_EXPR, fop_unordered_gt);
3212 293026 : set (UNEQ_EXPR, fop_unordered_equal);
3213 293026 : set (ORDERED_EXPR, fop_ordered);
3214 293026 : set (UNORDERED_EXPR, fop_unordered);
3215 293026 : set (LTGT_EXPR, fop_ltgt);
3216 293026 : set (RDIV_EXPR, fop_div);
3217 293026 : }
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
|