LCOV - code coverage report
Current view: top level - gcc - range-op-float.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.7 % 1344 1246
Test Date: 2026-07-11 15:47:05 Functions: 97.3 % 113 110
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      5398635 : range_operator::fold_range (frange &r, tree type,
      54              :                             const frange &op1, const frange &op2,
      55              :                             relation_trio trio) const
      56              : {
      57      5398635 :   if (empty_range_varying (r, type, op1, op2))
      58         6338 :     return true;
      59      5392297 :   if (op1.known_isnan () || op2.known_isnan ())
      60              :     {
      61         6993 :       r.set_nan (type);
      62         6993 :       return true;
      63              :     }
      64              : 
      65      5385304 :   rv_fold (r, type,
      66              :            op1.lower_bound (), op1.upper_bound (),
      67              :            op2.lower_bound (), op2.upper_bound (), trio.op1_op2 ());
      68              : 
      69      5385304 :   if (r.known_isnan ())
      70              :     return true;
      71      8821244 :   if (op1.maybe_isnan () || op2.maybe_isnan ())
      72      3846177 :     r.update_nan ();
      73              : 
      74              :   // If the result has overflowed and flag_trapping_math, folding this
      75              :   // operation could elide an overflow or division by zero exception.
      76              :   // Avoid returning a singleton +-INF, to keep the propagators (DOM
      77              :   // and substitute_and_fold_engine) from folding.  See PR107608.
      78      5384615 :   if (flag_trapping_math
      79     25275988 :       && MODE_HAS_INFINITIES (TYPE_MODE (type))
      80     10357861 :       && r.known_isinf () && !op1.known_isinf () && !op2.known_isinf ())
      81              :     {
      82         1611 :       REAL_VALUE_TYPE inf = r.lower_bound ();
      83         1611 :       if (real_isneg (&inf))
      84              :         {
      85           96 :           REAL_VALUE_TYPE min = real_min_representable (type);
      86           96 :           r.set (type, inf, min);
      87              :         }
      88              :       else
      89              :         {
      90         1515 :           REAL_VALUE_TYPE max = real_max_representable (type);
      91         1515 :           r.set (type, max, inf);
      92              :         }
      93              :     }
      94              : 
      95      5384615 :   r.flush_denormals_to_zero ();
      96              : 
      97      5384615 :   return true;
      98              : }
      99              : 
     100              : // For a given operation, fold two sets of ranges into [lb, ub].
     101              : // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
     102              : // UB, the final range has the possibility of a NAN.
     103              : void
     104       512933 : range_operator::rv_fold (frange &r, tree type,
     105              :                          const REAL_VALUE_TYPE &,
     106              :                          const REAL_VALUE_TYPE &,
     107              :                          const REAL_VALUE_TYPE &,
     108              :                          const REAL_VALUE_TYPE &, relation_kind) const
     109              : {
     110       512933 :   r.set (type, dconstninf, dconstinf, nan_state (true));
     111       512933 : }
     112              : 
     113              : bool
     114       102287 : range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
     115              :                             tree type ATTRIBUTE_UNUSED,
     116              :                             const frange &lh ATTRIBUTE_UNUSED,
     117              :                             const irange &rh ATTRIBUTE_UNUSED,
     118              :                             relation_trio) const
     119              : {
     120       102287 :   return false;
     121              : }
     122              : 
     123              : bool
     124            0 : range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
     125              :                             tree type ATTRIBUTE_UNUSED,
     126              :                             const frange &lh ATTRIBUTE_UNUSED,
     127              :                             const frange &rh ATTRIBUTE_UNUSED,
     128              :                             relation_trio) const
     129              : {
     130            0 :   return false;
     131              : }
     132              : 
     133              : bool
     134            0 : range_operator::fold_range (frange &r ATTRIBUTE_UNUSED,
     135              :                             tree type ATTRIBUTE_UNUSED,
     136              :                             const irange &lh ATTRIBUTE_UNUSED,
     137              :                             const irange &rh ATTRIBUTE_UNUSED,
     138              :                             relation_trio) const
     139              : {
     140            0 :   return false;
     141              : }
     142              : 
     143              : bool
     144          676 : range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
     145              :                            tree type ATTRIBUTE_UNUSED,
     146              :                            const frange &lhs ATTRIBUTE_UNUSED,
     147              :                            const frange &op2 ATTRIBUTE_UNUSED,
     148              :                            relation_trio) const
     149              : {
     150          676 :   return false;
     151              : }
     152              : 
     153              : bool
     154         6160 : range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
     155              :                                  tree type ATTRIBUTE_UNUSED,
     156              :                                  const irange &lhs ATTRIBUTE_UNUSED,
     157              :                                  const frange &op2 ATTRIBUTE_UNUSED,
     158              :                                  relation_trio) const
     159              : {
     160         6160 :   return false;
     161              : }
     162              : 
     163              : bool
     164         2391 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
     165              :                            tree type ATTRIBUTE_UNUSED,
     166              :                            const frange &lhs ATTRIBUTE_UNUSED,
     167              :                            const frange &op1 ATTRIBUTE_UNUSED,
     168              :                            relation_trio) const
     169              : {
     170         2391 :   return false;
     171              : }
     172              : 
     173              : bool
     174            0 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
     175              :                            tree type ATTRIBUTE_UNUSED,
     176              :                            const irange &lhs ATTRIBUTE_UNUSED,
     177              :                            const frange &op1 ATTRIBUTE_UNUSED,
     178              :                            relation_trio) const
     179              : {
     180            0 :   return false;
     181              : }
     182              : 
     183              : relation_kind
     184      5406525 : range_operator::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
     185              :                                   const frange &op1 ATTRIBUTE_UNUSED,
     186              :                                   const frange &op2 ATTRIBUTE_UNUSED,
     187              :                                   relation_kind) const
     188              : {
     189      5406525 :   return VREL_VARYING;
     190              : }
     191              : 
     192              : relation_kind
     193      1060419 : range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
     194              :                                   const frange &op1 ATTRIBUTE_UNUSED,
     195              :                                   const frange &op2 ATTRIBUTE_UNUSED,
     196              :                                   relation_kind) const
     197              : {
     198      1060419 :   return VREL_VARYING;
     199              : }
     200              : 
     201              : relation_kind
     202       181814 : range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
     203              :                                   const frange &op1 ATTRIBUTE_UNUSED,
     204              :                                   const frange &op2 ATTRIBUTE_UNUSED,
     205              :                                   relation_kind) const
     206              : {
     207       181814 :   return VREL_VARYING;
     208              : }
     209              : 
     210              : relation_kind
     211      3279187 : range_operator::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
     212              :                                   const frange &op1 ATTRIBUTE_UNUSED,
     213              :                                   const frange &op2 ATTRIBUTE_UNUSED,
     214              :                                   relation_kind) const
     215              : {
     216      3279187 :   return VREL_VARYING;
     217              : }
     218              : 
     219              : relation_kind
     220       360920 : range_operator::op1_op2_relation (const irange &,
     221              :                                   const frange &,
     222              :                                   const frange &) const
     223              : {
     224       360920 :   return VREL_VARYING;
     225              : }
     226              : 
     227              : 
     228              : relation_kind
     229       621634 : range_operator::op1_op2_relation (const frange &,
     230              :                                   const frange &,
     231              :                                   const frange &) const
     232              : {
     233       621634 :   return VREL_VARYING;
     234              : }
     235              : 
     236              : // Return TRUE if OP1 and OP2 may be a NAN.
     237              : 
     238              : static inline bool
     239      3643192 : maybe_isnan (const frange &op1, const frange &op2)
     240              : {
     241      6334524 :   return op1.maybe_isnan () || op2.maybe_isnan ();
     242              : }
     243              : 
     244              : // Floating point version of relop_early_resolve that takes NANs into
     245              : // account.
     246              : //
     247              : // For relation opcodes, first try to see if the supplied relation
     248              : // forces a true or false result, and return that.
     249              : // Then check for undefined operands.  If none of this applies,
     250              : // return false.
     251              : //
     252              : // TRIO are the relations between operands as they appear in the IL.
     253              : // MY_REL is the relation that corresponds to the operator being
     254              : // folded.  For example, when attempting to fold x_3 == y_5, MY_REL is
     255              : // VREL_EQ, and if the statement is dominated by x_3 > y_5, then
     256              : // TRIO.op1_op2() is VREL_GT.
     257              : 
     258              : static inline bool
     259      2117385 : frelop_early_resolve (irange &r, tree type,
     260              :                       const frange &op1, const frange &op2,
     261              :                       relation_trio trio, relation_kind my_rel)
     262              : {
     263      2117385 :   relation_kind rel = trio.op1_op2 ();
     264              : 
     265              :   // If known relation is a complete subset of this relation, always
     266              :   // return true.  However, avoid doing this when NAN is a possibility
     267              :   // as we'll incorrectly fold conditions:
     268              :   //
     269              :   //   if (x_3 >= y_5)
     270              :   //     ;
     271              :   //   else
     272              :   //     ;; With NANs the relation here is basically VREL_UNLT, so we
     273              :   //     ;; can't fold the following:
     274              :   //     if (x_3 < y_5)
     275      2117385 :   if (!maybe_isnan (op1, op2) && relation_union (rel, my_rel) == my_rel)
     276              :     {
     277         2104 :       r = range_true (type);
     278         2104 :       return true;
     279              :     }
     280              : 
     281              :   // If known relation has no subset of this relation, always false.
     282      2115281 :   if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
     283              :     {
     284         1114 :       r = range_false (type);
     285         1114 :       return true;
     286              :     }
     287              : 
     288              :   // If either operand is undefined, return VARYING.
     289      2114167 :   if (empty_range_varying (r, type, op1, op2))
     290         3776 :     return true;
     291              : 
     292              :   return false;
     293              : }
     294              : 
     295              : // Set VALUE to its next real value, or INF if the operation overflows.
     296              : 
     297              : void
     298      3460221 : frange_nextafter (enum machine_mode mode,
     299              :                   REAL_VALUE_TYPE &value,
     300              :                   const REAL_VALUE_TYPE &inf)
     301              : {
     302     24221547 :   if (MODE_COMPOSITE_P (mode)
     303            0 :       && (real_isdenormal (&value, mode) || real_iszero (&value)))
     304              :     {
     305              :       // IBM extended denormals only have DFmode precision.
     306            0 :       REAL_VALUE_TYPE tmp, tmp2;
     307            0 :       real_convert (&tmp2, DFmode, &value);
     308            0 :       real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
     309            0 :       real_convert (&value, mode, &tmp);
     310              :     }
     311              :   else
     312              :     {
     313      3460221 :       REAL_VALUE_TYPE tmp;
     314      3460221 :       real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
     315      3460221 :       value = tmp;
     316              :     }
     317      3460221 : }
     318              : 
     319              : // Like real_arithmetic, but round the result to INF if the operation
     320              : // produced inexact results.
     321              : //
     322              : // ?? There is still one problematic case, i387.  With
     323              : // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
     324              : // XFmode (long_double_type_node), so that case is OK.  But without
     325              : // -mfpmath=sse, all the SF/DFmode computations are in XFmode
     326              : // precision (64-bit mantissa) and only occasionally rounded to
     327              : // SF/DFmode (when storing into memory from the 387 stack).  Maybe
     328              : // this is ok as well though it is just occasionally more precise. ??
     329              : 
     330              : void
     331     14508723 : frange_arithmetic (enum tree_code code, tree type,
     332              :                    REAL_VALUE_TYPE &result,
     333              :                    const REAL_VALUE_TYPE &op1,
     334              :                    const REAL_VALUE_TYPE &op2,
     335              :                    const REAL_VALUE_TYPE &inf)
     336              : {
     337     14508723 :   REAL_VALUE_TYPE value;
     338     14508723 :   enum machine_mode mode = TYPE_MODE (type);
     339    101561061 :   bool mode_composite = MODE_COMPOSITE_P (mode);
     340              : 
     341     14508723 :   bool inexact = real_arithmetic (&value, code, &op1, &op2);
     342     14508723 :   real_convert (&result, mode, &value);
     343              : 
     344              :   /* When rounding towards negative infinity, x + (-x) and
     345              :      x - x is -0 rather than +0 real_arithmetic computes.
     346              :      So, when we are looking for lower bound (inf is negative),
     347              :      use -0 rather than +0.  */
     348     14508723 :   if (flag_rounding_math
     349        16184 :       && (code == PLUS_EXPR || code == MINUS_EXPR)
     350         4516 :       && !inexact
     351         4516 :       && real_iszero (&result)
     352           66 :       && !real_isneg (&result)
     353     14508789 :       && real_isneg (&inf))
     354              :     {
     355           36 :       REAL_VALUE_TYPE op2a = op2;
     356           36 :       if (code == PLUS_EXPR)
     357           30 :         op2a.sign ^= 1;
     358           36 :       if (real_isneg (&op1) == real_isneg (&op2a) && real_equal (&op1, &op2a))
     359           36 :         result.sign = 1;
     360              :     }
     361              : 
     362              :   // Be extra careful if there may be discrepancies between the
     363              :   // compile and runtime results.
     364     14508723 :   bool round = false;
     365     14508723 :   if (mode_composite)
     366              :     round = true;
     367              :   else
     368              :     {
     369     14508723 :       bool low = real_isneg (&inf);
     370     14508723 :       round = (low ? !real_less (&result, &value)
     371      7254425 :                    : !real_less (&value, &result));
     372     14508723 :       if (real_isinf (&result, !low)
     373      1531185 :           && !real_isinf (&value)
     374     14901664 :           && !flag_rounding_math)
     375              :         {
     376              :           // Use just [+INF, +INF] rather than [MAX, +INF]
     377              :           // even if value is larger than MAX and rounds to
     378              :           // nearest to +INF.  Similarly just [-INF, -INF]
     379              :           // rather than [-INF, +MAX] even if value is smaller
     380              :           // than -MAX and rounds to nearest to -INF.
     381              :           // Unless INEXACT is true, in that case we need some
     382              :           // extra buffer.
     383       391040 :           if (!inexact)
     384              :             round = false;
     385              :           else
     386              :             {
     387        56738 :               REAL_VALUE_TYPE tmp = result, tmp2;
     388        56738 :               frange_nextafter (mode, tmp, inf);
     389              :               // TMP is at this point the maximum representable
     390              :               // number.
     391        56738 :               real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp);
     392        56738 :               if (real_isneg (&tmp2) != low
     393        56738 :                   && (REAL_EXP (&tmp2) - REAL_EXP (&tmp)
     394        56738 :                       >= 2 - REAL_MODE_FORMAT (mode)->p))
     395        56737 :                 round = false;
     396              :             }
     397              :         }
     398              :     }
     399     14174421 :   if (round && (inexact || !real_identical (&result, &value)))
     400              :     {
     401      1236652 :       if (mode_composite
     402      1236652 :           && (real_isdenormal (&result, mode) || real_iszero (&result)))
     403              :         {
     404              :           // IBM extended denormals only have DFmode precision.
     405            0 :           REAL_VALUE_TYPE tmp, tmp2;
     406            0 :           real_convert (&tmp2, DFmode, &value);
     407            0 :           real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
     408            0 :           real_convert (&result, mode, &tmp);
     409              :         }
     410              :       else
     411      1236652 :         frange_nextafter (mode, result, inf);
     412              :     }
     413     14508723 :   if (mode_composite)
     414            0 :     switch (code)
     415              :       {
     416            0 :       case PLUS_EXPR:
     417            0 :       case MINUS_EXPR:
     418              :         // ibm-ldouble-format documents 1ulp for + and -.
     419            0 :         frange_nextafter (mode, result, inf);
     420            0 :         break;
     421            0 :       case MULT_EXPR:
     422              :         // ibm-ldouble-format documents 2ulps for *.
     423            0 :         frange_nextafter (mode, result, inf);
     424            0 :         frange_nextafter (mode, result, inf);
     425            0 :         break;
     426            0 :       case RDIV_EXPR:
     427              :         // ibm-ldouble-format documents 3ulps for /.
     428            0 :         frange_nextafter (mode, result, inf);
     429            0 :         frange_nextafter (mode, result, inf);
     430            0 :         frange_nextafter (mode, result, inf);
     431            0 :         break;
     432              :       default:
     433              :         break;
     434              :       }
     435     14508723 : }
     436              : 
     437              : // Crop R to [-INF, MAX] where MAX is the maximum representable number
     438              : // for TYPE.
     439              : 
     440              : static inline void
     441       177032 : frange_drop_inf (frange &r, tree type)
     442              : {
     443       177032 :   REAL_VALUE_TYPE max = real_max_representable (type);
     444       177032 :   frange tmp (type, r.lower_bound (), max);
     445       177032 :   r.intersect (tmp);
     446       177032 : }
     447              : 
     448              : // Crop R to [MIN, +INF] where MIN is the minimum representable number
     449              : // for TYPE.
     450              : 
     451              : static inline void
     452        91381 : frange_drop_ninf (frange &r, tree type)
     453              : {
     454        91381 :   REAL_VALUE_TYPE min = real_min_representable (type);
     455        91381 :   frange tmp (type, min, r.upper_bound ());
     456        91381 :   r.intersect (tmp);
     457        91381 : }
     458              : 
     459              : // Crop R to [MIN, MAX] where MAX is the maximum representable number
     460              : // for TYPE and MIN the minimum representable number for TYPE.
     461              : 
     462              : static inline void
     463      1323205 : frange_drop_infs (frange &r, tree type)
     464              : {
     465      1323205 :   REAL_VALUE_TYPE max = real_max_representable (type);
     466      1323205 :   REAL_VALUE_TYPE min = real_min_representable (type);
     467      1323205 :   frange tmp (type, min, max);
     468      1323205 :   r.intersect (tmp);
     469      1323205 : }
     470              : 
     471              : // If zero is in R, make sure both -0.0 and +0.0 are in the range.
     472              : 
     473              : static inline void
     474       923831 : frange_add_zeros (frange &r, tree type)
     475              : {
     476       923831 :   if (r.undefined_p () || r.known_isnan ())
     477              :     return;
     478              : 
     479       923831 :   if (HONOR_SIGNED_ZEROS (type)
     480       923831 :       && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
     481              :     {
     482       161851 :       frange zero;
     483       161851 :       zero.set_zero (type);
     484       161851 :       r.union_ (zero);
     485       161851 :     }
     486              : }
     487              : 
     488              : // Build a range that is <= VAL and store it in R.  Return TRUE if
     489              : // further changes may be needed for R, or FALSE if R is in its final
     490              : // form.
     491              : 
     492              : static bool
     493       254642 : build_le (frange &r, tree type, const frange &val)
     494              : {
     495       254642 :   gcc_checking_assert (!val.known_isnan ());
     496              : 
     497       254642 :   REAL_VALUE_TYPE ninf = frange_val_min (type);
     498       254642 :   r.set (type, ninf, val.upper_bound ());
     499              : 
     500              :   // Add both zeros if there's the possibility of zero equality.
     501       254642 :   frange_add_zeros (r, type);
     502              : 
     503       254642 :   return true;
     504              : }
     505              : 
     506              : // Build a range that is < VAL and store it in R.  Return TRUE if
     507              : // further changes may be needed for R, or FALSE if R is in its final
     508              : // form.
     509              : 
     510              : static bool
     511       306492 : build_lt (frange &r, tree type, const frange &val)
     512              : {
     513       306492 :   gcc_checking_assert (!val.known_isnan ());
     514              : 
     515              :   // < -INF is outside the range.
     516       306492 :   if (real_isinf (&val.upper_bound (), 1))
     517              :     {
     518         1450 :       if (HONOR_NANS (type))
     519         1450 :         r.set_nan (type);
     520              :       else
     521            0 :         r.set_undefined ();
     522         1450 :       return false;
     523              :     }
     524              : 
     525       305042 :   REAL_VALUE_TYPE ninf = frange_val_min (type);
     526       305042 :   REAL_VALUE_TYPE prev = val.upper_bound ();
     527       305042 :   machine_mode mode = TYPE_MODE (type);
     528              :   // Default to the conservatively correct closed ranges for
     529              :   // MODE_COMPOSITE_P, otherwise use nextafter.  Note that for
     530              :   // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
     531              :   // will crop the range appropriately.
     532      2135294 :   if (!MODE_COMPOSITE_P (mode))
     533       305042 :     frange_nextafter (mode, prev, ninf);
     534       305042 :   r.set (type, ninf, prev);
     535       305042 :   return true;
     536              : }
     537              : 
     538              : // Build a range that is >= VAL and store it in R.  Return TRUE if
     539              : // further changes may be needed for R, or FALSE if R is in its final
     540              : // form.
     541              : 
     542              : static bool
     543       388154 : build_ge (frange &r, tree type, const frange &val)
     544              : {
     545       388154 :   gcc_checking_assert (!val.known_isnan ());
     546              : 
     547       388154 :   REAL_VALUE_TYPE inf = frange_val_max (type);
     548       388154 :   r.set (type, val.lower_bound (), inf);
     549              : 
     550              :   // Add both zeros if there's the possibility of zero equality.
     551       388154 :   frange_add_zeros (r, type);
     552              : 
     553       388154 :   return true;
     554              : }
     555              : 
     556              : // Build a range that is > VAL and store it in R.  Return TRUE if
     557              : // further changes may be needed for R, or FALSE if R is in its final
     558              : // form.
     559              : 
     560              : static bool
     561       201378 : build_gt (frange &r, tree type, const frange &val)
     562              : {
     563       201378 :   gcc_checking_assert (!val.known_isnan ());
     564              : 
     565              :   // > +INF is outside the range.
     566       201378 :   if (real_isinf (&val.lower_bound (), 0))
     567              :     {
     568         3080 :       if (HONOR_NANS (type))
     569         3080 :         r.set_nan (type);
     570              :       else
     571            0 :         r.set_undefined ();
     572         3080 :       return false;
     573              :     }
     574              : 
     575       198298 :   REAL_VALUE_TYPE inf = frange_val_max (type);
     576       198298 :   REAL_VALUE_TYPE next = val.lower_bound ();
     577       198298 :   machine_mode mode = TYPE_MODE (type);
     578              :   // Default to the conservatively correct closed ranges for
     579              :   // MODE_COMPOSITE_P, otherwise use nextafter.  Note that for
     580              :   // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
     581              :   // will crop the range appropriately.
     582      1388086 :   if (!MODE_COMPOSITE_P (mode))
     583       198298 :     frange_nextafter (mode, next, inf);
     584       198298 :   r.set (type, next, inf);
     585       198298 :   return true;
     586              : }
     587              : 
     588              : 
     589              : bool
     590        56754 : operator_identity::fold_range (frange &r, tree, const frange &op1,
     591              :                                const frange &, relation_trio) const
     592              : {
     593        56754 :   r = op1;
     594        56754 :   return true;
     595              : }
     596              : 
     597              : bool
     598        17060 : operator_identity::op1_range (frange &r, tree, const frange &lhs,
     599              :                               const frange &, relation_trio) const
     600              : {
     601        17060 :   r = lhs;
     602        17060 :   return true;
     603              : }
     604              : 
     605              : bool
     606         1136 : operator_cst::fold_range (frange &r, tree, const frange &op1,
     607              :                           const frange &, relation_trio) const
     608              : {
     609         1136 :   r = op1;
     610         1136 :   return true;
     611              : }
     612              : 
     613              : bool
     614        29979 : operator_equal::op2_range (frange &r, tree type,
     615              :                            const irange &lhs, const frange &op1,
     616              :                            relation_trio rel) const
     617              : {
     618        29979 :   return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
     619              : }
     620              : 
     621              : bool
     622       196067 : operator_equal::fold_range (irange &r, tree type,
     623              :                             const frange &op1, const frange &op2,
     624              :                             relation_trio rel) const
     625              : {
     626       196067 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
     627              :     return true;
     628              : 
     629       192882 :   if (op1.known_isnan () || op2.known_isnan ())
     630          559 :     r = range_false (type);
     631              :   // We can be sure the values are always equal or not if both ranges
     632              :   // consist of a single value, and then compare them.
     633       192323 :   else if (op1.singleton_p () && op2.singleton_p ())
     634              :     {
     635          618 :       if (op1 == op2)
     636          248 :         r = range_true (type);
     637              :       // If one operand is -0.0 and other 0.0, they are still equal.
     638          370 :       else if (real_iszero (&op1.lower_bound ())
     639          370 :                && real_iszero (&op2.lower_bound ()))
     640           29 :         r = range_true (type);
     641              :       else
     642          341 :         r = range_false (type);
     643              :     }
     644       191705 :   else if (real_iszero (&op1.lower_bound ())
     645         6063 :            && real_iszero (&op1.upper_bound ())
     646          665 :            && real_iszero (&op2.lower_bound ())
     647          387 :            && real_iszero (&op2.upper_bound ())
     648       192092 :            && !maybe_isnan (op1, op2))
     649              :     // [-0.0, 0.0] == [-0.0, 0.0] or similar.
     650          236 :     r = range_true (type);
     651              :   else
     652              :     {
     653              :       // If ranges do not intersect, we know the range is not equal,
     654              :       // otherwise we don't know anything for sure.
     655       191469 :       frange tmp = op1;
     656       191469 :       tmp.intersect (op2);
     657       191469 :       if (tmp.undefined_p ())
     658              :         {
     659              :           // If one range is [whatever, -0.0] and another
     660              :           // [0.0, whatever2], we don't know anything either,
     661              :           // because -0.0 == 0.0.
     662          616 :           if ((real_iszero (&op1.upper_bound ())
     663           49 :                && real_iszero (&op2.lower_bound ()))
     664          619 :               || (real_iszero (&op1.lower_bound ())
     665           37 :                   && real_iszero (&op2.upper_bound ())))
     666           46 :             r = range_true_and_false (type);
     667              :           else
     668          570 :             r = range_false (type);
     669              :         }
     670              :       else
     671       190853 :         r = range_true_and_false (type);
     672       191469 :     }
     673              :   return true;
     674              : }
     675              : 
     676              : bool
     677       149892 : operator_equal::op1_range (frange &r, tree type,
     678              :                            const irange &lhs,
     679              :                            const frange &op2,
     680              :                            relation_trio trio) const
     681              : {
     682       149892 :   relation_kind rel = trio.op1_op2 ();
     683       149892 :   switch (get_bool_state (r, lhs, type))
     684              :     {
     685        44781 :     case BRS_TRUE:
     686              :       // The TRUE side of x == NAN is unreachable.
     687        44781 :       if (op2.known_isnan ())
     688            0 :         r.set_undefined ();
     689              :       else
     690              :         {
     691              :           // If it's true, the result is the same as OP2.
     692        44781 :           r = op2;
     693              :           // Add both zeros if there's the possibility of zero equality.
     694        44781 :           frange_add_zeros (r, type);
     695              :           // The TRUE side of op1 == op2 implies op1 is !NAN.
     696        44781 :           r.clear_nan ();
     697              :         }
     698              :       break;
     699              : 
     700       103393 :     case BRS_FALSE:
     701              :       // The FALSE side of op1 == op1 implies op1 is a NAN.
     702       103393 :       if (rel == VREL_EQ)
     703         2892 :         r.set_nan (type);
     704              :       // On the FALSE side of x == NAN, we know nothing about x.
     705       100501 :       else if (op2.known_isnan ())
     706            2 :         r.set_varying (type);
     707              :       // If the result is false, the only time we know anything is
     708              :       // if OP2 is a constant.
     709       100499 :       else if (op2.singleton_p ()
     710       109343 :                || (!op2.maybe_isnan () && op2.zero_p ()))
     711              :         {
     712        62793 :           REAL_VALUE_TYPE tmp = op2.lower_bound ();
     713        62793 :           r.set (type, tmp, tmp, VR_ANTI_RANGE);
     714              :         }
     715              :       else
     716        37706 :         r.set_varying (type);
     717              :       break;
     718              : 
     719              :     default:
     720              :       break;
     721              :     }
     722       149892 :   return true;
     723              : }
     724              : 
     725              : // Check if the LHS range indicates a relation between OP1 and OP2.
     726              : 
     727              : relation_kind
     728       151397 : operator_equal::op1_op2_relation (const irange &lhs, const frange &,
     729              :                                   const frange &) const
     730              : {
     731       151397 :   if (lhs.undefined_p ())
     732              :     return VREL_UNDEFINED;
     733              : 
     734              :   // FALSE = op1 == op2 indicates NE_EXPR.
     735       151397 :   if (lhs.zero_p ())
     736              :     return VREL_NE;
     737              : 
     738              :   // TRUE = op1 == op2 indicates EQ_EXPR.
     739        78473 :   if (!contains_zero_p (lhs))
     740        76939 :     return VREL_EQ;
     741              :   return VREL_VARYING;
     742              : }
     743              : 
     744              : bool
     745       855615 : operator_not_equal::fold_range (irange &r, tree type,
     746              :                                 const frange &op1, const frange &op2,
     747              :                                 relation_trio trio) const
     748              : {
     749       855615 :   relation_kind rel = trio.op1_op2 ();
     750              : 
     751              :   // VREL_NE & NE_EXPR is always true, even with NANs.
     752       855615 :   if (rel == VREL_NE)
     753              :     {
     754           26 :       r = range_true (type);
     755           26 :       return true;
     756              :     }
     757       855589 :   if (rel == VREL_EQ && maybe_isnan (op1, op2))
     758              :     {
     759              :       // Avoid frelop_early_resolve() below as it could fold to FALSE
     760              :       // without regards to NANs.  This would be incorrect if trying
     761              :       // to fold x_5 != x_5 without prior knowledge of NANs.
     762              :       // Still, if either operand is undefined, return VARYING.
     763        27486 :       if (empty_range_varying (r, type, op1, op2))
     764            5 :         return true;
     765              :     }
     766       828103 :   else if (frelop_early_resolve (r, type, op1, op2, trio, VREL_NE))
     767              :     return true;
     768              : 
     769              :   // x != NAN is always TRUE.
     770       854094 :   if (op1.known_isnan () || op2.known_isnan ())
     771         1263 :     r = range_true (type);
     772              :   // We can be sure the values are always equal or not if both ranges
     773              :   // consist of a single value, and then compare them.
     774       852831 :   else if (op1.singleton_p () && op2.singleton_p ())
     775              :     {
     776          995 :       if (op1 == op2)
     777          663 :         r = range_false (type);
     778              :       // If one operand is -0.0 and other 0.0, they are still equal.
     779          332 :       else if (real_iszero (&op1.lower_bound ())
     780          332 :                && real_iszero (&op2.lower_bound ()))
     781            0 :         r = range_false (type);
     782              :       else
     783          332 :         r = range_true (type);
     784              :     }
     785       851836 :   else if (real_iszero (&op1.lower_bound ())
     786         7075 :            && real_iszero (&op1.upper_bound ())
     787          365 :            && real_iszero (&op2.lower_bound ())
     788          186 :            && real_iszero (&op2.upper_bound ())
     789       852022 :            && !maybe_isnan (op1, op2))
     790              :     // [-0.0, 0.0] != [-0.0, 0.0] or similar.
     791           98 :     r = range_false (type);
     792              :   else
     793              :     {
     794              :       // If ranges do not intersect, we know the range is not equal,
     795              :       // otherwise we don't know anything for sure.
     796       851738 :       frange tmp = op1;
     797       851738 :       tmp.intersect (op2);
     798       851738 :       if (tmp.undefined_p ())
     799              :         {
     800              :           // If one range is [whatever, -0.0] and another
     801              :           // [0.0, whatever2], we don't know anything either,
     802              :           // because -0.0 == 0.0.
     803          536 :           if ((real_iszero (&op1.upper_bound ())
     804            5 :                && real_iszero (&op2.lower_bound ()))
     805          541 :               || (real_iszero (&op1.lower_bound ())
     806           10 :                   && real_iszero (&op2.upper_bound ())))
     807            0 :             r = range_true_and_false (type);
     808              :           else
     809          536 :             r = range_true (type);
     810              :         }
     811              :       else
     812       851202 :         r = range_true_and_false (type);
     813       851738 :     }
     814              :   return true;
     815              : }
     816              : 
     817              : bool
     818       286518 : operator_not_equal::op1_range (frange &r, tree type,
     819              :                                const irange &lhs,
     820              :                                const frange &op2,
     821              :                                relation_trio trio) const
     822              : {
     823       286518 :   relation_kind rel = trio.op1_op2 ();
     824       286518 :   switch (get_bool_state (r, lhs, type))
     825              :     {
     826        48531 :     case BRS_TRUE:
     827              :       // If the result is true, the only time we know anything is if
     828              :       // OP2 is a constant.
     829        48531 :       if (op2.singleton_p ())
     830              :         {
     831              :           // This is correct even if op1 is NAN, because the following
     832              :           // range would be ~[tmp, tmp] with the NAN property set to
     833              :           // maybe (VARYING).
     834        23601 :           REAL_VALUE_TYPE tmp = op2.lower_bound ();
     835        23601 :           r.set (type, tmp, tmp, VR_ANTI_RANGE);
     836              :         }
     837              :       // The TRUE side of op1 != op1 implies op1 is NAN.
     838        24930 :       else if (rel == VREL_EQ)
     839         6007 :         r.set_nan (type);
     840              :       else
     841        18923 :         r.set_varying (type);
     842              :       break;
     843              : 
     844       236405 :     case BRS_FALSE:
     845              :       // The FALSE side of x != NAN is impossible.
     846       236405 :       if (op2.known_isnan ())
     847          170 :         r.set_undefined ();
     848              :       else
     849              :         {
     850              :           // If it's false, the result is the same as OP2.
     851       236235 :           r = op2;
     852              :           // Add both zeros if there's the possibility of zero equality.
     853       236235 :           frange_add_zeros (r, type);
     854              :           // The FALSE side of op1 != op2 implies op1 is !NAN.
     855       236235 :           r.clear_nan ();
     856              :         }
     857              :       break;
     858              : 
     859              :     default:
     860              :       break;
     861              :     }
     862       286518 :   return true;
     863              : }
     864              : 
     865              : bool
     866       183908 : operator_not_equal::op2_range (frange &r, tree type,
     867              :                                const irange &lhs,
     868              :                                const frange &op1,
     869              :                                relation_trio trio) const
     870              : {
     871       183908 :   return op1_range (r, type, lhs, op1, trio);
     872              : }
     873              : 
     874              : // Check if the LHS range indicates a relation between OP1 and OP2.
     875              : 
     876              : relation_kind
     877       636220 : operator_not_equal::op1_op2_relation (const irange &lhs, const frange &,
     878              :                                       const frange &) const
     879              : {
     880       636220 :   if (lhs.undefined_p ())
     881              :     return VREL_UNDEFINED;
     882              : 
     883              :   // FALSE = op1 != op2  indicates EQ_EXPR.
     884       636220 :   if (lhs.zero_p ())
     885              :     return VREL_EQ;
     886              : 
     887              :   // TRUE = op1 != op2  indicates NE_EXPR.
     888       117503 :   if (!contains_zero_p (lhs))
     889       115950 :     return VREL_NE;
     890              :   return VREL_VARYING;
     891              : }
     892              : 
     893              : bool
     894       274871 : operator_lt::fold_range (irange &r, tree type,
     895              :                          const frange &op1, const frange &op2,
     896              :                          relation_trio trio) const
     897              : {
     898       274871 :   if (frelop_early_resolve (r, type, op1, op2, trio, VREL_LT))
     899              :     return true;
     900              : 
     901       274305 :   if (op1.known_isnan ()
     902       273874 :       || op2.known_isnan ()
     903       547917 :       || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
     904         2818 :     r = range_false (type);
     905       271487 :   else if (!maybe_isnan (op1, op2)
     906       271487 :            && real_less (&op1.upper_bound (), &op2.lower_bound ()))
     907         1115 :     r = range_true (type);
     908              :   else
     909       270372 :     r = range_true_and_false (type);
     910              :   return true;
     911              : }
     912              : 
     913              : bool
     914       436335 : operator_lt::op1_range (frange &r,
     915              :                         tree type,
     916              :                         const irange &lhs,
     917              :                         const frange &op2,
     918              :                         relation_trio) const
     919              : {
     920       436335 :   switch (get_bool_state (r, lhs, type))
     921              :     {
     922       148571 :     case BRS_TRUE:
     923              :       // The TRUE side of x < NAN is unreachable.
     924       148571 :       if (op2.known_isnan ())
     925           68 :         r.set_undefined ();
     926       148503 :       else if (op2.undefined_p ())
     927              :         return false;
     928       148503 :       else if (build_lt (r, type, op2))
     929              :         {
     930       148503 :           r.clear_nan ();
     931              :           // x < y implies x is not +INF.
     932       148503 :           frange_drop_inf (r, type);
     933              :         }
     934              :       break;
     935              : 
     936       287190 :     case BRS_FALSE:
     937              :       // On the FALSE side of x < NAN, we know nothing about x.
     938       544699 :       if (op2.maybe_isnan ())
     939        29681 :         r.set_varying (type);
     940              :       else
     941       257509 :         build_ge (r, type, op2);
     942              :       break;
     943              : 
     944              :     default:
     945              :       break;
     946              :     }
     947              :   return true;
     948              : }
     949              : 
     950              : bool
     951        64176 : operator_lt::op2_range (frange &r,
     952              :                         tree type,
     953              :                         const irange &lhs,
     954              :                         const frange &op1,
     955              :                         relation_trio) const
     956              : {
     957        64176 :   switch (get_bool_state (r, lhs, type))
     958              :     {
     959        26219 :     case BRS_TRUE:
     960              :       // The TRUE side of NAN < x is unreachable.
     961        26219 :       if (op1.known_isnan ())
     962           22 :         r.set_undefined ();
     963        26197 :       else if (op1.undefined_p ())
     964              :         return false;
     965        26197 :       else if (build_gt (r, type, op1))
     966              :         {
     967        26197 :           r.clear_nan ();
     968              :           // x < y implies y is not -INF.
     969        26197 :           frange_drop_ninf (r, type);
     970              :         }
     971              :       break;
     972              : 
     973        37572 :     case BRS_FALSE:
     974              :       // On the FALSE side of NAN < x, we know nothing about x.
     975        41209 :       if (op1.maybe_isnan ())
     976        33935 :         r.set_varying (type);
     977              :       else
     978         3637 :         build_le (r, type, op1);
     979              :       break;
     980              : 
     981              :     default:
     982              :       break;
     983              :     }
     984              :   return true;
     985              : }
     986              : 
     987              : 
     988              : // Check if the LHS range indicates a relation between OP1 and OP2.
     989              : 
     990              : relation_kind
     991       247546 : operator_lt::op1_op2_relation (const irange &lhs, const frange &,
     992              :                                const frange &) const
     993              : {
     994       247546 :   if (lhs.undefined_p ())
     995              :     return VREL_UNDEFINED;
     996              : 
     997              :   // FALSE = op1 < op2 indicates GE_EXPR.
     998       247546 :   if (lhs.zero_p ())
     999              :     return VREL_GE;
    1000              : 
    1001              :   // TRUE = op1 < op2 indicates LT_EXPR.
    1002       113284 :   if (!contains_zero_p (lhs))
    1003       112544 :     return VREL_LT;
    1004              :   return VREL_VARYING;
    1005              : }
    1006              : 
    1007              : bool
    1008       275545 : operator_le::fold_range (irange &r, tree type,
    1009              :                          const frange &op1, const frange &op2,
    1010              :                          relation_trio rel) const
    1011              : {
    1012       275545 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
    1013              :     return true;
    1014              : 
    1015       274960 :   if (op1.known_isnan ()
    1016       273960 :       || op2.known_isnan ()
    1017       548882 :       || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1018         2453 :     r = range_false (type);
    1019       272507 :   else if (!maybe_isnan (op1, op2)
    1020       272507 :            && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1021          791 :     r = range_true (type);
    1022              :   else
    1023       271716 :     r = range_true_and_false (type);
    1024              :   return true;
    1025              : }
    1026              : 
    1027              : bool
    1028        97675 : operator_le::op1_range (frange &r,
    1029              :                         tree type,
    1030              :                         const irange &lhs,
    1031              :                         const frange &op2,
    1032              :                         relation_trio) const
    1033              : {
    1034        97675 :   switch (get_bool_state (r, lhs, type))
    1035              :     {
    1036        67527 :     case BRS_TRUE:
    1037              :       // The TRUE side of x <= NAN is unreachable.
    1038        67527 :       if (op2.known_isnan ())
    1039            0 :         r.set_undefined ();
    1040        67527 :       else if (op2.undefined_p ())
    1041              :         return false;
    1042        67527 :       else if (build_le (r, type, op2))
    1043        67527 :         r.clear_nan ();
    1044              :       break;
    1045              : 
    1046        29812 :     case BRS_FALSE:
    1047              :       // On the FALSE side of x <= NAN, we know nothing about x.
    1048        54974 :       if (op2.maybe_isnan ())
    1049         4650 :         r.set_varying (type);
    1050              :       else
    1051        25162 :         build_gt (r, type, op2);
    1052              :       break;
    1053              : 
    1054              :     default:
    1055              :       break;
    1056              :     }
    1057              :   return true;
    1058              : }
    1059              : 
    1060              : bool
    1061        14748 : operator_le::op2_range (frange &r,
    1062              :                         tree type,
    1063              :                         const irange &lhs,
    1064              :                         const frange &op1,
    1065              :                         relation_trio) const
    1066              : {
    1067        14748 :   switch (get_bool_state (r, lhs, type))
    1068              :     {
    1069         3983 :     case BRS_TRUE:
    1070              :       // The TRUE side of NAN <= x is unreachable.
    1071         3983 :       if (op1.known_isnan ())
    1072            0 :         r.set_undefined ();
    1073         3983 :       else if (op1.undefined_p ())
    1074              :         return false;
    1075         3983 :       else if (build_ge (r, type, op1))
    1076         3983 :         r.clear_nan ();
    1077              :       break;
    1078              : 
    1079        10468 :     case BRS_FALSE:
    1080              :       // On the FALSE side of NAN <= x, we know nothing about x.
    1081        11256 :       if (op1.maybe_isnan ())
    1082         9680 :         r.set_varying (type);
    1083          788 :       else if (op1.undefined_p ())
    1084              :         return false;
    1085              :       else
    1086          788 :         build_lt (r, type, op1);
    1087              :       break;
    1088              : 
    1089              :     default:
    1090              :       break;
    1091              :     }
    1092              :   return true;
    1093              : }
    1094              : 
    1095              : // Check if the LHS range indicates a relation between OP1 and OP2.
    1096              : 
    1097              : relation_kind
    1098        60955 : operator_le::op1_op2_relation (const irange &lhs, const frange &,
    1099              :                                const frange &) const
    1100              : {
    1101        60955 :   if (lhs.undefined_p ())
    1102              :     return VREL_UNDEFINED;
    1103              : 
    1104              :   // FALSE = op1 <= op2 indicates GT_EXPR.
    1105        60955 :   if (lhs.zero_p ())
    1106              :     return VREL_GT;
    1107              : 
    1108              :   // TRUE = op1 <= op2 indicates LE_EXPR.
    1109        30732 :   if (!contains_zero_p (lhs))
    1110        30134 :     return VREL_LE;
    1111              :   return VREL_VARYING;
    1112              : }
    1113              : 
    1114              : bool
    1115       273299 : operator_gt::fold_range (irange &r, tree type,
    1116              :                          const frange &op1, const frange &op2,
    1117              :                          relation_trio trio) const
    1118              : {
    1119       273299 :   if (frelop_early_resolve (r, type, op1, op2, trio, VREL_GT))
    1120              :     return true;
    1121              : 
    1122       272522 :   if (op1.known_isnan ()
    1123       272123 :       || op2.known_isnan ()
    1124       544315 :       || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1125         4068 :     r = range_false (type);
    1126       268454 :   else if (!maybe_isnan (op1, op2)
    1127       268454 :            && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1128          732 :     r = range_true (type);
    1129              :   else
    1130       267722 :     r = range_true_and_false (type);
    1131              :   return true;
    1132              : }
    1133              : 
    1134              : bool
    1135       170838 : operator_gt::op1_range (frange &r,
    1136              :                         tree type,
    1137              :                         const irange &lhs,
    1138              :                         const frange &op2,
    1139              :                         relation_trio) const
    1140              : {
    1141       170838 :   switch (get_bool_state (r, lhs, type))
    1142              :     {
    1143        65212 :     case BRS_TRUE:
    1144              :       // The TRUE side of x > NAN is unreachable.
    1145        65212 :       if (op2.known_isnan ())
    1146           28 :         r.set_undefined ();
    1147        65184 :       else if (op2.undefined_p ())
    1148              :         return false;
    1149        65184 :       else if (build_gt (r, type, op2))
    1150              :         {
    1151        65184 :           r.clear_nan ();
    1152              :           // x > y implies x is not -INF.
    1153        65184 :           frange_drop_ninf (r, type);
    1154              :         }
    1155              :       break;
    1156              : 
    1157       104901 :     case BRS_FALSE:
    1158              :       // On the FALSE side of x > NAN, we know nothing about x.
    1159       180394 :       if (op2.maybe_isnan ())
    1160        29408 :         r.set_varying (type);
    1161        75493 :       else if (op2.undefined_p ())
    1162              :         return false;
    1163              :       else
    1164        75493 :         build_le (r, type, op2);
    1165              :       break;
    1166              : 
    1167              :     default:
    1168              :       break;
    1169              :     }
    1170              :   return true;
    1171              : }
    1172              : 
    1173              : bool
    1174        72396 : operator_gt::op2_range (frange &r,
    1175              :                         tree type,
    1176              :                         const irange &lhs,
    1177              :                         const frange &op1,
    1178              :                         relation_trio) const
    1179              : {
    1180        72396 :   switch (get_bool_state (r, lhs, type))
    1181              :     {
    1182        28551 :     case BRS_TRUE:
    1183              :       // The TRUE side of NAN > x is unreachable.
    1184        28551 :       if (op1.known_isnan ())
    1185           22 :         r.set_undefined ();
    1186        28529 :       else if (op1.undefined_p ())
    1187              :         return false;
    1188        28529 :       else if (build_lt (r, type, op1))
    1189              :         {
    1190        28529 :           r.clear_nan ();
    1191              :           // x > y implies y is not +INF.
    1192        28529 :           frange_drop_inf (r, type);
    1193              :         }
    1194              :       break;
    1195              : 
    1196        43438 :     case BRS_FALSE:
    1197              :       // On The FALSE side of NAN > x, we know nothing about x.
    1198        46744 :       if (op1.maybe_isnan ())
    1199        40132 :         r.set_varying (type);
    1200         3306 :       else if (op1.undefined_p ())
    1201              :         return false;
    1202              :       else
    1203         3306 :         build_ge (r, type, op1);
    1204              :       break;
    1205              : 
    1206              :     default:
    1207              :       break;
    1208              :     }
    1209              :   return true;
    1210              : }
    1211              : 
    1212              : // Check if the LHS range indicates a relation between OP1 and OP2.
    1213              : 
    1214              : relation_kind
    1215       270577 : operator_gt::op1_op2_relation (const irange &lhs, const frange &,
    1216              :                                const frange &) const
    1217              : {
    1218       270577 :   if (lhs.undefined_p ())
    1219              :     return VREL_UNDEFINED;
    1220              : 
    1221              :   // FALSE = op1 > op2 indicates LE_EXPR.
    1222       270577 :   if (lhs.zero_p ())
    1223              :     return VREL_LE;
    1224              : 
    1225              :   // TRUE = op1 > op2 indicates GT_EXPR.
    1226       121161 :   if (!contains_zero_p (lhs))
    1227       120311 :     return VREL_GT;
    1228              :   return VREL_VARYING;
    1229              : }
    1230              : 
    1231              : bool
    1232       269500 : operator_ge::fold_range (irange &r, tree type,
    1233              :                          const frange &op1, const frange &op2,
    1234              :                          relation_trio rel) const
    1235              : {
    1236       269500 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
    1237              :     return true;
    1238              : 
    1239       269109 :   if (op1.known_isnan ()
    1240       268293 :       || op2.known_isnan ()
    1241       537360 :       || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1242         1501 :     r = range_false (type);
    1243       267608 :   else if (!maybe_isnan (op1, op2)
    1244       267608 :            && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1245         2460 :     r = range_true (type);
    1246              :   else
    1247       265148 :     r = range_true_and_false (type);
    1248              :   return true;
    1249              : }
    1250              : 
    1251              : bool
    1252       107242 : operator_ge::op1_range (frange &r,
    1253              :                         tree type,
    1254              :                         const irange &lhs,
    1255              :                         const frange &op2,
    1256              :                         relation_trio) const
    1257              : {
    1258       107242 :   switch (get_bool_state (r, lhs, type))
    1259              :     {
    1260        59777 :     case BRS_TRUE:
    1261              :       // The TRUE side of x >= NAN is unreachable.
    1262        59777 :       if (op2.known_isnan ())
    1263            0 :         r.set_undefined ();
    1264        59777 :       else if (op2.undefined_p ())
    1265              :         return false;
    1266        59777 :       else if (build_ge (r, type, op2))
    1267        59777 :         r.clear_nan ();
    1268              :       break;
    1269              : 
    1270        47168 :     case BRS_FALSE:
    1271              :       // On the FALSE side of x >= NAN, we know nothing about x.
    1272        88096 :       if (op2.maybe_isnan ())
    1273         6240 :         r.set_varying (type);
    1274        40928 :       else if (op2.undefined_p ())
    1275              :         return false;
    1276              :       else
    1277        40928 :         build_lt (r, type, op2);
    1278              :       break;
    1279              : 
    1280              :     default:
    1281              :       break;
    1282              :     }
    1283              :   return true;
    1284              : }
    1285              : 
    1286              : bool
    1287        12828 : operator_ge::op2_range (frange &r, tree type,
    1288              :                         const irange &lhs,
    1289              :                         const frange &op1,
    1290              :                         relation_trio) const
    1291              : {
    1292        12828 :   switch (get_bool_state (r, lhs, type))
    1293              :     {
    1294         5352 :     case BRS_TRUE:
    1295              :       // The TRUE side of NAN >= x is unreachable.
    1296         5352 :       if (op1.known_isnan ())
    1297            0 :         r.set_undefined ();
    1298         5352 :       else if (op1.undefined_p ())
    1299              :         return false;
    1300         5352 :       else if (build_le (r, type, op1))
    1301         5352 :         r.clear_nan ();
    1302              :       break;
    1303              : 
    1304         7215 :     case BRS_FALSE:
    1305              :       // On the FALSE side of NAN >= x, we know nothing about x.
    1306         7868 :       if (op1.maybe_isnan ())
    1307         6562 :         r.set_varying (type);
    1308          653 :       else if (op1.undefined_p ())
    1309              :         return false;
    1310              :       else
    1311          653 :         build_gt (r, type, op1);
    1312              :       break;
    1313              : 
    1314              :     default:
    1315              :       break;
    1316              :     }
    1317              :   return true;
    1318              : }
    1319              : 
    1320              : // Check if the LHS range indicates a relation between OP1 and OP2.
    1321              : 
    1322              : relation_kind
    1323        56566 : operator_ge::op1_op2_relation (const irange &lhs, const frange &,
    1324              :                                const frange &) const
    1325              : {
    1326        56566 :   if (lhs.undefined_p ())
    1327              :     return VREL_UNDEFINED;
    1328              : 
    1329              :   // FALSE = op1 >= op2 indicates LT_EXPR.
    1330        56566 :   if (lhs.zero_p ())
    1331              :     return VREL_LT;
    1332              : 
    1333              :   // TRUE = op1 >= op2 indicates GE_EXPR.
    1334        30103 :   if (!contains_zero_p (lhs))
    1335        29577 :     return VREL_GE;
    1336              :   return VREL_VARYING;
    1337              : }
    1338              : 
    1339              : // UNORDERED_EXPR comparison.
    1340              : 
    1341              : class foperator_unordered : public range_operator
    1342              : {
    1343              :   using range_operator::fold_range;
    1344              :   using range_operator::op1_range;
    1345              :   using range_operator::op2_range;
    1346              : public:
    1347              :   bool fold_range (irange &r, tree type,
    1348              :                    const frange &op1, const frange &op2,
    1349              :                    relation_trio = TRIO_VARYING) const final override;
    1350              :   bool op1_range (frange &r, tree type,
    1351              :                   const irange &lhs, const frange &op2,
    1352              :                   relation_trio = TRIO_VARYING) const final override;
    1353        58140 :   bool op2_range (frange &r, tree type,
    1354              :                   const irange &lhs, const frange &op1,
    1355              :                   relation_trio rel = TRIO_VARYING) const final override
    1356              :   {
    1357        58140 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    1358              :   }
    1359              : };
    1360              : static const foperator_unordered fop_unordered;
    1361              : 
    1362              : bool
    1363        62365 : foperator_unordered::fold_range (irange &r, tree type,
    1364              :                                  const frange &op1, const frange &op2,
    1365              :                                  relation_trio) const
    1366              : {
    1367              :   // UNORDERED is TRUE if either operand is a NAN.
    1368        62365 :   if (op1.known_isnan () || op2.known_isnan ())
    1369          219 :     r = range_true (type);
    1370              :   // UNORDERED is FALSE if neither operand is a NAN.
    1371        64770 :   else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
    1372         1314 :     r = range_false (type);
    1373              :   else
    1374        60832 :     r = range_true_and_false (type);
    1375        62365 :   return true;
    1376              : }
    1377              : 
    1378              : bool
    1379       108867 : foperator_unordered::op1_range (frange &r, tree type,
    1380              :                                 const irange &lhs,
    1381              :                                 const frange &op2,
    1382              :                                 relation_trio trio) const
    1383              : {
    1384       108867 :   relation_kind rel = trio.op1_op2 ();
    1385       108867 :   switch (get_bool_state (r, lhs, type))
    1386              :     {
    1387        40104 :     case BRS_TRUE:
    1388              :       // Since at least one operand must be NAN, if one of them is
    1389              :       // not, the other must be.
    1390        40104 :       if (rel == VREL_EQ || !op2.maybe_isnan ())
    1391        10885 :         r.set_nan (type);
    1392              :       else
    1393        29219 :         r.set_varying (type);
    1394              :       break;
    1395              : 
    1396        61274 :     case BRS_FALSE:
    1397              :       // A false UNORDERED means both operands are !NAN, so it's
    1398              :       // impossible for op2 to be a NAN.
    1399        61274 :       if (op2.known_isnan ())
    1400            0 :         r.set_undefined ();
    1401              :       else
    1402              :         {
    1403        61274 :           r.set_varying (type);
    1404        61274 :           r.clear_nan ();
    1405              :         }
    1406              :       break;
    1407              : 
    1408              :     default:
    1409              :       break;
    1410              :     }
    1411       108867 :   return true;
    1412              : }
    1413              : 
    1414              : // ORDERED_EXPR comparison.
    1415              : 
    1416              : class foperator_ordered : public range_operator
    1417              : {
    1418              :   using range_operator::fold_range;
    1419              :   using range_operator::op1_range;
    1420              :   using range_operator::op2_range;
    1421              : public:
    1422              :   bool fold_range (irange &r, tree type,
    1423              :                    const frange &op1, const frange &op2,
    1424              :                    relation_trio = TRIO_VARYING) const final override;
    1425              :   bool op1_range (frange &r, tree type,
    1426              :                   const irange &lhs, const frange &op2,
    1427              :                   relation_trio = TRIO_VARYING) const final override;
    1428        29463 :   bool op2_range (frange &r, tree type,
    1429              :                   const irange &lhs, const frange &op1,
    1430              :                   relation_trio rel = TRIO_VARYING) const final override
    1431              :   {
    1432        29463 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    1433              :   }
    1434              : };
    1435              : static const foperator_ordered fop_ordered;
    1436              : 
    1437              : bool
    1438        33314 : foperator_ordered::fold_range (irange &r, tree type,
    1439              :                                const frange &op1, const frange &op2,
    1440              :                                relation_trio) const
    1441              : {
    1442        33314 :   if (op1.known_isnan () || op2.known_isnan ())
    1443          360 :     r = range_false (type);
    1444        35852 :   else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
    1445         1442 :     r = range_true (type);
    1446              :   else
    1447        31512 :     r = range_true_and_false (type);
    1448        33314 :   return true;
    1449              : }
    1450              : 
    1451              : bool
    1452        62921 : foperator_ordered::op1_range (frange &r, tree type,
    1453              :                               const irange &lhs,
    1454              :                               const frange &op2,
    1455              :                               relation_trio trio) const
    1456              : {
    1457        62921 :   relation_kind rel = trio.op1_op2 ();
    1458        62921 :   switch (get_bool_state (r, lhs, type))
    1459              :     {
    1460        56524 :     case BRS_TRUE:
    1461              :       // The TRUE side of ORDERED means both operands are !NAN, so
    1462              :       // it's impossible for op2 to be a NAN.
    1463        56524 :       if (op2.known_isnan ())
    1464           10 :         r.set_undefined ();
    1465              :       else
    1466              :         {
    1467        56514 :           r.set_varying (type);
    1468        56514 :           r.clear_nan ();
    1469              :         }
    1470              :       break;
    1471              : 
    1472         4606 :     case BRS_FALSE:
    1473              :       // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
    1474         4606 :       if (rel == VREL_EQ)
    1475         2103 :         r.set_nan (type);
    1476              :       else
    1477         2503 :         r.set_varying (type);
    1478              :       break;
    1479              : 
    1480              :     default:
    1481              :       break;
    1482              :     }
    1483        62921 :   return true;
    1484              : }
    1485              : 
    1486              : bool
    1487       244334 : operator_negate::fold_range (frange &r, tree type,
    1488              :                              const frange &op1, const frange &op2,
    1489              :                              relation_trio) const
    1490              : {
    1491       244334 :   if (empty_range_varying (r, type, op1, op2))
    1492          429 :     return true;
    1493       243905 :   if (op1.known_isnan ())
    1494              :     {
    1495          418 :       bool sign;
    1496          418 :       if (op1.nan_signbit_p (sign))
    1497           38 :         r.set_nan (type, !sign);
    1498              :       else
    1499          380 :         r.set_nan (type);
    1500          418 :       return true;
    1501              :     }
    1502              : 
    1503       243487 :   REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
    1504       243487 :   REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
    1505       243487 :   lh_lb = real_value_negate (&lh_lb);
    1506       243487 :   lh_ub = real_value_negate (&lh_ub);
    1507       243487 :   r.set (type, lh_ub, lh_lb);
    1508       433617 :   if (op1.maybe_isnan ())
    1509              :     {
    1510        53361 :       bool sign;
    1511        53361 :       if (op1.nan_signbit_p (sign))
    1512         2490 :         r.update_nan (!sign);
    1513              :       else
    1514        50871 :         r.update_nan ();
    1515              :     }
    1516              :   else
    1517       190126 :     r.clear_nan ();
    1518              :   return true;
    1519              : }
    1520              : 
    1521              : bool
    1522         3288 : operator_negate::op1_range (frange &r, tree type,
    1523              :                             const frange &lhs, const frange &op2,
    1524              :                             relation_trio rel) const
    1525              : {
    1526         3288 :   return fold_range (r, type, lhs, op2, rel);
    1527              : }
    1528              : 
    1529              : bool
    1530       586788 : operator_abs::fold_range (frange &r, tree type,
    1531              :                           const frange &op1, const frange &op2,
    1532              :                           relation_trio) const
    1533              : {
    1534       586788 :   if (empty_range_varying (r, type, op1, op2))
    1535          114 :     return true;
    1536       586674 :   if (op1.known_isnan ())
    1537              :     {
    1538          590 :       r.set_nan (type, /*sign=*/false);
    1539          590 :       return true;
    1540              :     }
    1541              : 
    1542       586084 :   const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
    1543       586084 :   const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
    1544              :   // Handle the easy case where everything is positive.
    1545       586084 :   if (real_compare (GE_EXPR, &lh_lb, &dconst0)
    1546       159952 :       && !real_iszero (&lh_lb, /*sign=*/true)
    1547       743377 :       && !op1.maybe_isnan (/*sign=*/true))
    1548              :     {
    1549       156928 :       r = op1;
    1550       156928 :       return true;
    1551              :     }
    1552              : 
    1553       429156 :   REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
    1554       429156 :   REAL_VALUE_TYPE max = real_value_abs (&lh_ub);
    1555              :   // If the range contains zero then we know that the minimum value in the
    1556              :   // range will be zero.
    1557       429156 :   if (real_compare (LE_EXPR, &lh_lb, &dconst0)
    1558       429156 :       && real_compare (GE_EXPR, &lh_ub, &dconst0))
    1559              :     {
    1560       428280 :       if (real_compare (GT_EXPR, &min, &max))
    1561         5139 :         max = min;
    1562       428280 :       min = dconst0;
    1563              :     }
    1564              :   else
    1565              :     {
    1566              :       // If the range was reversed, swap MIN and MAX.
    1567          876 :       if (real_compare (GT_EXPR, &min, &max))
    1568          797 :         std::swap (min, max);
    1569              :     }
    1570              : 
    1571       429156 :   r.set (type, min, max);
    1572       454493 :   if (op1.maybe_isnan ())
    1573       405317 :     r.update_nan (/*sign=*/false);
    1574              :   else
    1575        23839 :     r.clear_nan ();
    1576              :   return true;
    1577              : }
    1578              : 
    1579              : bool
    1580       332636 : operator_abs::op1_range (frange &r, tree type,
    1581              :                          const frange &lhs, const frange &op2,
    1582              :                          relation_trio) const
    1583              : {
    1584       332636 :   if (empty_range_varying (r, type, lhs, op2))
    1585            0 :     return true;
    1586       332636 :   if (lhs.known_isnan ())
    1587              :     {
    1588         2630 :       r.set_nan (type);
    1589         2630 :       return true;
    1590              :     }
    1591              : 
    1592              :   // Start with the positives because negatives are an impossible result.
    1593       330006 :   frange positives (type, dconst0, frange_val_max (type));
    1594       330006 :   positives.update_nan (/*sign=*/false);
    1595       330006 :   positives.intersect (lhs);
    1596       330006 :   r = positives;
    1597              :   // Add -NAN if relevant.
    1598       497814 :   if (r.maybe_isnan ())
    1599              :     {
    1600       162138 :       frange neg_nan;
    1601       162138 :       neg_nan.set_nan (type, true);
    1602       162138 :       r.union_ (neg_nan);
    1603       162138 :     }
    1604       330006 :   if (r.known_isnan () || r.undefined_p ())
    1605              :     return true;
    1606              :   // Then add the negative of each pair:
    1607              :   // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
    1608       329934 :   frange negatives (type, real_value_negate (&positives.upper_bound ()),
    1609       329934 :                     real_value_negate (&positives.lower_bound ()));
    1610       329934 :   negatives.clear_nan ();
    1611       329934 :   r.union_ (negatives);
    1612       329934 :   return true;
    1613       659940 : }
    1614              : 
    1615              : class foperator_unordered_lt : public range_operator
    1616              : {
    1617              :   using range_operator::fold_range;
    1618              :   using range_operator::op1_range;
    1619              :   using range_operator::op2_range;
    1620              : public:
    1621        11143 :   bool fold_range (irange &r, tree type,
    1622              :                    const frange &op1, const frange &op2,
    1623              :                    relation_trio trio = TRIO_VARYING) const final override
    1624              :   {
    1625        11143 :     if (op1.known_isnan () || op2.known_isnan ())
    1626              :       {
    1627           33 :         r = range_true (type);
    1628           33 :         return true;
    1629              :       }
    1630        11110 :     frange op1_no_nan = op1;
    1631        11110 :     frange op2_no_nan = op2;
    1632        13740 :     if (op1.maybe_isnan ())
    1633         8464 :       op1_no_nan.clear_nan ();
    1634        18646 :     if (op2.maybe_isnan ())
    1635         3574 :       op2_no_nan.clear_nan ();
    1636        11110 :     if (!range_op_handler (LT_EXPR).fold_range (r, type, op1_no_nan,
    1637              :                                                 op2_no_nan, trio))
    1638              :       return false;
    1639              :     // The result is the same as the ordered version when the
    1640              :     // comparison is true or when the operands cannot be NANs.
    1641        11110 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1642              :       return true;
    1643              :     else
    1644              :       {
    1645         8360 :         r = range_true_and_false (type);
    1646         8360 :         return true;
    1647              :       }
    1648        11110 :   }
    1649              :   bool op1_range (frange &r, tree type,
    1650              :                   const irange &lhs,
    1651              :                   const frange &op2,
    1652              :                   relation_trio trio) const final override;
    1653              :   bool op2_range (frange &r, tree type,
    1654              :                   const irange &lhs,
    1655              :                   const frange &op1,
    1656              :                   relation_trio trio) const final override;
    1657              : };
    1658              : static const foperator_unordered_lt fop_unordered_lt;
    1659              : 
    1660              : bool
    1661         3332 : foperator_unordered_lt::op1_range (frange &r, tree type,
    1662              :                                    const irange &lhs,
    1663              :                                    const frange &op2,
    1664              :                                    relation_trio) const
    1665              : {
    1666         3332 :   switch (get_bool_state (r, lhs, type))
    1667              :     {
    1668         1468 :     case BRS_TRUE:
    1669         2880 :       if (op2.maybe_isnan ())
    1670           56 :         r.set_varying (type);
    1671         1412 :       else if (op2.undefined_p ())
    1672              :         return false;
    1673              :       else
    1674         1412 :         build_lt (r, type, op2);
    1675              :       break;
    1676              : 
    1677         1236 :     case BRS_FALSE:
    1678              :       // A false UNORDERED_LT means both operands are !NAN, so it's
    1679              :       // impossible for op2 to be a NAN.
    1680         1236 :       if (op2.known_isnan ())
    1681            0 :         r.set_undefined ();
    1682         1236 :       else if (op2.undefined_p ())
    1683              :         return false;
    1684         1236 :       else if (build_ge (r, type, op2))
    1685         1236 :         r.clear_nan ();
    1686              :       break;
    1687              : 
    1688              :     default:
    1689              :       break;
    1690              :     }
    1691              :   return true;
    1692              : }
    1693              : 
    1694              : bool
    1695          684 : foperator_unordered_lt::op2_range (frange &r, tree type,
    1696              :                                    const irange &lhs,
    1697              :                                    const frange &op1,
    1698              :                                    relation_trio) const
    1699              : {
    1700          684 :   switch (get_bool_state (r, lhs, type))
    1701              :     {
    1702           56 :     case BRS_TRUE:
    1703           56 :       if (op1.maybe_isnan ())
    1704           56 :         r.set_varying (type);
    1705            0 :       else if (op1.undefined_p ())
    1706              :         return false;
    1707              :       else
    1708            0 :         build_gt (r, type, op1);
    1709              :       break;
    1710              : 
    1711            0 :     case BRS_FALSE:
    1712              :       // A false UNORDERED_LT means both operands are !NAN, so it's
    1713              :       // impossible for op1 to be a NAN.
    1714            0 :       if (op1.known_isnan ())
    1715            0 :         r.set_undefined ();
    1716            0 :       else if (op1.undefined_p ())
    1717              :         return false;
    1718            0 :       else if (build_le (r, type, op1))
    1719            0 :         r.clear_nan ();
    1720              :       break;
    1721              : 
    1722              :     default:
    1723              :       break;
    1724              :     }
    1725              :   return true;
    1726              : }
    1727              : 
    1728              : class foperator_unordered_le : public range_operator
    1729              : {
    1730              :   using range_operator::fold_range;
    1731              :   using range_operator::op1_range;
    1732              :   using range_operator::op2_range;
    1733              : public:
    1734       183996 :   bool fold_range (irange &r, tree type,
    1735              :                    const frange &op1, const frange &op2,
    1736              :                    relation_trio trio = TRIO_VARYING) const final override
    1737              :   {
    1738       183996 :     if (op1.known_isnan () || op2.known_isnan ())
    1739              :       {
    1740           98 :         r = range_true (type);
    1741           98 :         return true;
    1742              :       }
    1743       183898 :     frange op1_no_nan = op1;
    1744       183898 :     frange op2_no_nan = op2;
    1745       209725 :     if (op1.maybe_isnan ())
    1746       158045 :       op1_no_nan.clear_nan ();
    1747       360612 :     if (op2.maybe_isnan ())
    1748         7178 :       op2_no_nan.clear_nan ();
    1749       183898 :     if (!range_op_handler (LE_EXPR).fold_range (r, type, op1_no_nan,
    1750              :                                                 op2_no_nan, trio))
    1751              :       return false;
    1752              :     // The result is the same as the ordered version when the
    1753              :     // comparison is true or when the operands cannot be NANs.
    1754       183898 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1755              :       return true;
    1756              :     else
    1757              :       {
    1758       159809 :         r = range_true_and_false (type);
    1759       159809 :         return true;
    1760              :       }
    1761       183898 :   }
    1762              :   bool op1_range (frange &r, tree type,
    1763              :                   const irange &lhs, const frange &op2,
    1764              :                   relation_trio = TRIO_VARYING) const final override;
    1765              :   bool op2_range (frange &r, tree type,
    1766              :                   const irange &lhs, const frange &op1,
    1767              :                   relation_trio = TRIO_VARYING) const final override;
    1768              : };
    1769              : static const foperator_unordered_le fop_unordered_le;
    1770              : 
    1771              : bool
    1772       169130 : foperator_unordered_le::op1_range (frange &r, tree type,
    1773              :                                    const irange &lhs, const frange &op2,
    1774              :                                    relation_trio) const
    1775              : {
    1776       169130 :   switch (get_bool_state (r, lhs, type))
    1777              :     {
    1778        93610 :     case BRS_TRUE:
    1779       182103 :       if (op2.maybe_isnan ())
    1780         5117 :         r.set_varying (type);
    1781        88493 :       else if (op2.undefined_p ())
    1782              :         return false;
    1783              :       else
    1784        88493 :         build_le (r, type, op2);
    1785              :       break;
    1786              : 
    1787        74878 :     case BRS_FALSE:
    1788              :       // A false UNORDERED_LE means both operands are !NAN, so it's
    1789              :       // impossible for op2 to be a NAN.
    1790        74878 :       if (op2.known_isnan ())
    1791            0 :         r.set_undefined ();
    1792        74878 :       else if (build_gt (r, type, op2))
    1793        74876 :         r.clear_nan ();
    1794              :       break;
    1795              : 
    1796              :     default:
    1797              :       break;
    1798              :     }
    1799              :   return true;
    1800              : }
    1801              : 
    1802              : bool
    1803        14097 : foperator_unordered_le::op2_range (frange &r,
    1804              :                                    tree type,
    1805              :                                    const irange &lhs,
    1806              :                                    const frange &op1,
    1807              :                                    relation_trio) const
    1808              : {
    1809        14097 :   switch (get_bool_state (r, lhs, type))
    1810              :     {
    1811         9851 :     case BRS_TRUE:
    1812        14857 :       if (op1.maybe_isnan ())
    1813         4845 :         r.set_varying (type);
    1814         5006 :       else if (op1.undefined_p ())
    1815              :         return false;
    1816              :       else
    1817         5006 :         build_ge (r, type, op1);
    1818              :       break;
    1819              : 
    1820         3604 :     case BRS_FALSE:
    1821              :       // A false UNORDERED_LE means both operands are !NAN, so it's
    1822              :       // impossible for op1 to be a NAN.
    1823         3604 :       if (op1.known_isnan ())
    1824            0 :         r.set_undefined ();
    1825         3604 :       else if (op1.undefined_p ())
    1826              :         return false;
    1827         3604 :       else if (build_lt (r, type, op1))
    1828         3604 :         r.clear_nan ();
    1829              :       break;
    1830              : 
    1831              :     default:
    1832              :       break;
    1833              :     }
    1834              :   return true;
    1835              : }
    1836              : 
    1837              : class foperator_unordered_gt : public range_operator
    1838              : {
    1839              :   using range_operator::fold_range;
    1840              :   using range_operator::op1_range;
    1841              :   using range_operator::op2_range;
    1842              : public:
    1843        41908 :   bool fold_range (irange &r, tree type,
    1844              :                    const frange &op1, const frange &op2,
    1845              :                    relation_trio trio = TRIO_VARYING) const final override
    1846              :   {
    1847        41908 :     if (op1.known_isnan () || op2.known_isnan ())
    1848              :       {
    1849          158 :         r = range_true (type);
    1850          158 :         return true;
    1851              :       }
    1852        41750 :     frange op1_no_nan = op1;
    1853        41750 :     frange op2_no_nan = op2;
    1854        45204 :     if (op1.maybe_isnan ())
    1855        38277 :       op1_no_nan.clear_nan ();
    1856        79834 :     if (op2.maybe_isnan ())
    1857         3666 :       op2_no_nan.clear_nan ();
    1858        41750 :     if (!range_op_handler (GT_EXPR).fold_range (r, type, op1_no_nan,
    1859              :                                                 op2_no_nan, trio))
    1860              :       return false;
    1861              :     // The result is the same as the ordered version when the
    1862              :     // comparison is true or when the operands cannot be NANs.
    1863        41750 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1864              :       return true;
    1865              :     else
    1866              :       {
    1867        38169 :         r = range_true_and_false (type);
    1868        38169 :         return true;
    1869              :       }
    1870        41750 :   }
    1871              :   bool op1_range (frange &r, tree type,
    1872              :                   const irange &lhs, const frange &op2,
    1873              :                   relation_trio = TRIO_VARYING) const final override;
    1874              :   bool op2_range (frange &r, tree type,
    1875              :                   const irange &lhs, const frange &op1,
    1876              :                   relation_trio = TRIO_VARYING) const final override;
    1877              : };
    1878              : static const foperator_unordered_gt fop_unordered_gt;
    1879              : 
    1880              : bool
    1881        14359 : foperator_unordered_gt::op1_range (frange &r,
    1882              :                                    tree type,
    1883              :                                    const irange &lhs,
    1884              :                                    const frange &op2,
    1885              :                                    relation_trio) const
    1886              : {
    1887        14359 :   switch (get_bool_state (r, lhs, type))
    1888              :     {
    1889         3995 :     case BRS_TRUE:
    1890         7914 :       if (op2.maybe_isnan ())
    1891           76 :         r.set_varying (type);
    1892         3919 :       else if (op2.undefined_p ())
    1893              :         return false;
    1894              :       else
    1895         3919 :         build_gt (r, type, op2);
    1896              :       break;
    1897              : 
    1898         9766 :     case BRS_FALSE:
    1899              :       // A false UNORDERED_GT means both operands are !NAN, so it's
    1900              :       // impossible for op2 to be a NAN.
    1901         9766 :       if (op2.known_isnan ())
    1902            0 :         r.set_undefined ();
    1903         9766 :       else if (op2.undefined_p ())
    1904              :         return false;
    1905         9766 :       else if (build_le (r, type, op2))
    1906         9766 :         r.clear_nan ();
    1907              :       break;
    1908              : 
    1909              :     default:
    1910              :       break;
    1911              :     }
    1912              :   return true;
    1913              : }
    1914              : 
    1915              : bool
    1916          674 : foperator_unordered_gt::op2_range (frange &r,
    1917              :                                    tree type,
    1918              :                                    const irange &lhs,
    1919              :                                    const frange &op1,
    1920              :                                    relation_trio) const
    1921              : {
    1922          674 :   switch (get_bool_state (r, lhs, type))
    1923              :     {
    1924           76 :     case BRS_TRUE:
    1925           76 :       if (op1.maybe_isnan ())
    1926           76 :         r.set_varying (type);
    1927            0 :       else if (op1.undefined_p ())
    1928              :         return false;
    1929              :       else
    1930            0 :         build_lt (r, type, op1);
    1931              :       break;
    1932              : 
    1933            0 :     case BRS_FALSE:
    1934              :       // A false UNORDERED_GT means both operands are !NAN, so it's
    1935              :       // impossible for op1 to be a NAN.
    1936            0 :       if (op1.known_isnan ())
    1937            0 :         r.set_undefined ();
    1938            0 :       else if (op1.undefined_p ())
    1939              :         return false;
    1940            0 :       else if (build_ge (r, type, op1))
    1941            0 :         r.clear_nan ();
    1942              :       break;
    1943              : 
    1944              :     default:
    1945              :       break;
    1946              :     }
    1947              :   return true;
    1948              : }
    1949              : 
    1950              : class foperator_unordered_ge : public range_operator
    1951              : {
    1952              :   using range_operator::fold_range;
    1953              :   using range_operator::op1_range;
    1954              :   using range_operator::op2_range;
    1955              : public:
    1956       174479 :   bool fold_range (irange &r, tree type,
    1957              :                    const frange &op1, const frange &op2,
    1958              :                    relation_trio trio = TRIO_VARYING) const final override
    1959              :   {
    1960       174479 :     if (op1.known_isnan () || op2.known_isnan ())
    1961              :       {
    1962           45 :         r = range_true (type);
    1963           45 :         return true;
    1964              :       }
    1965       174434 :     frange op1_no_nan = op1;
    1966       174434 :     frange op2_no_nan = op2;
    1967       187921 :     if (op1.maybe_isnan ())
    1968       160886 :       op1_no_nan.clear_nan ();
    1969       341552 :     if (op2.maybe_isnan ())
    1970         7310 :       op2_no_nan.clear_nan ();
    1971       174434 :     if (!range_op_handler (GE_EXPR).fold_range (r, type, op1_no_nan,
    1972              :                                                 op2_no_nan, trio))
    1973              :       return false;
    1974              :     // The result is the same as the ordered version when the
    1975              :     // comparison is true or when the operands cannot be NANs.
    1976       174434 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1977              :       return true;
    1978              :     else
    1979              :       {
    1980       161017 :         r = range_true_and_false (type);
    1981       161017 :         return true;
    1982              :       }
    1983       174434 :   }
    1984              :   bool op1_range (frange &r, tree type,
    1985              :                   const irange &lhs, const frange &op2,
    1986              :                   relation_trio = TRIO_VARYING) const final override;
    1987              :   bool op2_range (frange &r, tree type,
    1988              :                   const irange &lhs, const frange &op1,
    1989              :                   relation_trio = TRIO_VARYING) const final override;
    1990              : };
    1991              : static const foperator_unordered_ge fop_unordered_ge;
    1992              : 
    1993              : bool
    1994       145648 : foperator_unordered_ge::op1_range (frange &r,
    1995              :                                    tree type,
    1996              :                                    const irange &lhs,
    1997              :                                    const frange &op2,
    1998              :                                    relation_trio) const
    1999              : {
    2000       145648 :   switch (get_bool_state (r, lhs, type))
    2001              :     {
    2002        62216 :     case BRS_TRUE:
    2003       119553 :       if (op2.maybe_isnan ())
    2004         4879 :         r.set_varying (type);
    2005        57337 :       else if (op2.undefined_p ())
    2006              :         return false;
    2007              :       else
    2008        57337 :         build_ge (r, type, op2);
    2009              :       break;
    2010              : 
    2011        82728 :     case BRS_FALSE:
    2012              :       // A false UNORDERED_GE means both operands are !NAN, so it's
    2013              :       // impossible for op2 to be a NAN.
    2014        82728 :       if (op2.known_isnan ())
    2015            0 :         r.set_undefined ();
    2016        82728 :       else if (op2.undefined_p ())
    2017              :         return false;
    2018        82728 :       else if (build_lt (r, type, op2))
    2019        82724 :         r.clear_nan ();
    2020              :       break;
    2021              : 
    2022              :     default:
    2023              :       break;
    2024              :     }
    2025              :   return true;
    2026              : }
    2027              : 
    2028              : bool
    2029        15064 : foperator_unordered_ge::op2_range (frange &r, tree type,
    2030              :                                    const irange &lhs,
    2031              :                                    const frange &op1,
    2032              :                                    relation_trio) const
    2033              : {
    2034        15064 :   switch (get_bool_state (r, lhs, type))
    2035              :     {
    2036         9095 :     case BRS_TRUE:
    2037        13469 :       if (op1.maybe_isnan ())
    2038         4721 :         r.set_varying (type);
    2039         4374 :       else if (op1.undefined_p ())
    2040              :         return false;
    2041              :       else
    2042         4374 :         build_le (r, type, op1);
    2043              :       break;
    2044              : 
    2045         5385 :     case BRS_FALSE:
    2046              :       // A false UNORDERED_GE means both operands are !NAN, so it's
    2047              :       // impossible for op1 to be a NAN.
    2048         5385 :       if (op1.known_isnan ())
    2049            0 :         r.set_undefined ();
    2050         5385 :       else if (op1.undefined_p ())
    2051              :         return false;
    2052         5385 :       else if (build_gt (r, type, op1))
    2053         5385 :         r.clear_nan ();
    2054              :       break;
    2055              : 
    2056              :     default:
    2057              :       break;
    2058              :     }
    2059              :   return true;
    2060              : }
    2061              : 
    2062              : class foperator_unordered_equal : public range_operator
    2063              : {
    2064              :   using range_operator::fold_range;
    2065              :   using range_operator::op1_range;
    2066              :   using range_operator::op2_range;
    2067              : public:
    2068         3629 :   bool fold_range (irange &r, tree type,
    2069              :                    const frange &op1, const frange &op2,
    2070              :                    relation_trio trio = TRIO_VARYING) const final override
    2071              :   {
    2072         3629 :     if (op1.known_isnan () || op2.known_isnan ())
    2073              :       {
    2074            0 :         r = range_true (type);
    2075            0 :         return true;
    2076              :       }
    2077         3629 :     frange op1_no_nan = op1;
    2078         3629 :     frange op2_no_nan = op2;
    2079         3949 :     if (op1.maybe_isnan ())
    2080         3309 :       op1_no_nan.clear_nan ();
    2081         4050 :     if (op2.maybe_isnan ())
    2082         3208 :       op2_no_nan.clear_nan ();
    2083         3629 :     if (!range_op_handler (EQ_EXPR).fold_range (r, type, op1_no_nan,
    2084              :                                                 op2_no_nan, trio))
    2085              :       return false;
    2086              :     // The result is the same as the ordered version when the
    2087              :     // comparison is true or when the operands cannot be NANs.
    2088         3629 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    2089              :       return true;
    2090              :     else
    2091              :       {
    2092         3308 :         r = range_true_and_false (type);
    2093         3308 :         return true;
    2094              :       }
    2095         3629 :   }
    2096              :   bool op1_range (frange &r, tree type,
    2097              :                   const irange &lhs, const frange &op2,
    2098              :                   relation_trio = TRIO_VARYING) const final override;
    2099          628 :   bool op2_range (frange &r, tree type,
    2100              :                   const irange &lhs, const frange &op1,
    2101              :                   relation_trio rel = TRIO_VARYING) const final override
    2102              :   {
    2103          628 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    2104              :   }
    2105              : };
    2106              : static const foperator_unordered_equal fop_unordered_equal;
    2107              : 
    2108              : bool
    2109         1259 : foperator_unordered_equal::op1_range (frange &r, tree type,
    2110              :                                       const irange &lhs,
    2111              :                                       const frange &op2,
    2112              :                                       relation_trio) const
    2113              : {
    2114         1259 :   switch (get_bool_state (r, lhs, type))
    2115              :     {
    2116            3 :     case BRS_TRUE:
    2117              :       // If it's true, the result is the same as OP2 plus a NAN.
    2118            3 :       r = op2;
    2119              :       // Add both zeros if there's the possibility of zero equality.
    2120            3 :       frange_add_zeros (r, type);
    2121              :       // Add the possibility of a NAN.
    2122            3 :       r.update_nan ();
    2123            3 :       break;
    2124              : 
    2125            0 :     case BRS_FALSE:
    2126              :       // A false UNORDERED_EQ means both operands are !NAN, so it's
    2127              :       // impossible for op2 to be a NAN.
    2128            0 :       if (op2.known_isnan ())
    2129            0 :         r.set_undefined ();
    2130              :       else
    2131              :         {
    2132              :           // The false side indicates !NAN and not equal.  We can at least
    2133              :           // represent !NAN.
    2134            0 :           r.set_varying (type);
    2135            0 :           r.clear_nan ();
    2136              :         }
    2137              :       break;
    2138              : 
    2139              :     default:
    2140              :       break;
    2141              :     }
    2142         1259 :   return true;
    2143              : }
    2144              : 
    2145              : class foperator_ltgt : public range_operator
    2146              : {
    2147              :   using range_operator::fold_range;
    2148              :   using range_operator::op1_range;
    2149              :   using range_operator::op2_range;
    2150              : public:
    2151         2162 :   bool fold_range (irange &r, tree type,
    2152              :                    const frange &op1, const frange &op2,
    2153              :                    relation_trio trio = TRIO_VARYING) const final override
    2154              :   {
    2155         2162 :     if (op1.known_isnan () || op2.known_isnan ())
    2156              :       {
    2157            2 :         r = range_false (type);
    2158            2 :         return true;
    2159              :       }
    2160         2160 :     frange op1_no_nan = op1;
    2161         2160 :     frange op2_no_nan = op2;
    2162         2488 :     if (op1.maybe_isnan ())
    2163         1816 :       op1_no_nan.clear_nan ();
    2164         2488 :     if (op2.maybe_isnan ())
    2165         1816 :       op2_no_nan.clear_nan ();
    2166         2160 :     if (!range_op_handler (NE_EXPR).fold_range (r, type, op1_no_nan,
    2167              :                                                 op2_no_nan, trio))
    2168              :       return false;
    2169              :     // The result is the same as the ordered version when the
    2170              :     // comparison is true or when the operands cannot be NANs.
    2171         2160 :     if (!maybe_isnan (op1, op2) || r == range_false (type))
    2172              :       return true;
    2173              :     else
    2174              :       {
    2175         1800 :         r = range_true_and_false (type);
    2176         1800 :         return true;
    2177              :       }
    2178         2160 :   }
    2179              :   bool op1_range (frange &r, tree type,
    2180              :                   const irange &lhs, const frange &op2,
    2181              :                   relation_trio = TRIO_VARYING) const final override;
    2182          792 :   bool op2_range (frange &r, tree type,
    2183              :                   const irange &lhs, const frange &op1,
    2184              :                   relation_trio rel = TRIO_VARYING) const final override
    2185              :   {
    2186          792 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    2187              :   }
    2188              : };
    2189              : static const foperator_ltgt fop_ltgt;
    2190              : 
    2191              : bool
    2192         1580 : foperator_ltgt::op1_range (frange &r, tree type,
    2193              :                            const irange &lhs,
    2194              :                            const frange &op2,
    2195              :                            relation_trio) const
    2196              : {
    2197         1580 :   switch (get_bool_state (r, lhs, type))
    2198              :     {
    2199            0 :     case BRS_TRUE:
    2200              :       // A true LTGT means both operands are !NAN, so it's
    2201              :       // impossible for op2 to be a NAN.
    2202            0 :       if (op2.known_isnan ())
    2203            0 :         r.set_undefined ();
    2204              :       else
    2205              :         {
    2206              :           // The true side indicates !NAN and not equal.  We can at least
    2207              :           // represent !NAN.
    2208            0 :           r.set_varying (type);
    2209            0 :           r.clear_nan ();
    2210              :         }
    2211              :       break;
    2212              : 
    2213           16 :     case BRS_FALSE:
    2214              :       // If it's false, the result is the same as OP2 plus a NAN.
    2215           16 :       r = op2;
    2216              :       // Add both zeros if there's the possibility of zero equality.
    2217           16 :       frange_add_zeros (r, type);
    2218              :       // Add the possibility of a NAN.
    2219           16 :       r.update_nan ();
    2220           16 :       break;
    2221              : 
    2222              :     default:
    2223              :       break;
    2224              :     }
    2225         1580 :   return true;
    2226              : }
    2227              : 
    2228              : // Final tweaks for float binary op op1_range/op2_range.
    2229              : // Return TRUE if the operation is performed and a valid range is available.
    2230              : 
    2231              : static bool
    2232       856018 : float_binary_op_range_finish (bool ret, frange &r, tree type,
    2233              :                               const frange &lhs, bool div_op2 = false)
    2234              : {
    2235       856018 :   if (!ret)
    2236              :     return false;
    2237              : 
    2238              :   // If we get a known NAN from reverse op, it means either that
    2239              :   // the other operand was known NAN (in that case we know nothing),
    2240              :   // or the reverse operation introduced a known NAN.
    2241              :   // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
    2242              :   // 0 / 0 is known NAN.  Just punt in that case.
    2243              :   // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
    2244              :   // Or if lhs is a known NAN, we also don't know anything.
    2245       856018 :   if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
    2246              :     {
    2247         6616 :       r.set_varying (type);
    2248         6616 :       return true;
    2249              :     }
    2250              : 
    2251              :   // If lhs isn't NAN, then neither operand could be NAN,
    2252              :   // even if the reverse operation does introduce a maybe_nan.
    2253      1532064 :   if (!lhs.maybe_isnan ())
    2254              :     {
    2255       682662 :       r.clear_nan ();
    2256       682662 :       if (div_op2
    2257       708425 :           ? !(real_compare (LE_EXPR, &lhs.lower_bound (), &dconst0)
    2258        25763 :               && real_compare (GE_EXPR, &lhs.upper_bound (), &dconst0))
    2259      1171406 :           : !(real_isinf (&lhs.lower_bound ())
    2260       521953 :               || real_isinf (&lhs.upper_bound ())))
    2261              :         // For reverse + or - or * or op1 of /, if result is finite, then
    2262              :         // r must be finite too, as X + INF or X - INF or X * INF or
    2263              :         // INF / X is always +-INF or NAN.  For op2 of /, if result is
    2264              :         // non-zero and not NAN, r must be finite, as X / INF is always
    2265              :         // 0 or NAN.
    2266       500803 :         frange_drop_infs (r, type);
    2267              :     }
    2268              :   // If lhs is a maybe or known NAN, the operand could be
    2269              :   // NAN.
    2270              :   else
    2271       166740 :     r.update_nan ();
    2272              :   return true;
    2273              : }
    2274              : 
    2275              : // True if [lb, ub] is [+-0, +-0].
    2276              : static bool
    2277      5100713 : zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2278              : {
    2279      5100713 :   return real_iszero (&lb) && real_iszero (&ub);
    2280              : }
    2281              : 
    2282              : // True if +0 or -0 is in [lb, ub] range.
    2283              : static bool
    2284      4157857 : contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2285              : {
    2286      4157857 :   return (real_compare (LE_EXPR, &lb, &dconst0)
    2287      4157857 :           && real_compare (GE_EXPR, &ub, &dconst0));
    2288              : }
    2289              : 
    2290              : // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
    2291              : static bool
    2292      2885349 : singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2293              : {
    2294      2885349 :   return real_isinf (&lb) && real_isinf (&ub, real_isneg (&lb));
    2295              : }
    2296              : 
    2297              : // Return -1 if binary op result must have sign bit set,
    2298              : // 1 if binary op result must have sign bit clear,
    2299              : // 0 otherwise.
    2300              : // Sign bit of binary op result is exclusive or of the
    2301              : // operand's sign bits.
    2302              : static int
    2303      1299944 : signbit_known_p (const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
    2304              :                  const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub)
    2305              : {
    2306      1299944 :   if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
    2307      1299944 :       && real_isneg (&rh_lb) == real_isneg (&rh_ub))
    2308              :     {
    2309       112619 :       if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
    2310              :         return 1;
    2311              :       else
    2312         6753 :         return -1;
    2313              :     }
    2314              :   return 0;
    2315              : }
    2316              : 
    2317              : // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
    2318              : // signbit_known.
    2319              : static void
    2320         6520 : zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2321              : {
    2322         6520 :   ub = lb = dconst0;
    2323         6520 :   if (signbit_known <= 0)
    2324         6373 :     lb = dconstm0;
    2325         6373 :   if (signbit_known < 0)
    2326           44 :     ub = lb;
    2327         6520 : }
    2328              : 
    2329              : // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
    2330              : // signbit_known.
    2331              : static void
    2332         4327 : inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2333              : {
    2334         4327 :   if (signbit_known > 0)
    2335          952 :     ub = lb = dconstinf;
    2336         3375 :   else if (signbit_known < 0)
    2337           96 :     ub = lb = dconstninf;
    2338              :   else
    2339              :     {
    2340         3279 :       lb = dconstninf;
    2341         3279 :       ub = dconstinf;
    2342              :     }
    2343         4327 : }
    2344              : 
    2345              : // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
    2346              : // signbit_known.
    2347              : static void
    2348       946901 : zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2349              : {
    2350       946901 :   if (signbit_known > 0)
    2351              :     {
    2352         9842 :       lb = dconst0;
    2353         9842 :       ub = dconstinf;
    2354              :     }
    2355       937059 :   else if (signbit_known < 0)
    2356              :     {
    2357          219 :       lb = dconstninf;
    2358          219 :       ub = dconstm0;
    2359              :     }
    2360              :   else
    2361              :     {
    2362       936840 :       lb = dconstninf;
    2363       936840 :       ub = dconstinf;
    2364              :     }
    2365       946901 : }
    2366              : 
    2367              : /* Extend the LHS range by 1ulp in each direction.  For op1_range
    2368              :    or op2_range of binary operations just computing the inverse
    2369              :    operation on ranges isn't sufficient.  Consider e.g.
    2370              :    [1., 1.] = op1 + [1., 1.].  op1's range is not [0., 0.], but
    2371              :    [-0x1.0p-54, 0x1.0p-53] (when not -frounding-math), any value for
    2372              :    which adding 1. to it results in 1. after rounding to nearest.
    2373              :    So, for op1_range/op2_range extend the lhs range by 1ulp (or 0.5ulp)
    2374              :    in each direction.  See PR109008 for more details.  */
    2375              : 
    2376              : static frange
    2377       835733 : float_widen_lhs_range (tree type, const frange &lhs)
    2378              : {
    2379       835733 :   frange ret = lhs;
    2380       835733 :   if (lhs.known_isnan ())
    2381              :     return ret;
    2382       829118 :   REAL_VALUE_TYPE lb = lhs.lower_bound ();
    2383       829118 :   REAL_VALUE_TYPE ub = lhs.upper_bound ();
    2384       829118 :   if (real_isfinite (&lb))
    2385              :     {
    2386       640429 :       frange_nextafter (TYPE_MODE (type), lb, dconstninf);
    2387       640429 :       if (real_isinf (&lb))
    2388              :         {
    2389              :           /* For -DBL_MAX, instead of -Inf use
    2390              :              nexttoward (-DBL_MAX, -LDBL_MAX) in a hypothetical
    2391              :              wider type with the same mantissa precision but larger
    2392              :              exponent range; it is outside of range of double values,
    2393              :              but makes it clear it is just one ulp larger rather than
    2394              :              infinite amount larger.  */
    2395        59779 :           lb = dconstm1;
    2396       239116 :           SET_REAL_EXP (&lb, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
    2397              :         }
    2398      4483003 :       if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
    2399              :         {
    2400              :           /* If not -frounding-math nor IBM double double, actually widen
    2401              :              just by 0.5ulp rather than 1ulp.  */
    2402       640429 :           REAL_VALUE_TYPE tem;
    2403       640429 :           real_arithmetic (&tem, PLUS_EXPR, &lhs.lower_bound (), &lb);
    2404       640429 :           real_arithmetic (&lb, RDIV_EXPR, &tem, &dconst2);
    2405              :         }
    2406              :     }
    2407       829118 :   if (real_isfinite (&ub))
    2408              :     {
    2409       566961 :       frange_nextafter (TYPE_MODE (type), ub, dconstinf);
    2410       566961 :       if (real_isinf (&ub))
    2411              :         {
    2412              :           /* For DBL_MAX similarly.  */
    2413        60654 :           ub = dconst1;
    2414       242616 :           SET_REAL_EXP (&ub, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
    2415              :         }
    2416      3968727 :       if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
    2417              :         {
    2418              :           /* If not -frounding-math nor IBM double double, actually widen
    2419              :              just by 0.5ulp rather than 1ulp.  */
    2420       566961 :           REAL_VALUE_TYPE tem;
    2421       566961 :           real_arithmetic (&tem, PLUS_EXPR, &lhs.upper_bound (), &ub);
    2422       566961 :           real_arithmetic (&ub, RDIV_EXPR, &tem, &dconst2);
    2423              :         }
    2424              :     }
    2425              :   /* Temporarily disable -ffinite-math-only, so that frange::set doesn't
    2426              :      reduce the range back to real_min_representable (type) as lower bound
    2427              :      or real_max_representable (type) as upper bound.  */
    2428       829118 :   bool save_flag_finite_math_only = flag_finite_math_only;
    2429       829118 :   flag_finite_math_only = false;
    2430       829118 :   ret.set (type, lb, ub, lhs.get_nan_state ());
    2431       829118 :   flag_finite_math_only = save_flag_finite_math_only;
    2432       829118 :   return ret;
    2433              : }
    2434              : 
    2435              : bool
    2436       175095 : operator_plus::op1_range (frange &r, tree type, const frange &lhs,
    2437              :                           const frange &op2, relation_trio) const
    2438              : {
    2439       175095 :   if (lhs.undefined_p ())
    2440              :     return false;
    2441       175095 :   range_op_handler minus (MINUS_EXPR);
    2442       175095 :   if (!minus)
    2443              :     return false;
    2444       175095 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2445       175095 :   return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
    2446              :                                        r, type, wlhs);
    2447       175095 : }
    2448              : 
    2449              : bool
    2450        76302 : operator_plus::op2_range (frange &r, tree type,
    2451              :                           const frange &lhs, const frange &op1,
    2452              :                           relation_trio) const
    2453              : {
    2454        76302 :   return op1_range (r, type, lhs, op1);
    2455              : }
    2456              : 
    2457              : void
    2458      2111682 : operator_plus::rv_fold (frange &r, tree type,
    2459              :                         const REAL_VALUE_TYPE &lh_lb,
    2460              :                         const REAL_VALUE_TYPE &lh_ub,
    2461              :                         const REAL_VALUE_TYPE &rh_lb,
    2462              :                         const REAL_VALUE_TYPE &rh_ub,
    2463              :                         relation_kind) const
    2464              : {
    2465      2111682 :   REAL_VALUE_TYPE lb, ub;
    2466      2111682 :   bool maybe_nan = false;
    2467              : 
    2468      2111682 :   frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
    2469      2111682 :   frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
    2470              : 
    2471              :   // [-INF] + [+INF] = NAN
    2472      2111682 :   if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
    2473              :     maybe_nan = true;
    2474              :   // [+INF] + [-INF] = NAN
    2475       777836 :   else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
    2476              :     maybe_nan = true;
    2477              : 
    2478              :   // Handle possible NANs by saturating to the appropriate INF if only
    2479              :   // one end is a NAN.  If both ends are a NAN, just return a NAN.
    2480      2111682 :   bool lb_nan = real_isnan (&lb);
    2481      2111682 :   bool ub_nan = real_isnan (&ub);
    2482      2111682 :   if (lb_nan && ub_nan)
    2483              :     {
    2484            0 :       r.set_nan (type);
    2485            0 :       return;
    2486              :     }
    2487      2111682 :   if (lb_nan)
    2488          374 :     lb = dconstninf;
    2489      2111308 :   else if (ub_nan)
    2490            0 :     ub = dconstinf;
    2491      2111682 :   r.set (type, lb, ub, nan_state (maybe_nan));
    2492              : }
    2493              : 
    2494              : 
    2495              : bool
    2496        87154 : operator_minus::op1_range (frange &r, tree type,
    2497              :                            const frange &lhs, const frange &op2,
    2498              :                            relation_trio) const
    2499              : {
    2500        87154 :   if (lhs.undefined_p ())
    2501              :     return false;
    2502        87154 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2503        87154 :   return float_binary_op_range_finish (
    2504       174308 :               range_op_handler (PLUS_EXPR).fold_range (r, type, wlhs, op2),
    2505              :               r, type, wlhs);
    2506        87154 : }
    2507              : 
    2508              : bool
    2509       132575 : operator_minus::op2_range (frange &r, tree type,
    2510              :                            const frange &lhs, const frange &op1,
    2511              :                            relation_trio) const
    2512              : {
    2513       132575 :   if (lhs.undefined_p ())
    2514              :     return false;
    2515       132575 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2516       132575 :   return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
    2517              :                                        r, type, wlhs);
    2518       132575 : }
    2519              : 
    2520              : void
    2521       931461 : operator_minus::rv_fold (frange &r, tree type,
    2522              :                          const REAL_VALUE_TYPE &lh_lb,
    2523              :                          const REAL_VALUE_TYPE &lh_ub,
    2524              :                          const REAL_VALUE_TYPE &rh_lb,
    2525              :                          const REAL_VALUE_TYPE &rh_ub,
    2526              :                          relation_kind) const
    2527              : {
    2528       931461 :   REAL_VALUE_TYPE lb, ub;
    2529       931461 :   bool maybe_nan = false;
    2530              : 
    2531       931461 :   frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
    2532       931461 :   frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
    2533              : 
    2534              :   // [+INF] - [+INF] = NAN
    2535       931461 :   if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
    2536              :     maybe_nan = true;
    2537              :   // [-INF] - [-INF] = NAN
    2538       637688 :   else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
    2539              :     maybe_nan = true;
    2540              : 
    2541              :   // Handle possible NANs by saturating to the appropriate INF if only
    2542              :   // one end is a NAN.  If both ends are a NAN, just return a NAN.
    2543       931461 :   bool lb_nan = real_isnan (&lb);
    2544       931461 :   bool ub_nan = real_isnan (&ub);
    2545       931461 :   if (lb_nan && ub_nan)
    2546              :     {
    2547            0 :       r.set_nan (type);
    2548            0 :       return;
    2549              :     }
    2550       931461 :   if (lb_nan)
    2551          186 :     lb = dconstninf;
    2552       931275 :   else if (ub_nan)
    2553          312 :     ub = dconstinf;
    2554       931461 :   r.set (type, lb, ub, nan_state (maybe_nan));
    2555              : }
    2556              : 
    2557              : 
    2558              : // Given CP[0] to CP[3] floating point values rounded to -INF,
    2559              : // set LB to the smallest of them (treating -0 as smaller to +0).
    2560              : // Given CP[4] to CP[7] floating point values rounded to +INF,
    2561              : // set UB to the largest of them (treating -0 as smaller to +0).
    2562              : 
    2563              : static void
    2564      1071450 : find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
    2565              :             const REAL_VALUE_TYPE (&cp)[8])
    2566              : {
    2567      1071450 :   lb = cp[0];
    2568      1071450 :   ub = cp[4];
    2569      4285800 :   for (int i = 1; i < 4; ++i)
    2570              :     {
    2571      3214350 :       if (real_less (&cp[i], &lb)
    2572      3214350 :           || (real_iszero (&lb) && real_isnegzero (&cp[i])))
    2573       358472 :         lb = cp[i];
    2574      3214350 :       if (real_less (&ub, &cp[i + 4])
    2575      3214350 :           || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
    2576      1008937 :         ub = cp[i + 4];
    2577              :     }
    2578      1071450 : }
    2579              : 
    2580              : 
    2581              : bool
    2582       338708 : operator_mult::op1_range (frange &r, tree type,
    2583              :                           const frange &lhs, const frange &op2,
    2584              :                           relation_trio) const
    2585              : {
    2586       338708 :   if (lhs.undefined_p ())
    2587              :     return false;
    2588       338708 :   range_op_handler rdiv (RDIV_EXPR);
    2589       338708 :   if (!rdiv)
    2590              :     return false;
    2591       338708 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2592       338708 :   bool ret = rdiv.fold_range (r, type, wlhs, op2);
    2593       338708 :   if (ret == false)
    2594              :     return false;
    2595       338708 :   if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
    2596           16 :     return float_binary_op_range_finish (ret, r, type, wlhs);
    2597       338692 :   const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2598       338692 :   const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2599       338692 :   const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
    2600       338692 :   const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
    2601       628447 :   if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
    2602       487644 :       || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
    2603        41627 :           && (real_isinf (&op2_lb) || real_isinf (&op2_ub))))
    2604              :     {
    2605              :       // If both lhs and op2 could be zeros or both could be infinities,
    2606              :       // we don't know anything about op1 except maybe for the sign
    2607              :       // and perhaps if it can be NAN or not.
    2608       148155 :       REAL_VALUE_TYPE lb, ub;
    2609       148155 :       int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
    2610       148155 :       zero_to_inf_range (lb, ub, signbit_known);
    2611       148155 :       r.set (type, lb, ub);
    2612              :     }
    2613              :   // Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
    2614              :   // or if lhs must be zero and op2 doesn't include zero, it would be
    2615              :   // UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
    2616              :   // range.  Those are supersets of UNDEFINED, so let's keep that way.
    2617       338692 :   return float_binary_op_range_finish (ret, r, type, wlhs);
    2618       338708 : }
    2619              : 
    2620              : bool
    2621        82337 : operator_mult::op2_range (frange &r, tree type,
    2622              :                           const frange &lhs, const frange &op1,
    2623              :                           relation_trio) const
    2624              : {
    2625        82337 :   return op1_range (r, type, lhs, op1);
    2626              : }
    2627              : 
    2628              : void
    2629      1149477 : operator_mult::rv_fold (frange &r, tree type,
    2630              :                         const REAL_VALUE_TYPE &lh_lb,
    2631              :                         const REAL_VALUE_TYPE &lh_ub,
    2632              :                         const REAL_VALUE_TYPE &rh_lb,
    2633              :                         const REAL_VALUE_TYPE &rh_ub,
    2634              :                         relation_kind kind) const
    2635              : {
    2636      1149477 :   bool is_square
    2637              :     = (kind == VREL_EQ
    2638        37390 :        && real_equal (&lh_lb, &rh_lb)
    2639        37387 :        && real_equal (&lh_ub, &rh_ub)
    2640        37387 :        && real_isneg (&lh_lb) == real_isneg (&rh_lb)
    2641      1186864 :        && real_isneg (&lh_ub) == real_isneg (&rh_ub));
    2642      1112090 :   REAL_VALUE_TYPE lb, ub;
    2643      1841344 :   bool maybe_nan = false;
    2644              :   // x * x never produces a new NAN and we only multiply the same
    2645              :   // values, so the 0 * INF problematic cases never appear there.
    2646      1112090 :   if (!is_square)
    2647              :     {
    2648              :       // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
    2649      1117463 :       if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
    2650      1117457 :           || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
    2651              :         {
    2652           37 :           r.set_nan (type);
    2653       420223 :           return;
    2654              :         }
    2655              : 
    2656              :       // Otherwise, if one range includes zero and the other ends with +-INF,
    2657              :       // it is a maybe NAN.
    2658      1112053 :       if ((contains_zero_p (lh_lb, lh_ub)
    2659      1010038 :            && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
    2660      1730470 :           || (contains_zero_p (rh_lb, rh_ub)
    2661       198912 :               && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
    2662              :         {
    2663       420186 :           maybe_nan = true;
    2664              : 
    2665       420186 :           int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
    2666              : 
    2667              :           // If one of the ranges that includes INF is singleton
    2668              :           // and the other range includes zero, the resulting
    2669              :           // range is INF and NAN, because the 0 * INF boundary
    2670              :           // case will be NAN, but already nextafter (0, 1) * INF
    2671              :           // is INF.
    2672       420186 :           if (singleton_inf_p (lh_lb, lh_ub)
    2673       420186 :               || singleton_inf_p (rh_lb, rh_ub))
    2674              :             {
    2675          988 :               inf_range (lb, ub, signbit_known);
    2676          988 :               r.set (type, lb, ub, nan_state (true));
    2677          988 :               return;
    2678              :             }
    2679              : 
    2680              :           // If one of the multiplicands must be zero, the resulting
    2681              :           // range is +-0 and NAN.
    2682       419198 :           if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
    2683              :             {
    2684         5993 :               zero_range (lb, ub, signbit_known);
    2685         5993 :               r.set (type, lb, ub, nan_state (true));
    2686         5993 :               return;
    2687              :             }
    2688              : 
    2689              :           // Otherwise one of the multiplicands could be
    2690              :           // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
    2691              :           // or similarly with different signs.  0.0 * DBL_MAX
    2692              :           // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
    2693              :           // so if the signs are always the same or always different,
    2694              :           // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
    2695       413205 :           zero_to_inf_range (lb, ub, signbit_known);
    2696       413205 :           r.set (type, lb, ub, nan_state (true));
    2697       413205 :           return;
    2698              :         }
    2699              :     }
    2700              : 
    2701       729254 :   REAL_VALUE_TYPE cp[8];
    2702              :   // Do a cross-product.  At this point none of the multiplications
    2703              :   // should produce a NAN.
    2704       729254 :   frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
    2705       729254 :   frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
    2706       729254 :   if (is_square)
    2707              :     {
    2708              :       // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
    2709              :       // as maximum and -0.0 as minimum if 0.0 is in the range,
    2710              :       // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
    2711              :       // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
    2712              :       // x and y are bitwise equal, just that they compare equal.
    2713        37387 :       if (contains_zero_p (lh_lb, lh_ub))
    2714              :         {
    2715        34548 :           if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
    2716         1257 :             cp[1] = dconst0;
    2717              :           else
    2718        33291 :             cp[1] = dconstm0;
    2719              :         }
    2720              :       else
    2721         2839 :         cp[1] = cp[0];
    2722        37387 :       cp[2] = cp[0];
    2723        37387 :       cp[5] = cp[4];
    2724        37387 :       cp[6] = cp[4];
    2725              :     }
    2726              :   else
    2727              :     {
    2728       691867 :       frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
    2729       691867 :       frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
    2730       691867 :       frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
    2731       691867 :       frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
    2732              :     }
    2733       729254 :   frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
    2734       729254 :   frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
    2735              : 
    2736       729254 :   find_range (lb, ub, cp);
    2737              : 
    2738       729254 :   gcc_checking_assert (!real_isnan (&lb));
    2739       729254 :   gcc_checking_assert (!real_isnan (&ub));
    2740       729254 :   r.set (type, lb, ub, nan_state (maybe_nan));
    2741              : }
    2742              : 
    2743              : 
    2744              : class foperator_div : public range_operator
    2745              : {
    2746              :   using range_operator::op1_range;
    2747              :   using range_operator::op2_range;
    2748              : public:
    2749        25191 :   virtual bool op1_range (frange &r, tree type,
    2750              :                           const frange &lhs,
    2751              :                           const frange &op2,
    2752              :                           relation_trio = TRIO_VARYING) const final override
    2753              :   {
    2754        25191 :     if (lhs.undefined_p ())
    2755              :       return false;
    2756        25191 :     frange wlhs = float_widen_lhs_range (type, lhs);
    2757        25191 :     bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
    2758        25191 :     if (!ret)
    2759              :       return ret;
    2760        25191 :     if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
    2761            4 :       return float_binary_op_range_finish (ret, r, type, wlhs);
    2762        25187 :     const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2763        25187 :     const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2764        25187 :     const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
    2765        25187 :     const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
    2766        25187 :     if ((contains_zero_p (lhs_lb, lhs_ub)
    2767        17741 :          && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
    2768        31582 :         || ((contains_zero_p (op2_lb, op2_ub))
    2769         8191 :             && (real_isinf (&lhs_lb) || real_isinf (&lhs_ub))))
    2770              :       {
    2771              :         // If both lhs could be zero and op2 infinity or vice versa,
    2772              :         // we don't know anything about op1 except maybe for the sign
    2773              :         // and perhaps if it can be NAN or not.
    2774        18987 :         REAL_VALUE_TYPE lb, ub;
    2775        18987 :         int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
    2776        18987 :         zero_to_inf_range (lb, ub, signbit_known);
    2777        18987 :         r.set (type, lb, ub);
    2778              :       }
    2779        25187 :     return float_binary_op_range_finish (ret, r, type, wlhs);
    2780        25191 :   }
    2781        42901 :   virtual bool op2_range (frange &r, tree type,
    2782              :                           const frange &lhs,
    2783              :                           const frange &op1,
    2784              :                           relation_trio = TRIO_VARYING) const final override
    2785              :   {
    2786        42901 :     if (lhs.undefined_p ())
    2787              :       return false;
    2788        42901 :     frange wlhs = float_widen_lhs_range (type, lhs);
    2789        42901 :     bool ret = fold_range (r, type, op1, wlhs);
    2790        42901 :     if (!ret)
    2791              :       return ret;
    2792        42901 :     if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
    2793           20 :       return float_binary_op_range_finish (ret, r, type, wlhs, true);
    2794        42881 :     const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2795        42881 :     const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2796        42881 :     const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
    2797        42881 :     const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
    2798        75672 :     if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
    2799        46467 :         || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
    2800         7847 :             && (real_isinf (&op1_lb) || real_isinf (&op1_ub))))
    2801              :       {
    2802              :         // If both lhs and op1 could be zeros or both could be infinities,
    2803              :         // we don't know anything about op2 except maybe for the sign
    2804              :         // and perhaps if it can be NAN or not.
    2805        33517 :         REAL_VALUE_TYPE lb, ub;
    2806        33517 :         int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
    2807        33517 :         zero_to_inf_range (lb, ub, signbit_known);
    2808        33517 :         r.set (type, lb, ub);
    2809              :       }
    2810        42881 :     return float_binary_op_range_finish (ret, r, type, wlhs, true);
    2811        42901 :   }
    2812              : private:
    2813       679751 :   void rv_fold (frange &r, tree type,
    2814              :                 const REAL_VALUE_TYPE &lh_lb,
    2815              :                 const REAL_VALUE_TYPE &lh_ub,
    2816              :                 const REAL_VALUE_TYPE &rh_lb,
    2817              :                 const REAL_VALUE_TYPE &rh_ub,
    2818              :                 relation_kind) const final override
    2819              :   {
    2820              :     // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
    2821       680922 :     if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
    2822       680276 :         || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
    2823              :       {
    2824          652 :         r.set_nan (type);
    2825       337555 :         return;
    2826              :       }
    2827              : 
    2828       679099 :     REAL_VALUE_TYPE lb, ub;
    2829       679099 :     bool maybe_nan = false;
    2830              :     // If +-0.0 is in both ranges, it is a maybe NAN.
    2831       679099 :     if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
    2832              :       maybe_nan = true;
    2833              :     // If +-INF is in both ranges, it is a maybe NAN.
    2834       661561 :     else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
    2835       389603 :              && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
    2836              :       maybe_nan = true;
    2837              : 
    2838       679099 :     int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
    2839              : 
    2840              :     // If dividend must be zero, the range is just +-0
    2841              :     // (including if the divisor is +-INF).
    2842              :     // If divisor must be +-INF, the range is just +-0
    2843              :     // (including if the dividend is zero).
    2844       679099 :     if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
    2845              :       {
    2846          527 :         zero_range (lb, ub, signbit_known);
    2847          527 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2848          527 :         return;
    2849              :       }
    2850              : 
    2851              :     // If divisor must be zero, the range is just +-INF
    2852              :     // (including if the dividend is +-INF).
    2853              :     // If dividend must be +-INF, the range is just +-INF
    2854              :     // (including if the dividend is zero).
    2855       678572 :     if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
    2856              :       {
    2857         3339 :         inf_range (lb, ub, signbit_known);
    2858         3339 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2859         3339 :         return;
    2860              :       }
    2861              : 
    2862              :     // Otherwise if both operands may be zero, divisor could be
    2863              :     // nextafter(0.0, +-1.0) and dividend +-0.0
    2864              :     // in which case result is going to INF or vice versa and
    2865              :     // result +0.0.  So, all we can say for that case is if the
    2866              :     // signs of divisor and dividend are always the same we have
    2867              :     // [+0.0, +INF], if they are always different we have
    2868              :     // [-INF, -0.0].  If they vary, VARYING.
    2869              :     // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
    2870              :     // in which case result is going to INF or vice versa and
    2871              :     // result +0.0.  So, all we can say for that case is if the
    2872              :     // signs of divisor and dividend are always the same we have
    2873              :     // [+0.0, +INF], if they are always different we have
    2874              :     // [-INF, -0.0].  If they vary, VARYING.
    2875       675233 :     if (maybe_nan)
    2876              :       {
    2877       333037 :         zero_to_inf_range (lb, ub, signbit_known);
    2878       333037 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2879       333037 :         return;
    2880              :       }
    2881              : 
    2882       342196 :     REAL_VALUE_TYPE cp[8];
    2883              :     // Do a cross-division.  At this point none of the divisions should
    2884              :     // produce a NAN.
    2885       342196 :     frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
    2886       342196 :     frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
    2887       342196 :     frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
    2888       342196 :     frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
    2889       342196 :     frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
    2890       342196 :     frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
    2891       342196 :     frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
    2892       342196 :     frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
    2893              : 
    2894       342196 :     find_range (lb, ub, cp);
    2895              : 
    2896              :     // If divisor may be zero (but is not known to be only zero),
    2897              :     // and dividend can't be zero, the range can go up to -INF or +INF
    2898              :     // depending on the signs.
    2899       342196 :     if (contains_zero_p (rh_lb, rh_ub))
    2900              :       {
    2901        52202 :         if (signbit_known <= 0)
    2902        49808 :           real_inf (&lb, true);
    2903        49808 :         if (signbit_known >= 0)
    2904        52164 :           real_inf (&ub, false);
    2905              :       }
    2906              : 
    2907       342196 :     gcc_checking_assert (!real_isnan (&lb));
    2908       342196 :     gcc_checking_assert (!real_isnan (&ub));
    2909       342196 :     r.set (type, lb, ub, nan_state (maybe_nan));
    2910              :   }
    2911              : };
    2912              : static const foperator_div fop_div;
    2913              : 
    2914              : bool
    2915       918101 : operator_cast::fold_range (frange &r, tree type, const frange &op1,
    2916              :                            const frange &, relation_trio) const
    2917              : {
    2918       918101 :   REAL_VALUE_TYPE lb, ub;
    2919       918101 :   enum machine_mode mode = TYPE_MODE (type);
    2920      6426707 :   bool mode_composite = MODE_COMPOSITE_P (mode);
    2921              : 
    2922       918101 :   if (empty_range_varying (r, type, op1, op1))
    2923          816 :     return true;
    2924      3669140 :   if (!MODE_HAS_NANS (mode) && op1.maybe_isnan ())
    2925              :     {
    2926            0 :       r.set_varying (type);
    2927            0 :       return true;
    2928              :     }
    2929       917285 :   if (op1.known_isnan ())
    2930              :     {
    2931         3052 :       r.set_nan (type);
    2932         3052 :       return true;
    2933              :     }
    2934              : 
    2935       914233 :   const REAL_VALUE_TYPE &lh_lb = op1.lower_bound ();
    2936       914233 :   const REAL_VALUE_TYPE &lh_ub = op1.upper_bound ();
    2937       914233 :   real_convert (&lb, mode, &lh_lb);
    2938       914233 :   real_convert (&ub, mode, &lh_ub);
    2939              : 
    2940       914233 :   if (flag_rounding_math)
    2941              :     {
    2942        31513 :       if (real_less (&lh_lb, &lb))
    2943              :         {
    2944         2662 :           if (mode_composite
    2945         2662 :               && (real_isdenormal (&lb, mode) || real_iszero (&lb)))
    2946              :             {
    2947              :               // IBM extended denormals only have DFmode precision.
    2948            0 :               REAL_VALUE_TYPE tmp, tmp2;
    2949            0 :               real_convert (&tmp2, DFmode, &lh_lb);
    2950            0 :               real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
    2951              :                               &dconstninf);
    2952            0 :               real_convert (&lb, mode, &tmp);
    2953              :             }
    2954              :           else
    2955         2662 :             frange_nextafter (mode, lb, dconstninf);
    2956              :         }
    2957        31513 :       if (real_less (&ub, &lh_ub))
    2958              :         {
    2959         1064 :           if (mode_composite
    2960         1064 :               && (real_isdenormal (&ub, mode) || real_iszero (&ub)))
    2961              :             {
    2962              :               // IBM extended denormals only have DFmode precision.
    2963            0 :               REAL_VALUE_TYPE tmp, tmp2;
    2964            0 :               real_convert (&tmp2, DFmode, &lh_ub);
    2965            0 :               real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
    2966              :                               &dconstinf);
    2967            0 :               real_convert (&ub, mode, &tmp);
    2968              :             }
    2969              :           else
    2970         1064 :             frange_nextafter (mode, ub, dconstinf);
    2971              :         }
    2972              :     }
    2973              : 
    2974       914233 :   r.set (type, lb, ub, op1.get_nan_state ());
    2975              : 
    2976       914233 :   if (flag_trapping_math
    2977      4119592 :       && MODE_HAS_INFINITIES (TYPE_MODE (type))
    2978       801340 :       && r.known_isinf ()
    2979       914313 :       && !op1.known_isinf ())
    2980              :     {
    2981            1 :       REAL_VALUE_TYPE inf = r.lower_bound ();
    2982            1 :       if (real_isneg (&inf))
    2983              :         {
    2984            0 :           REAL_VALUE_TYPE min = real_min_representable (type);
    2985            0 :           r.set (type, inf, min);
    2986              :         }
    2987              :       else
    2988              :         {
    2989            1 :           REAL_VALUE_TYPE max = real_max_representable (type);
    2990            1 :           r.set (type, max, inf);
    2991              :         }
    2992              :     }
    2993              : 
    2994       914233 :   r.flush_denormals_to_zero ();
    2995       914233 :   return true;
    2996              : }
    2997              : 
    2998              : // Implement fold for a cast from float to another float.
    2999              : bool
    3000        54394 : operator_cast::op1_range (frange &r, tree type, const frange &lhs,
    3001              :                           const frange &op2, relation_trio) const
    3002              : {
    3003        54394 :   if (lhs.undefined_p ())
    3004              :     return false;
    3005        54394 :   tree lhs_type = lhs.type ();
    3006        54394 :   enum machine_mode mode = TYPE_MODE (type);
    3007        54394 :   enum machine_mode lhs_mode = TYPE_MODE (lhs_type);
    3008        54394 :   frange wlhs;
    3009        54394 :   bool rm;
    3010        54394 :   if (REAL_MODE_FORMAT (mode)->ieee_bits
    3011        50038 :       && REAL_MODE_FORMAT (lhs_mode)->ieee_bits
    3012        46830 :       && (REAL_MODE_FORMAT (lhs_mode)->ieee_bits
    3013              :           >= REAL_MODE_FORMAT (mode)->ieee_bits)
    3014        74679 :       && pow2p_hwi (REAL_MODE_FORMAT (mode)->ieee_bits))
    3015              :     {
    3016              :       /* If the cast is widening from IEEE exchange mode to
    3017              :          wider exchange mode or extended mode, no need to extend
    3018              :          the range on reverse operation.  */
    3019        20285 :       rm = false;
    3020        20285 :       wlhs = lhs;
    3021              :     }
    3022              :   else
    3023              :     {
    3024        34109 :       rm = true;
    3025        34109 :       wlhs = float_widen_lhs_range (lhs_type, lhs);
    3026              :     }
    3027        54394 :   auto save_flag_rounding_math = flag_rounding_math;
    3028        54394 :   flag_rounding_math = rm;
    3029        54394 :   bool ret = float_binary_op_range_finish (fold_range (r, type, wlhs, op2),
    3030              :                                            r, type, lhs);
    3031        54394 :   flag_rounding_math = save_flag_rounding_math;
    3032        54394 :   return ret;
    3033        54394 : }
    3034              : 
    3035              : // Implement fold for a cast from float to an int.
    3036              : bool
    3037       210301 : operator_cast::fold_range (irange &r, tree type, const frange &op1,
    3038              :                            const irange &, relation_trio) const
    3039              : {
    3040       210301 :   if (empty_range_varying (r, type, op1, op1))
    3041          566 :     return true;
    3042       209735 :   if (op1.maybe_isnan () || op1.maybe_isinf ())
    3043              :     {
    3044       183251 :       r.set_varying (type);
    3045       183251 :       return true;
    3046              :     }
    3047        26484 :   REAL_VALUE_TYPE lb, ub;
    3048        26484 :   real_trunc (&lb, VOIDmode, &op1.lower_bound ());
    3049        26484 :   real_trunc (&ub, VOIDmode, &op1.upper_bound ());
    3050        26484 :   REAL_VALUE_TYPE l, u;
    3051        26484 :   l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
    3052        26484 :   if (real_less (&lb, &l))
    3053              :     {
    3054         9503 :       r.set_varying (type);
    3055         9503 :       return true;
    3056              :     }
    3057        16981 :   u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
    3058        16981 :   if (real_less (&u, &ub))
    3059              :     {
    3060         8070 :       r.set_varying (type);
    3061         8070 :       return true;
    3062              :     }
    3063         8911 :   bool fail = false;
    3064         8911 :   wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
    3065         8911 :   wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
    3066         8911 :   if (fail)
    3067              :     {
    3068            0 :       r.set_varying (type);
    3069            0 :       return true;
    3070              :     }
    3071         8911 :   r.set (type, wlb, wub);
    3072         8911 :   return true;
    3073         8911 : }
    3074              : 
    3075              : // Implement op1_range for a cast from float to an int.
    3076              : bool
    3077         8227 : operator_cast::op1_range (frange &r, tree type, const irange &lhs,
    3078              :                           const frange &, relation_trio) const
    3079              : {
    3080         8227 :   if (lhs.undefined_p ())
    3081              :     return false;
    3082         8227 :   REAL_VALUE_TYPE lb, lbo, ub, ubo;
    3083         8227 :   wide_int lhs_lb = lhs.lower_bound ();
    3084         8227 :   wide_int lhs_ub = lhs.upper_bound ();
    3085         8227 :   tree lhs_type = lhs.type ();
    3086         8227 :   enum machine_mode mode = TYPE_MODE (type);
    3087         8227 :   real_from_integer (&lbo, VOIDmode, lhs_lb, TYPE_SIGN (lhs_type));
    3088         8227 :   real_from_integer (&ubo, VOIDmode, lhs_ub, TYPE_SIGN (lhs_type));
    3089         8227 :   real_convert (&lb, mode, &lbo);
    3090         8227 :   real_convert (&ub, mode, &ubo);
    3091         8227 :   if (real_identical (&lb, &lbo))
    3092              :     {
    3093              :       /* If low bound is exactly representable in type,
    3094              :          use nextafter (lb - 1., +inf).  */
    3095         8009 :       real_arithmetic (&lb, PLUS_EXPR, &lbo, &dconstm1);
    3096         8009 :       real_convert (&lb, mode, &lb);
    3097         8009 :       if (!real_identical (&lb, &lbo))
    3098         6634 :         frange_nextafter (mode, lb, dconstinf);
    3099         8009 :       if (real_identical (&lb, &lbo))
    3100         1377 :         frange_nextafter (mode, lb, dconstninf);
    3101              :     }
    3102          218 :   else if (real_less (&lbo, &lb))
    3103           13 :     frange_nextafter (mode, lb, dconstninf);
    3104         8227 :   if (real_identical (&ub, &ubo))
    3105              :     {
    3106              :       /* If upper bound is exactly representable in type,
    3107              :          use nextafter (ub + 1., -inf).  */
    3108         6285 :       real_arithmetic (&ub, PLUS_EXPR, &ubo, &dconst1);
    3109         6285 :       real_convert (&ub, mode, &ub);
    3110         6285 :       if (!real_identical (&ub, &ubo))
    3111         6141 :         frange_nextafter (mode, ub, dconstninf);
    3112         6285 :       if (real_identical (&ub, &ubo))
    3113          144 :         frange_nextafter (mode, ub, dconstinf);
    3114              :     }
    3115         1942 :   else if (real_less (&ub, &ubo))
    3116            0 :     frange_nextafter (mode, ub, dconstinf);
    3117         8227 :   r.set (type, lb, ub, nan_state (false));
    3118         8227 :   return true;
    3119         8227 : }
    3120              : 
    3121              : // Implement fold for a cast from int to a float.
    3122              : bool
    3123       823804 : operator_cast::fold_range (frange &r, tree type, const irange &op1,
    3124              :                            const frange &, relation_trio) const
    3125              : {
    3126       823804 :   if (empty_range_varying (r, type, op1, op1))
    3127         1402 :     return true;
    3128       822402 :   REAL_VALUE_TYPE lb, ub;
    3129       822402 :   wide_int op1_lb = op1.lower_bound ();
    3130       822402 :   wide_int op1_ub = op1.upper_bound ();
    3131       822402 :   tree op1_type = op1.type ();
    3132       822402 :   enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
    3133       822402 :   real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
    3134       822402 :   real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
    3135       822402 :   if (flag_rounding_math)
    3136              :     {
    3137         1213 :       REAL_VALUE_TYPE lbo = lb, ubo = ub;
    3138         1213 :       mode = TYPE_MODE (type);
    3139         1213 :       real_convert (&lb, mode, &lb);
    3140         1213 :       real_convert (&ub, mode, &ub);
    3141         1213 :       if (real_less (&lbo, &lb))
    3142          322 :         frange_nextafter (mode, lb, dconstninf);
    3143         1213 :       if (real_less (&ub, &ubo))
    3144          192 :         frange_nextafter (mode, ub, dconstinf);
    3145              :     }
    3146       822402 :   r.set (type, lb, ub, nan_state (false));
    3147       822402 :   frange_drop_infs (r, type);
    3148       822402 :   if (r.undefined_p ())
    3149            4 :     r.set_varying (type);
    3150       822402 :   return true;
    3151       822417 : }
    3152              : 
    3153              : // Implement op1_range for a cast from int to a float.
    3154              : bool
    3155       214376 : operator_cast::op1_range (irange &r, tree type, const frange &lhs,
    3156              :                           const irange &, relation_trio) const
    3157              : {
    3158       214376 :   if (lhs.undefined_p ())
    3159              :     return false;
    3160       214376 :   if (lhs.known_isnan ())
    3161              :     {
    3162            0 :       r.set_varying (type);
    3163            0 :       return true;
    3164              :     }
    3165       214376 :   REAL_VALUE_TYPE lb = lhs.lower_bound ();
    3166       214376 :   REAL_VALUE_TYPE ub = lhs.upper_bound ();
    3167       214376 :   enum machine_mode mode = TYPE_MODE (lhs.type ());
    3168       214376 :   frange_nextafter (mode, lb, dconstninf);
    3169       214376 :   frange_nextafter (mode, ub, dconstinf);
    3170       214376 :   if (flag_rounding_math)
    3171              :     {
    3172           37 :       real_floor (&lb, mode, &lb);
    3173           37 :       real_ceil (&ub, mode, &ub);
    3174              :     }
    3175              :   else
    3176              :     {
    3177       214339 :       real_trunc (&lb, mode, &lb);
    3178       214339 :       real_trunc (&ub, mode, &ub);
    3179              :     }
    3180       214376 :   REAL_VALUE_TYPE l, u;
    3181       214376 :   wide_int wlb, wub;
    3182       214376 :   l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
    3183       214376 :   if (real_less (&lb, &l))
    3184        28791 :     wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3185              :   else
    3186              :     {
    3187       185585 :       bool fail = false;
    3188       185585 :       wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
    3189       185585 :       if (fail)
    3190            0 :         wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3191              :     }
    3192       214376 :   u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
    3193       214376 :   if (real_less (&u, &ub))
    3194        39819 :     wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3195              :   else
    3196              :     {
    3197       174557 :       bool fail = false;
    3198       174557 :       wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
    3199       174557 :       if (fail)
    3200            0 :         wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3201              :     }
    3202       214376 :   r.set (type, wlb, wub);
    3203       214376 :   return true;
    3204       214376 : }
    3205              : 
    3206              : // Initialize any float operators to the primary table
    3207              : 
    3208              : void
    3209       291201 : range_op_table::initialize_float_ops ()
    3210              : {
    3211       291201 :   set (UNLE_EXPR, fop_unordered_le);
    3212       291201 :   set (UNLT_EXPR, fop_unordered_lt);
    3213       291201 :   set (UNGE_EXPR, fop_unordered_ge);
    3214       291201 :   set (UNGT_EXPR, fop_unordered_gt);
    3215       291201 :   set (UNEQ_EXPR, fop_unordered_equal);
    3216       291201 :   set (ORDERED_EXPR, fop_ordered);
    3217       291201 :   set (UNORDERED_EXPR, fop_unordered);
    3218       291201 :   set (LTGT_EXPR, fop_ltgt);
    3219       291201 :   set (RDIV_EXPR, fop_div);
    3220       291201 : }
    3221              : 
    3222              : #if CHECKING_P
    3223              : #include "selftest.h"
    3224              : 
    3225              : namespace selftest
    3226              : {
    3227              : 
    3228              : // Build an frange from string endpoints.
    3229              : 
    3230              : static inline frange
    3231           16 : frange_float (const char *lb, const char *ub, tree type = float_type_node)
    3232              : {
    3233           16 :   REAL_VALUE_TYPE min, max;
    3234           16 :   gcc_assert (real_from_string (&min, lb) == 0);
    3235           16 :   gcc_assert (real_from_string (&max, ub) == 0);
    3236           16 :   return frange (type, min, max);
    3237              : }
    3238              : 
    3239              : void
    3240            4 : range_op_float_tests ()
    3241              : {
    3242            4 :   frange r, r0, r1;
    3243            4 :   frange trange (float_type_node);
    3244              : 
    3245              :   // negate([-5, +10]) => [-10, 5]
    3246            4 :   r0 = frange_float ("-5", "10");
    3247            4 :   range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
    3248            4 :   ASSERT_EQ (r, frange_float ("-10", "5"));
    3249              : 
    3250              :   // negate([0, 1] -NAN) => [-1, -0] +NAN
    3251            4 :   r0 = frange_float ("0", "1");
    3252            4 :   r0.update_nan (true);
    3253            4 :   range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
    3254            4 :   r1 = frange_float ("-1", "-0");
    3255            4 :   r1.update_nan (false);
    3256            4 :   ASSERT_EQ (r, r1);
    3257              : 
    3258              :   // [-INF,+INF] + [-INF,+INF] could be a NAN.
    3259            4 :   range_op_handler plus (PLUS_EXPR);
    3260            4 :   r0.set_varying (float_type_node);
    3261            4 :   r1.set_varying (float_type_node);
    3262            4 :   r0.clear_nan ();
    3263            4 :   r1.clear_nan ();
    3264            4 :   plus.fold_range (r, float_type_node, r0, r1);
    3265            4 :   if (HONOR_NANS (float_type_node))
    3266            8 :     ASSERT_TRUE (r.maybe_isnan ());
    3267            4 : }
    3268              : 
    3269              : } // namespace selftest
    3270              : 
    3271              : #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.