LCOV - code coverage report
Current view: top level - gcc - range-op-float.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.2 % 1407 1326
Test Date: 2026-08-22 16:33:35 Functions: 97.3 % 112 109
Legend: Lines:     hit not hit

            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
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.