LCOV - code coverage report
Current view: top level - gcc - range-op-float.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.6 % 1344 1245
Test Date: 2026-05-11 19:44:49 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      5690629 : range_operator::fold_range (frange &r, tree type,
      54              :                             const frange &op1, const frange &op2,
      55              :                             relation_trio trio) const
      56              : {
      57      5690629 :   if (empty_range_varying (r, type, op1, op2))
      58         6391 :     return true;
      59      5684238 :   if (op1.known_isnan () || op2.known_isnan ())
      60              :     {
      61         7395 :       r.set_nan (type);
      62         7395 :       return true;
      63              :     }
      64              : 
      65      5676843 :   rv_fold (r, type,
      66              :            op1.lower_bound (), op1.upper_bound (),
      67              :            op2.lower_bound (), op2.upper_bound (), trio.op1_op2 ());
      68              : 
      69      5676843 :   if (r.known_isnan ())
      70              :     return true;
      71      9124332 :   if (op1.maybe_isnan () || op2.maybe_isnan ())
      72      4126657 :     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      5676152 :   if (flag_trapping_math
      79     26629837 :       && MODE_HAS_INFINITIES (TYPE_MODE (type))
      80     10914976 :       && 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      5676152 :   r.flush_denormals_to_zero ();
      96              : 
      97      5676152 :   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       504146 : 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       504146 :   r.set (type, dconstninf, dconstinf, nan_state (true));
     111       504146 : }
     112              : 
     113              : bool
     114       101745 : 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       101745 :   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         6074 : 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         6074 :   return false;
     161              : }
     162              : 
     163              : bool
     164         2407 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
     165              :                            tree type ATTRIBUTE_UNUSED,
     166              :                            const frange &lhs ATTRIBUTE_UNUSED,
     167              :                            const frange &op1 ATTRIBUTE_UNUSED,
     168              :                            relation_trio) const
     169              : {
     170         2407 :   return false;
     171              : }
     172              : 
     173              : bool
     174            0 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
     175              :                            tree type ATTRIBUTE_UNUSED,
     176              :                            const irange &lhs ATTRIBUTE_UNUSED,
     177              :                            const frange &op1 ATTRIBUTE_UNUSED,
     178              :                            relation_trio) const
     179              : {
     180            0 :   return false;
     181              : }
     182              : 
     183              : relation_kind
     184      5702403 : 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      5702403 :   return VREL_VARYING;
     190              : }
     191              : 
     192              : relation_kind
     193      1022092 : 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      1022092 :   return VREL_VARYING;
     199              : }
     200              : 
     201              : relation_kind
     202       169229 : 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       169229 :   return VREL_VARYING;
     208              : }
     209              : 
     210              : relation_kind
     211      3613318 : 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      3613318 :   return VREL_VARYING;
     217              : }
     218              : 
     219              : relation_kind
     220       353664 : range_operator::op1_op2_relation (const irange &,
     221              :                                   const frange &,
     222              :                                   const frange &) const
     223              : {
     224       353664 :   return VREL_VARYING;
     225              : }
     226              : 
     227              : 
     228              : relation_kind
     229       599715 : range_operator::op1_op2_relation (const frange &,
     230              :                                   const frange &,
     231              :                                   const frange &) const
     232              : {
     233       599715 :   return VREL_VARYING;
     234              : }
     235              : 
     236              : // Return TRUE if OP1 and OP2 may be a NAN.
     237              : 
     238              : static inline bool
     239      3561772 : maybe_isnan (const frange &op1, const frange &op2)
     240              : {
     241      6203225 :   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      2070040 : frelop_early_resolve (irange &r, tree type,
     260              :                       const frange &op1, const frange &op2,
     261              :                       relation_trio trio, relation_kind my_rel)
     262              : {
     263      2070040 :   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      2070040 :   if (!maybe_isnan (op1, op2) && relation_union (rel, my_rel) == my_rel)
     276              :     {
     277         1936 :       r = range_true (type);
     278         1936 :       return true;
     279              :     }
     280              : 
     281              :   // If known relation has no subset of this relation, always false.
     282      2068104 :   if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
     283              :     {
     284         1044 :       r = range_false (type);
     285         1044 :       return true;
     286              :     }
     287              : 
     288              :   // If either operand is undefined, return VARYING.
     289      2067060 :   if (empty_range_varying (r, type, op1, op2))
     290         3086 :     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      3405831 : frange_nextafter (enum machine_mode mode,
     299              :                   REAL_VALUE_TYPE &value,
     300              :                   const REAL_VALUE_TYPE &inf)
     301              : {
     302     23840817 :   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      3405831 :       REAL_VALUE_TYPE tmp;
     314      3405831 :       real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
     315      3405831 :       value = tmp;
     316              :     }
     317      3405831 : }
     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     15100239 : 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     15100239 :   REAL_VALUE_TYPE value;
     338     15100239 :   enum machine_mode mode = TYPE_MODE (type);
     339    105701673 :   bool mode_composite = MODE_COMPOSITE_P (mode);
     340              : 
     341     15100239 :   bool inexact = real_arithmetic (&value, code, &op1, &op2);
     342     15100239 :   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     15100239 :   if (flag_rounding_math
     349        16568 :       && (code == PLUS_EXPR || code == MINUS_EXPR)
     350         4868 :       && !inexact
     351         4868 :       && real_iszero (&result)
     352           66 :       && !real_isneg (&result)
     353     15100305 :       && 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     15100239 :   bool round = false;
     365     15100239 :   if (mode_composite)
     366              :     round = true;
     367              :   else
     368              :     {
     369     15100239 :       bool low = real_isneg (&inf);
     370     15100239 :       round = (low ? !real_less (&result, &value)
     371      7550183 :                    : !real_less (&value, &result));
     372     15100239 :       if (real_isinf (&result, !low)
     373      1527322 :           && !real_isinf (&value)
     374     15490309 :           && !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       388169 :           if (!inexact)
     384              :             round = false;
     385              :           else
     386              :             {
     387        56702 :               REAL_VALUE_TYPE tmp = result, tmp2;
     388        56702 :               frange_nextafter (mode, tmp, inf);
     389              :               // TMP is at this point the maximum representable
     390              :               // number.
     391        56702 :               real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp);
     392        56702 :               if (real_isneg (&tmp2) != low
     393        56702 :                   && (REAL_EXP (&tmp2) - REAL_EXP (&tmp)
     394        56702 :                       >= 2 - REAL_MODE_FORMAT (mode)->p))
     395        56701 :                 round = false;
     396              :             }
     397              :         }
     398              :     }
     399     14768772 :   if (round && (inexact || !real_identical (&result, &value)))
     400              :     {
     401      1228032 :       if (mode_composite
     402      1228032 :           && (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      1228032 :         frange_nextafter (mode, result, inf);
     412              :     }
     413     15100239 :   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     15100239 : }
     436              : 
     437              : // Crop R to [-INF, MAX] where MAX is the maximum representable number
     438              : // for TYPE.
     439              : 
     440              : static inline void
     441       171300 : frange_drop_inf (frange &r, tree type)
     442              : {
     443       171300 :   REAL_VALUE_TYPE max = real_max_representable (type);
     444       171300 :   frange tmp (type, r.lower_bound (), max);
     445       171300 :   r.intersect (tmp);
     446       171300 : }
     447              : 
     448              : // Crop R to [MIN, +INF] where MIN is the minimum representable number
     449              : // for TYPE.
     450              : 
     451              : static inline void
     452        90645 : frange_drop_ninf (frange &r, tree type)
     453              : {
     454        90645 :   REAL_VALUE_TYPE min = real_min_representable (type);
     455        90645 :   frange tmp (type, min, r.upper_bound ());
     456        90645 :   r.intersect (tmp);
     457        90645 : }
     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      1303823 : frange_drop_infs (frange &r, tree type)
     464              : {
     465      1303823 :   REAL_VALUE_TYPE max = real_max_representable (type);
     466      1303823 :   REAL_VALUE_TYPE min = real_min_representable (type);
     467      1303823 :   frange tmp (type, min, max);
     468      1303823 :   r.intersect (tmp);
     469      1303823 : }
     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       906976 : frange_add_zeros (frange &r, tree type)
     475              : {
     476       906976 :   if (r.undefined_p () || r.known_isnan ())
     477              :     return;
     478              : 
     479       906976 :   if (HONOR_SIGNED_ZEROS (type)
     480       906976 :       && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
     481              :     {
     482       158548 :       frange zero;
     483       158548 :       zero.set_zero (type);
     484       158548 :       r.union_ (zero);
     485       158548 :     }
     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       253060 : build_le (frange &r, tree type, const frange &val)
     494              : {
     495       253060 :   gcc_checking_assert (!val.known_isnan ());
     496              : 
     497       253060 :   REAL_VALUE_TYPE ninf = frange_val_min (type);
     498       253060 :   r.set (type, ninf, val.upper_bound ());
     499              : 
     500              :   // Add both zeros if there's the possibility of zero equality.
     501       253060 :   frange_add_zeros (r, type);
     502              : 
     503       253060 :   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       300779 : build_lt (frange &r, tree type, const frange &val)
     512              : {
     513       300779 :   gcc_checking_assert (!val.known_isnan ());
     514              : 
     515              :   // < -INF is outside the range.
     516       300779 :   if (real_isinf (&val.upper_bound (), 1))
     517              :     {
     518         1460 :       if (HONOR_NANS (type))
     519         1460 :         r.set_nan (type);
     520              :       else
     521            0 :         r.set_undefined ();
     522         1460 :       return false;
     523              :     }
     524              : 
     525       299319 :   REAL_VALUE_TYPE ninf = frange_val_min (type);
     526       299319 :   REAL_VALUE_TYPE prev = val.upper_bound ();
     527       299319 :   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      2095233 :   if (!MODE_COMPOSITE_P (mode))
     533       299319 :     frange_nextafter (mode, prev, ninf);
     534       299319 :   r.set (type, ninf, prev);
     535       299319 :   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       380824 : build_ge (frange &r, tree type, const frange &val)
     544              : {
     545       380824 :   gcc_checking_assert (!val.known_isnan ());
     546              : 
     547       380824 :   REAL_VALUE_TYPE inf = frange_val_max (type);
     548       380824 :   r.set (type, val.lower_bound (), inf);
     549              : 
     550              :   // Add both zeros if there's the possibility of zero equality.
     551       380824 :   frange_add_zeros (r, type);
     552              : 
     553       380824 :   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       201556 : build_gt (frange &r, tree type, const frange &val)
     562              : {
     563       201556 :   gcc_checking_assert (!val.known_isnan ());
     564              : 
     565              :   // > +INF is outside the range.
     566       201556 :   if (real_isinf (&val.lower_bound (), 0))
     567              :     {
     568         3239 :       if (HONOR_NANS (type))
     569         3239 :         r.set_nan (type);
     570              :       else
     571            0 :         r.set_undefined ();
     572         3239 :       return false;
     573              :     }
     574              : 
     575       198317 :   REAL_VALUE_TYPE inf = frange_val_max (type);
     576       198317 :   REAL_VALUE_TYPE next = val.lower_bound ();
     577       198317 :   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      1388219 :   if (!MODE_COMPOSITE_P (mode))
     583       198317 :     frange_nextafter (mode, next, inf);
     584       198317 :   r.set (type, next, inf);
     585       198317 :   return true;
     586              : }
     587              : 
     588              : 
     589              : bool
     590        55170 : operator_identity::fold_range (frange &r, tree, const frange &op1,
     591              :                                const frange &, relation_trio) const
     592              : {
     593        55170 :   r = op1;
     594        55170 :   return true;
     595              : }
     596              : 
     597              : bool
     598        17024 : operator_identity::op1_range (frange &r, tree, const frange &lhs,
     599              :                               const frange &, relation_trio) const
     600              : {
     601        17024 :   r = lhs;
     602        17024 :   return true;
     603              : }
     604              : 
     605              : bool
     606         1118 : operator_cst::fold_range (frange &r, tree, const frange &op1,
     607              :                           const frange &, relation_trio) const
     608              : {
     609         1118 :   r = op1;
     610         1118 :   return true;
     611              : }
     612              : 
     613              : bool
     614        25564 : operator_equal::op2_range (frange &r, tree type,
     615              :                            const irange &lhs, const frange &op1,
     616              :                            relation_trio rel) const
     617              : {
     618        25564 :   return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
     619              : }
     620              : 
     621              : bool
     622       175755 : operator_equal::fold_range (irange &r, tree type,
     623              :                             const frange &op1, const frange &op2,
     624              :                             relation_trio rel) const
     625              : {
     626       175755 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
     627              :     return true;
     628              : 
     629       173392 :   if (op1.known_isnan () || op2.known_isnan ())
     630          525 :     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       172867 :   else if (op1.singleton_p () && op2.singleton_p ())
     634              :     {
     635          458 :       if (op1 == op2)
     636          110 :         r = range_true (type);
     637              :       // If one operand is -0.0 and other 0.0, they are still equal.
     638          348 :       else if (real_iszero (&op1.lower_bound ())
     639          348 :                && real_iszero (&op2.lower_bound ()))
     640           29 :         r = range_true (type);
     641              :       else
     642          319 :         r = range_false (type);
     643              :     }
     644       172409 :   else if (real_iszero (&op1.lower_bound ())
     645         5788 :            && real_iszero (&op1.upper_bound ())
     646          735 :            && real_iszero (&op2.lower_bound ())
     647          309 :            && real_iszero (&op2.upper_bound ())
     648       172718 :            && !maybe_isnan (op1, op2))
     649              :     // [-0.0, 0.0] == [-0.0, 0.0] or similar.
     650          166 :     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       172243 :       frange tmp = op1;
     656       172243 :       tmp.intersect (op2);
     657       172243 :       if (tmp.undefined_p ())
     658              :         {
     659              :           // If one range is [whatever, -0.0] and another
     660              :           // [0.0, whatever2], we don't know anything either,
     661              :           // because -0.0 == 0.0.
     662          612 :           if ((real_iszero (&op1.upper_bound ())
     663           59 :                && real_iszero (&op2.lower_bound ()))
     664          615 :               || (real_iszero (&op1.lower_bound ())
     665           37 :                   && real_iszero (&op2.upper_bound ())))
     666           56 :             r = range_true_and_false (type);
     667              :           else
     668          556 :             r = range_false (type);
     669              :         }
     670              :       else
     671       171631 :         r = range_true_and_false (type);
     672       172243 :     }
     673              :   return true;
     674              : }
     675              : 
     676              : bool
     677       135273 : operator_equal::op1_range (frange &r, tree type,
     678              :                            const irange &lhs,
     679              :                            const frange &op2,
     680              :                            relation_trio trio) const
     681              : {
     682       135273 :   relation_kind rel = trio.op1_op2 ();
     683       135273 :   switch (get_bool_state (r, lhs, type))
     684              :     {
     685        37875 :     case BRS_TRUE:
     686              :       // The TRUE side of x == NAN is unreachable.
     687        37875 :       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        37875 :           r = op2;
     693              :           // Add both zeros if there's the possibility of zero equality.
     694        37875 :           frange_add_zeros (r, type);
     695              :           // The TRUE side of op1 == op2 implies op1 is !NAN.
     696        37875 :           r.clear_nan ();
     697              :         }
     698              :       break;
     699              : 
     700        95640 :     case BRS_FALSE:
     701              :       // The FALSE side of op1 == op1 implies op1 is a NAN.
     702        95640 :       if (rel == VREL_EQ)
     703         2217 :         r.set_nan (type);
     704              :       // On the FALSE side of x == NAN, we know nothing about x.
     705        93423 :       else if (op2.known_isnan ())
     706            0 :         r.set_varying (type);
     707              :       // If the result is false, the only time we know anything is
     708              :       // if OP2 is a constant.
     709        93423 :       else if (op2.singleton_p ()
     710       102470 :                || (!op2.maybe_isnan () && op2.zero_p ()))
     711              :         {
     712        61110 :           REAL_VALUE_TYPE tmp = op2.lower_bound ();
     713        61110 :           r.set (type, tmp, tmp, VR_ANTI_RANGE);
     714              :         }
     715              :       else
     716        32313 :         r.set_varying (type);
     717              :       break;
     718              : 
     719              :     default:
     720              :       break;
     721              :     }
     722       135273 :   return true;
     723              : }
     724              : 
     725              : // Check if the LHS range indicates a relation between OP1 and OP2.
     726              : 
     727              : relation_kind
     728       133860 : operator_equal::op1_op2_relation (const irange &lhs, const frange &,
     729              :                                   const frange &) const
     730              : {
     731       133860 :   if (lhs.undefined_p ())
     732              :     return VREL_UNDEFINED;
     733              : 
     734              :   // FALSE = op1 == op2 indicates NE_EXPR.
     735       133860 :   if (lhs.zero_p ())
     736              :     return VREL_NE;
     737              : 
     738              :   // TRUE = op1 == op2 indicates EQ_EXPR.
     739        70099 :   if (!contains_zero_p (lhs))
     740        68525 :     return VREL_EQ;
     741              :   return VREL_VARYING;
     742              : }
     743              : 
     744              : bool
     745       850320 : operator_not_equal::fold_range (irange &r, tree type,
     746              :                                 const frange &op1, const frange &op2,
     747              :                                 relation_trio trio) const
     748              : {
     749       850320 :   relation_kind rel = trio.op1_op2 ();
     750              : 
     751              :   // VREL_NE & NE_EXPR is always true, even with NANs.
     752       850320 :   if (rel == VREL_NE)
     753              :     {
     754           26 :       r = range_true (type);
     755           26 :       return true;
     756              :     }
     757       850294 :   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        27072 :       if (empty_range_varying (r, type, op1, op2))
     764            5 :         return true;
     765              :     }
     766       823222 :   else if (frelop_early_resolve (r, type, op1, op2, trio, VREL_NE))
     767              :     return true;
     768              : 
     769              :   // x != NAN is always TRUE.
     770       848862 :   if (op1.known_isnan () || op2.known_isnan ())
     771         1271 :     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       847591 :   else if (op1.singleton_p () && op2.singleton_p ())
     775              :     {
     776         1024 :       if (op1 == op2)
     777          677 :         r = range_false (type);
     778              :       // If one operand is -0.0 and other 0.0, they are still equal.
     779          347 :       else if (real_iszero (&op1.lower_bound ())
     780          347 :                && real_iszero (&op2.lower_bound ()))
     781            0 :         r = range_false (type);
     782              :       else
     783          347 :         r = range_true (type);
     784              :     }
     785       846567 :   else if (real_iszero (&op1.lower_bound ())
     786         7102 :            && real_iszero (&op1.upper_bound ())
     787          367 :            && real_iszero (&op2.lower_bound ())
     788          188 :            && real_iszero (&op2.upper_bound ())
     789       846755 :            && !maybe_isnan (op1, op2))
     790              :     // [-0.0, 0.0] != [-0.0, 0.0] or similar.
     791          100 :     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       846467 :       frange tmp = op1;
     797       846467 :       tmp.intersect (op2);
     798       846467 :       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          542 :           if ((real_iszero (&op1.upper_bound ())
     804            5 :                && real_iszero (&op2.lower_bound ()))
     805          547 :               || (real_iszero (&op1.lower_bound ())
     806           10 :                   && real_iszero (&op2.upper_bound ())))
     807            0 :             r = range_true_and_false (type);
     808              :           else
     809          542 :             r = range_true (type);
     810              :         }
     811              :       else
     812       845925 :         r = range_true_and_false (type);
     813       846467 :     }
     814              :   return true;
     815              : }
     816              : 
     817              : bool
     818       284006 : operator_not_equal::op1_range (frange &r, tree type,
     819              :                                const irange &lhs,
     820              :                                const frange &op2,
     821              :                                relation_trio trio) const
     822              : {
     823       284006 :   relation_kind rel = trio.op1_op2 ();
     824       284006 :   switch (get_bool_state (r, lhs, type))
     825              :     {
     826        47050 :     case BRS_TRUE:
     827              :       // If the result is true, the only time we know anything is if
     828              :       // OP2 is a constant.
     829        47050 :       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        22987 :           REAL_VALUE_TYPE tmp = op2.lower_bound ();
     835        22987 :           r.set (type, tmp, tmp, VR_ANTI_RANGE);
     836              :         }
     837              :       // The TRUE side of op1 != op1 implies op1 is NAN.
     838        24063 :       else if (rel == VREL_EQ)
     839         5907 :         r.set_nan (type);
     840              :       else
     841        18156 :         r.set_varying (type);
     842              :       break;
     843              : 
     844       235374 :     case BRS_FALSE:
     845              :       // The FALSE side of x != NAN is impossible.
     846       235374 :       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       235204 :           r = op2;
     852              :           // Add both zeros if there's the possibility of zero equality.
     853       235204 :           frange_add_zeros (r, type);
     854              :           // The FALSE side of op1 != op2 implies op1 is !NAN.
     855       235204 :           r.clear_nan ();
     856              :         }
     857              :       break;
     858              : 
     859              :     default:
     860              :       break;
     861              :     }
     862       284006 :   return true;
     863              : }
     864              : 
     865              : bool
     866       183217 : operator_not_equal::op2_range (frange &r, tree type,
     867              :                                const irange &lhs,
     868              :                                const frange &op1,
     869              :                                relation_trio trio) const
     870              : {
     871       183217 :   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       634821 : operator_not_equal::op1_op2_relation (const irange &lhs, const frange &,
     878              :                                       const frange &) const
     879              : {
     880       634821 :   if (lhs.undefined_p ())
     881              :     return VREL_UNDEFINED;
     882              : 
     883              :   // FALSE = op1 != op2  indicates EQ_EXPR.
     884       634821 :   if (lhs.zero_p ())
     885              :     return VREL_EQ;
     886              : 
     887              :   // TRUE = op1 != op2  indicates NE_EXPR.
     888       118000 :   if (!contains_zero_p (lhs))
     889       116445 :     return VREL_NE;
     890              :   return VREL_VARYING;
     891              : }
     892              : 
     893              : bool
     894       269758 : operator_lt::fold_range (irange &r, tree type,
     895              :                          const frange &op1, const frange &op2,
     896              :                          relation_trio trio) const
     897              : {
     898       269758 :   if (frelop_early_resolve (r, type, op1, op2, trio, VREL_LT))
     899              :     return true;
     900              : 
     901       269217 :   if (op1.known_isnan ()
     902       268824 :       || op2.known_isnan ()
     903       537787 :       || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
     904         2641 :     r = range_false (type);
     905       266576 :   else if (!maybe_isnan (op1, op2)
     906       266576 :            && real_less (&op1.upper_bound (), &op2.lower_bound ()))
     907         1087 :     r = range_true (type);
     908              :   else
     909       265489 :     r = range_true_and_false (type);
     910              :   return true;
     911              : }
     912              : 
     913              : bool
     914       424477 : operator_lt::op1_range (frange &r,
     915              :                         tree type,
     916              :                         const irange &lhs,
     917              :                         const frange &op2,
     918              :                         relation_trio) const
     919              : {
     920       424477 :   switch (get_bool_state (r, lhs, type))
     921              :     {
     922       143949 :     case BRS_TRUE:
     923              :       // The TRUE side of x < NAN is unreachable.
     924       143949 :       if (op2.known_isnan ())
     925           68 :         r.set_undefined ();
     926       143881 :       else if (op2.undefined_p ())
     927              :         return false;
     928       143881 :       else if (build_lt (r, type, op2))
     929              :         {
     930       143881 :           r.clear_nan ();
     931              :           // x < y implies x is not +INF.
     932       143881 :           frange_drop_inf (r, type);
     933              :         }
     934              :       break;
     935              : 
     936       279954 :     case BRS_FALSE:
     937              :       // On the FALSE side of x < NAN, we know nothing about x.
     938       530639 :       if (op2.maybe_isnan ())
     939        29269 :         r.set_varying (type);
     940              :       else
     941       250685 :         build_ge (r, type, op2);
     942              :       break;
     943              : 
     944              :     default:
     945              :       break;
     946              :     }
     947              :   return true;
     948              : }
     949              : 
     950              : bool
     951        63804 : operator_lt::op2_range (frange &r,
     952              :                         tree type,
     953              :                         const irange &lhs,
     954              :                         const frange &op1,
     955              :                         relation_trio) const
     956              : {
     957        63804 :   switch (get_bool_state (r, lhs, type))
     958              :     {
     959        25809 :     case BRS_TRUE:
     960              :       // The TRUE side of NAN < x is unreachable.
     961        25809 :       if (op1.known_isnan ())
     962           22 :         r.set_undefined ();
     963        25787 :       else if (op1.undefined_p ())
     964              :         return false;
     965        25787 :       else if (build_gt (r, type, op1))
     966              :         {
     967        25787 :           r.clear_nan ();
     968              :           // x < y implies y is not -INF.
     969        25787 :           frange_drop_ninf (r, type);
     970              :         }
     971              :       break;
     972              : 
     973        37610 :     case BRS_FALSE:
     974              :       // On the FALSE side of NAN < x, we know nothing about x.
     975        41318 :       if (op1.maybe_isnan ())
     976        33902 :         r.set_varying (type);
     977              :       else
     978         3708 :         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       244525 : operator_lt::op1_op2_relation (const irange &lhs, const frange &,
     992              :                                const frange &) const
     993              : {
     994       244525 :   if (lhs.undefined_p ())
     995              :     return VREL_UNDEFINED;
     996              : 
     997              :   // FALSE = op1 < op2 indicates GE_EXPR.
     998       244525 :   if (lhs.zero_p ())
     999              :     return VREL_GE;
    1000              : 
    1001              :   // TRUE = op1 < op2 indicates LT_EXPR.
    1002       112202 :   if (!contains_zero_p (lhs))
    1003       111462 :     return VREL_LT;
    1004              :   return VREL_VARYING;
    1005              : }
    1006              : 
    1007              : bool
    1008       271508 : operator_le::fold_range (irange &r, tree type,
    1009              :                          const frange &op1, const frange &op2,
    1010              :                          relation_trio rel) const
    1011              : {
    1012       271508 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
    1013              :     return true;
    1014              : 
    1015       270919 :   if (op1.known_isnan ()
    1016       269917 :       || op2.known_isnan ()
    1017       540794 :       || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1018         2463 :     r = range_false (type);
    1019       268456 :   else if (!maybe_isnan (op1, op2)
    1020       268456 :            && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1021          776 :     r = range_true (type);
    1022              :   else
    1023       267680 :     r = range_true_and_false (type);
    1024              :   return true;
    1025              : }
    1026              : 
    1027              : bool
    1028        98104 : operator_le::op1_range (frange &r,
    1029              :                         tree type,
    1030              :                         const irange &lhs,
    1031              :                         const frange &op2,
    1032              :                         relation_trio) const
    1033              : {
    1034        98104 :   switch (get_bool_state (r, lhs, type))
    1035              :     {
    1036        67703 :     case BRS_TRUE:
    1037              :       // The TRUE side of x <= NAN is unreachable.
    1038        67703 :       if (op2.known_isnan ())
    1039            0 :         r.set_undefined ();
    1040        67703 :       else if (op2.undefined_p ())
    1041              :         return false;
    1042        67703 :       else if (build_le (r, type, op2))
    1043        67703 :         r.clear_nan ();
    1044              :       break;
    1045              : 
    1046        30068 :     case BRS_FALSE:
    1047              :       // On the FALSE side of x <= NAN, we know nothing about x.
    1048        55393 :       if (op2.maybe_isnan ())
    1049         4743 :         r.set_varying (type);
    1050              :       else
    1051        25325 :         build_gt (r, type, op2);
    1052              :       break;
    1053              : 
    1054              :     default:
    1055              :       break;
    1056              :     }
    1057              :   return true;
    1058              : }
    1059              : 
    1060              : bool
    1061        14995 : operator_le::op2_range (frange &r,
    1062              :                         tree type,
    1063              :                         const irange &lhs,
    1064              :                         const frange &op1,
    1065              :                         relation_trio) const
    1066              : {
    1067        14995 :   switch (get_bool_state (r, lhs, type))
    1068              :     {
    1069         4088 :     case BRS_TRUE:
    1070              :       // The TRUE side of NAN <= x is unreachable.
    1071         4088 :       if (op1.known_isnan ())
    1072            0 :         r.set_undefined ();
    1073         4088 :       else if (op1.undefined_p ())
    1074              :         return false;
    1075         4088 :       else if (build_ge (r, type, op1))
    1076         4088 :         r.clear_nan ();
    1077              :       break;
    1078              : 
    1079        10610 :     case BRS_FALSE:
    1080              :       // On the FALSE side of NAN <= x, we know nothing about x.
    1081        11452 :       if (op1.maybe_isnan ())
    1082         9768 :         r.set_varying (type);
    1083          842 :       else if (op1.undefined_p ())
    1084              :         return false;
    1085              :       else
    1086          842 :         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        60969 : operator_le::op1_op2_relation (const irange &lhs, const frange &,
    1099              :                                const frange &) const
    1100              : {
    1101        60969 :   if (lhs.undefined_p ())
    1102              :     return VREL_UNDEFINED;
    1103              : 
    1104              :   // FALSE = op1 <= op2 indicates GT_EXPR.
    1105        60969 :   if (lhs.zero_p ())
    1106              :     return VREL_GT;
    1107              : 
    1108              :   // TRUE = op1 <= op2 indicates LE_EXPR.
    1109        30729 :   if (!contains_zero_p (lhs))
    1110        30131 :     return VREL_LE;
    1111              :   return VREL_VARYING;
    1112              : }
    1113              : 
    1114              : bool
    1115       260996 : operator_gt::fold_range (irange &r, tree type,
    1116              :                          const frange &op1, const frange &op2,
    1117              :                          relation_trio trio) const
    1118              : {
    1119       260996 :   if (frelop_early_resolve (r, type, op1, op2, trio, VREL_GT))
    1120              :     return true;
    1121              : 
    1122       260227 :   if (op1.known_isnan ()
    1123       259884 :       || op2.known_isnan ()
    1124       519787 :       || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1125         3940 :     r = range_false (type);
    1126       256287 :   else if (!maybe_isnan (op1, op2)
    1127       256287 :            && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1128          689 :     r = range_true (type);
    1129              :   else
    1130       255598 :     r = range_true_and_false (type);
    1131              :   return true;
    1132              : }
    1133              : 
    1134              : bool
    1135       168763 : operator_gt::op1_range (frange &r,
    1136              :                         tree type,
    1137              :                         const irange &lhs,
    1138              :                         const frange &op2,
    1139              :                         relation_trio) const
    1140              : {
    1141       168763 :   switch (get_bool_state (r, lhs, type))
    1142              :     {
    1143        64886 :     case BRS_TRUE:
    1144              :       // The TRUE side of x > NAN is unreachable.
    1145        64886 :       if (op2.known_isnan ())
    1146           28 :         r.set_undefined ();
    1147        64858 :       else if (op2.undefined_p ())
    1148              :         return false;
    1149        64858 :       else if (build_gt (r, type, op2))
    1150              :         {
    1151        64858 :           r.clear_nan ();
    1152              :           // x > y implies x is not -INF.
    1153        64858 :           frange_drop_ninf (r, type);
    1154              :         }
    1155              :       break;
    1156              : 
    1157       103136 :     case BRS_FALSE:
    1158              :       // On the FALSE side of x > NAN, we know nothing about x.
    1159       177543 :       if (op2.maybe_isnan ())
    1160        28729 :         r.set_varying (type);
    1161        74407 :       else if (op2.undefined_p ())
    1162              :         return false;
    1163              :       else
    1164        74407 :         build_le (r, type, op2);
    1165              :       break;
    1166              : 
    1167              :     default:
    1168              :       break;
    1169              :     }
    1170              :   return true;
    1171              : }
    1172              : 
    1173              : bool
    1174        69995 : operator_gt::op2_range (frange &r,
    1175              :                         tree type,
    1176              :                         const irange &lhs,
    1177              :                         const frange &op1,
    1178              :                         relation_trio) const
    1179              : {
    1180        69995 :   switch (get_bool_state (r, lhs, type))
    1181              :     {
    1182        27441 :     case BRS_TRUE:
    1183              :       // The TRUE side of NAN > x is unreachable.
    1184        27441 :       if (op1.known_isnan ())
    1185           22 :         r.set_undefined ();
    1186        27419 :       else if (op1.undefined_p ())
    1187              :         return false;
    1188        27419 :       else if (build_lt (r, type, op1))
    1189              :         {
    1190        27419 :           r.clear_nan ();
    1191              :           // x > y implies y is not +INF.
    1192        27419 :           frange_drop_inf (r, type);
    1193              :         }
    1194              :       break;
    1195              : 
    1196        42147 :     case BRS_FALSE:
    1197              :       // On The FALSE side of NAN > x, we know nothing about x.
    1198        45527 :       if (op1.maybe_isnan ())
    1199        38767 :         r.set_varying (type);
    1200         3380 :       else if (op1.undefined_p ())
    1201              :         return false;
    1202              :       else
    1203         3380 :         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       266577 : operator_gt::op1_op2_relation (const irange &lhs, const frange &,
    1216              :                                const frange &) const
    1217              : {
    1218       266577 :   if (lhs.undefined_p ())
    1219              :     return VREL_UNDEFINED;
    1220              : 
    1221              :   // FALSE = op1 > op2 indicates LE_EXPR.
    1222       266577 :   if (lhs.zero_p ())
    1223              :     return VREL_LE;
    1224              : 
    1225              :   // TRUE = op1 > op2 indicates GT_EXPR.
    1226       119629 :   if (!contains_zero_p (lhs))
    1227       118779 :     return VREL_GT;
    1228              :   return VREL_VARYING;
    1229              : }
    1230              : 
    1231              : bool
    1232       268801 : operator_ge::fold_range (irange &r, tree type,
    1233              :                          const frange &op1, const frange &op2,
    1234              :                          relation_trio rel) const
    1235              : {
    1236       268801 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
    1237              :     return true;
    1238              : 
    1239       268424 :   if (op1.known_isnan ()
    1240       267608 :       || op2.known_isnan ()
    1241       535988 :       || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1242         1503 :     r = range_false (type);
    1243       266921 :   else if (!maybe_isnan (op1, op2)
    1244       266921 :            && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1245         2457 :     r = range_true (type);
    1246              :   else
    1247       264464 :     r = range_true_and_false (type);
    1248              :   return true;
    1249              : }
    1250              : 
    1251              : bool
    1252       108130 : operator_ge::op1_range (frange &r,
    1253              :                         tree type,
    1254              :                         const irange &lhs,
    1255              :                         const frange &op2,
    1256              :                         relation_trio) const
    1257              : {
    1258       108130 :   switch (get_bool_state (r, lhs, type))
    1259              :     {
    1260        60009 :     case BRS_TRUE:
    1261              :       // The TRUE side of x >= NAN is unreachable.
    1262        60009 :       if (op2.known_isnan ())
    1263            0 :         r.set_undefined ();
    1264        60009 :       else if (op2.undefined_p ())
    1265              :         return false;
    1266        60009 :       else if (build_ge (r, type, op2))
    1267        60009 :         r.clear_nan ();
    1268              :       break;
    1269              : 
    1270        47824 :     case BRS_FALSE:
    1271              :       // On the FALSE side of x >= NAN, we know nothing about x.
    1272        88865 :       if (op2.maybe_isnan ())
    1273         6783 :         r.set_varying (type);
    1274        41041 :       else if (op2.undefined_p ())
    1275              :         return false;
    1276              :       else
    1277        41041 :         build_lt (r, type, op2);
    1278              :       break;
    1279              : 
    1280              :     default:
    1281              :       break;
    1282              :     }
    1283              :   return true;
    1284              : }
    1285              : 
    1286              : bool
    1287        13488 : operator_ge::op2_range (frange &r, tree type,
    1288              :                         const irange &lhs,
    1289              :                         const frange &op1,
    1290              :                         relation_trio) const
    1291              : {
    1292        13488 :   switch (get_bool_state (r, lhs, type))
    1293              :     {
    1294         5497 :     case BRS_TRUE:
    1295              :       // The TRUE side of NAN >= x is unreachable.
    1296         5497 :       if (op1.known_isnan ())
    1297            0 :         r.set_undefined ();
    1298         5497 :       else if (op1.undefined_p ())
    1299              :         return false;
    1300         5497 :       else if (build_le (r, type, op1))
    1301         5497 :         r.clear_nan ();
    1302              :       break;
    1303              : 
    1304         7730 :     case BRS_FALSE:
    1305              :       // On the FALSE side of NAN >= x, we know nothing about x.
    1306         8499 :       if (op1.maybe_isnan ())
    1307         6961 :         r.set_varying (type);
    1308          769 :       else if (op1.undefined_p ())
    1309              :         return false;
    1310              :       else
    1311          769 :         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        58419 : operator_ge::op1_op2_relation (const irange &lhs, const frange &,
    1324              :                                const frange &) const
    1325              : {
    1326        58419 :   if (lhs.undefined_p ())
    1327              :     return VREL_UNDEFINED;
    1328              : 
    1329              :   // FALSE = op1 >= op2 indicates LT_EXPR.
    1330        58419 :   if (lhs.zero_p ())
    1331              :     return VREL_LT;
    1332              : 
    1333              :   // TRUE = op1 >= op2 indicates GE_EXPR.
    1334        30518 :   if (!contains_zero_p (lhs))
    1335        29992 :     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        56399 :   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        56399 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    1358              :   }
    1359              : };
    1360              : static const foperator_unordered fop_unordered;
    1361              : 
    1362              : bool
    1363        54985 : 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        54985 :   if (op1.known_isnan () || op2.known_isnan ())
    1369          115 :     r = range_true (type);
    1370              :   // UNORDERED is FALSE if neither operand is a NAN.
    1371        57322 :   else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
    1372         1228 :     r = range_false (type);
    1373              :   else
    1374        53642 :     r = range_true_and_false (type);
    1375        54985 :   return true;
    1376              : }
    1377              : 
    1378              : bool
    1379       103067 : foperator_unordered::op1_range (frange &r, tree type,
    1380              :                                 const irange &lhs,
    1381              :                                 const frange &op2,
    1382              :                                 relation_trio trio) const
    1383              : {
    1384       103067 :   relation_kind rel = trio.op1_op2 ();
    1385       103067 :   switch (get_bool_state (r, lhs, type))
    1386              :     {
    1387        37802 :     case BRS_TRUE:
    1388              :       // Since at least one operand must be NAN, if one of them is
    1389              :       // not, the other must be.
    1390        37802 :       if (rel == VREL_EQ || !op2.maybe_isnan ())
    1391         9589 :         r.set_nan (type);
    1392              :       else
    1393        28213 :         r.set_varying (type);
    1394              :       break;
    1395              : 
    1396        57422 :     case BRS_FALSE:
    1397              :       // A false UNORDERED means both operands are !NAN, so it's
    1398              :       // impossible for op2 to be a NAN.
    1399        57422 :       if (op2.known_isnan ())
    1400            0 :         r.set_undefined ();
    1401              :       else
    1402              :         {
    1403        57422 :           r.set_varying (type);
    1404        57422 :           r.clear_nan ();
    1405              :         }
    1406              :       break;
    1407              : 
    1408              :     default:
    1409              :       break;
    1410              :     }
    1411       103067 :   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        30034 :   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        30034 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    1433              :   }
    1434              : };
    1435              : static const foperator_ordered fop_ordered;
    1436              : 
    1437              : bool
    1438        32814 : foperator_ordered::fold_range (irange &r, tree type,
    1439              :                                const frange &op1, const frange &op2,
    1440              :                                relation_trio) const
    1441              : {
    1442        32814 :   if (op1.known_isnan () || op2.known_isnan ())
    1443          360 :     r = range_false (type);
    1444        35368 :   else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
    1445         1450 :     r = range_true (type);
    1446              :   else
    1447        31004 :     r = range_true_and_false (type);
    1448        32814 :   return true;
    1449              : }
    1450              : 
    1451              : bool
    1452        63925 : foperator_ordered::op1_range (frange &r, tree type,
    1453              :                               const irange &lhs,
    1454              :                               const frange &op2,
    1455              :                               relation_trio trio) const
    1456              : {
    1457        63925 :   relation_kind rel = trio.op1_op2 ();
    1458        63925 :   switch (get_bool_state (r, lhs, type))
    1459              :     {
    1460        57316 :     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        57316 :       if (op2.known_isnan ())
    1464           10 :         r.set_undefined ();
    1465              :       else
    1466              :         {
    1467        57306 :           r.set_varying (type);
    1468        57306 :           r.clear_nan ();
    1469              :         }
    1470              :       break;
    1471              : 
    1472         4626 :     case BRS_FALSE:
    1473              :       // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
    1474         4626 :       if (rel == VREL_EQ)
    1475         2111 :         r.set_nan (type);
    1476              :       else
    1477         2515 :         r.set_varying (type);
    1478              :       break;
    1479              : 
    1480              :     default:
    1481              :       break;
    1482              :     }
    1483        63925 :   return true;
    1484              : }
    1485              : 
    1486              : bool
    1487       241330 : operator_negate::fold_range (frange &r, tree type,
    1488              :                              const frange &op1, const frange &op2,
    1489              :                              relation_trio) const
    1490              : {
    1491       241330 :   if (empty_range_varying (r, type, op1, op2))
    1492          426 :     return true;
    1493       240904 :   if (op1.known_isnan ())
    1494              :     {
    1495          398 :       bool sign;
    1496          398 :       if (op1.nan_signbit_p (sign))
    1497           38 :         r.set_nan (type, !sign);
    1498              :       else
    1499          360 :         r.set_nan (type);
    1500          398 :       return true;
    1501              :     }
    1502              : 
    1503       240506 :   REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
    1504       240506 :   REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
    1505       240506 :   lh_lb = real_value_negate (&lh_lb);
    1506       240506 :   lh_ub = real_value_negate (&lh_ub);
    1507       240506 :   r.set (type, lh_ub, lh_lb);
    1508       430184 :   if (op1.maybe_isnan ())
    1509              :     {
    1510        50832 :       bool sign;
    1511        50832 :       if (op1.nan_signbit_p (sign))
    1512         2372 :         r.update_nan (!sign);
    1513              :       else
    1514        48460 :         r.update_nan ();
    1515              :     }
    1516              :   else
    1517       189674 :     r.clear_nan ();
    1518              :   return true;
    1519              : }
    1520              : 
    1521              : bool
    1522         3130 : operator_negate::op1_range (frange &r, tree type,
    1523              :                             const frange &lhs, const frange &op2,
    1524              :                             relation_trio rel) const
    1525              : {
    1526         3130 :   return fold_range (r, type, lhs, op2, rel);
    1527              : }
    1528              : 
    1529              : bool
    1530       558015 : operator_abs::fold_range (frange &r, tree type,
    1531              :                           const frange &op1, const frange &op2,
    1532              :                           relation_trio) const
    1533              : {
    1534       558015 :   if (empty_range_varying (r, type, op1, op2))
    1535          113 :     return true;
    1536       557902 :   if (op1.known_isnan ())
    1537              :     {
    1538          588 :       r.set_nan (type, /*sign=*/false);
    1539          588 :       return true;
    1540              :     }
    1541              : 
    1542       557314 :   const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
    1543       557314 :   const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
    1544              :   // Handle the easy case where everything is positive.
    1545       557314 :   if (real_compare (GE_EXPR, &lh_lb, &dconst0)
    1546       159761 :       && !real_iszero (&lh_lb, /*sign=*/true)
    1547       714507 :       && !op1.maybe_isnan (/*sign=*/true))
    1548              :     {
    1549       156828 :       r = op1;
    1550       156828 :       return true;
    1551              :     }
    1552              : 
    1553       400486 :   REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
    1554       400486 :   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       400486 :   if (real_compare (LE_EXPR, &lh_lb, &dconst0)
    1558       400486 :       && real_compare (GE_EXPR, &lh_ub, &dconst0))
    1559              :     {
    1560       399617 :       if (real_compare (GT_EXPR, &min, &max))
    1561         4791 :         max = min;
    1562       399617 :       min = dconst0;
    1563              :     }
    1564              :   else
    1565              :     {
    1566              :       // If the range was reversed, swap MIN and MAX.
    1567          869 :       if (real_compare (GT_EXPR, &min, &max))
    1568          790 :         std::swap (min, max);
    1569              :     }
    1570              : 
    1571       400486 :   r.set (type, min, max);
    1572       425704 :   if (op1.maybe_isnan ())
    1573       376431 :     r.update_nan (/*sign=*/false);
    1574              :   else
    1575        24055 :     r.clear_nan ();
    1576              :   return true;
    1577              : }
    1578              : 
    1579              : bool
    1580       320737 : operator_abs::op1_range (frange &r, tree type,
    1581              :                          const frange &lhs, const frange &op2,
    1582              :                          relation_trio) const
    1583              : {
    1584       320737 :   if (empty_range_varying (r, type, lhs, op2))
    1585            0 :     return true;
    1586       320737 :   if (lhs.known_isnan ())
    1587              :     {
    1588         2805 :       r.set_nan (type);
    1589         2805 :       return true;
    1590              :     }
    1591              : 
    1592              :   // Start with the positives because negatives are an impossible result.
    1593       317932 :   frange positives (type, dconst0, frange_val_max (type));
    1594       317932 :   positives.update_nan (/*sign=*/false);
    1595       317932 :   positives.intersect (lhs);
    1596       317932 :   r = positives;
    1597              :   // Add -NAN if relevant.
    1598       480752 :   if (r.maybe_isnan ())
    1599              :     {
    1600       155052 :       frange neg_nan;
    1601       155052 :       neg_nan.set_nan (type, true);
    1602       155052 :       r.union_ (neg_nan);
    1603       155052 :     }
    1604       317932 :   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       317860 :   frange negatives (type, real_value_negate (&positives.upper_bound ()),
    1609       317860 :                     real_value_negate (&positives.lower_bound ()));
    1610       317860 :   negatives.clear_nan ();
    1611       317860 :   r.union_ (negatives);
    1612       317860 :   return true;
    1613       635792 : }
    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        11060 :   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        11060 :     if (op1.known_isnan () || op2.known_isnan ())
    1626              :       {
    1627           33 :         r = range_true (type);
    1628           33 :         return true;
    1629              :       }
    1630        11027 :     frange op1_no_nan = op1;
    1631        11027 :     frange op2_no_nan = op2;
    1632        13632 :     if (op1.maybe_isnan ())
    1633         8406 :       op1_no_nan.clear_nan ();
    1634        18488 :     if (op2.maybe_isnan ())
    1635         3566 :       op2_no_nan.clear_nan ();
    1636        11027 :     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        11027 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1642              :       return true;
    1643              :     else
    1644              :       {
    1645         8302 :         r = range_true_and_false (type);
    1646         8302 :         return true;
    1647              :       }
    1648        11027 :   }
    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         3586 : foperator_unordered_lt::op1_range (frange &r, tree type,
    1662              :                                    const irange &lhs,
    1663              :                                    const frange &op2,
    1664              :                                    relation_trio) const
    1665              : {
    1666         3586 :   switch (get_bool_state (r, lhs, type))
    1667              :     {
    1668         1722 :     case BRS_TRUE:
    1669         3388 :       if (op2.maybe_isnan ())
    1670           56 :         r.set_varying (type);
    1671         1666 :       else if (op2.undefined_p ())
    1672              :         return false;
    1673              :       else
    1674         1666 :         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       180058 :   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       180058 :     if (op1.known_isnan () || op2.known_isnan ())
    1739              :       {
    1740           98 :         r = range_true (type);
    1741           98 :         return true;
    1742              :       }
    1743       179960 :     frange op1_no_nan = op1;
    1744       179960 :     frange op2_no_nan = op2;
    1745       206042 :     if (op1.maybe_isnan ())
    1746       153852 :       op1_no_nan.clear_nan ();
    1747       352735 :     if (op2.maybe_isnan ())
    1748         7179 :       op2_no_nan.clear_nan ();
    1749       179960 :     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       179960 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1755              :       return true;
    1756              :     else
    1757              :       {
    1758       155616 :         r = range_true_and_false (type);
    1759       155616 :         return true;
    1760              :       }
    1761       179960 :   }
    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       167157 : foperator_unordered_le::op1_range (frange &r, tree type,
    1773              :                                    const irange &lhs, const frange &op2,
    1774              :                                    relation_trio) const
    1775              : {
    1776       167157 :   switch (get_bool_state (r, lhs, type))
    1777              :     {
    1778        92205 :     case BRS_TRUE:
    1779       179293 :       if (op2.maybe_isnan ())
    1780         5117 :         r.set_varying (type);
    1781        87088 :       else if (op2.undefined_p ())
    1782              :         return false;
    1783              :       else
    1784        87088 :         build_le (r, type, op2);
    1785              :       break;
    1786              : 
    1787        74310 :     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        74310 :       if (op2.known_isnan ())
    1791            0 :         r.set_undefined ();
    1792        74310 :       else if (build_gt (r, type, op2))
    1793        74308 :         r.clear_nan ();
    1794              :       break;
    1795              : 
    1796              :     default:
    1797              :       break;
    1798              :     }
    1799              :   return true;
    1800              : }
    1801              : 
    1802              : bool
    1803        14098 : foperator_unordered_le::op2_range (frange &r,
    1804              :                                    tree type,
    1805              :                                    const irange &lhs,
    1806              :                                    const frange &op1,
    1807              :                                    relation_trio) const
    1808              : {
    1809        14098 :   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         3605 :     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         3605 :       if (op1.known_isnan ())
    1824            0 :         r.set_undefined ();
    1825         3605 :       else if (op1.undefined_p ())
    1826              :         return false;
    1827         3605 :       else if (build_lt (r, type, op1))
    1828         3605 :         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        35422 :   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        35422 :     if (op1.known_isnan () || op2.known_isnan ())
    1848              :       {
    1849          157 :         r = range_true (type);
    1850          157 :         return true;
    1851              :       }
    1852        35265 :     frange op1_no_nan = op1;
    1853        35265 :     frange op2_no_nan = op2;
    1854        38712 :     if (op1.maybe_isnan ())
    1855        31799 :       op1_no_nan.clear_nan ();
    1856        66872 :     if (op2.maybe_isnan ())
    1857         3658 :       op2_no_nan.clear_nan ();
    1858        35265 :     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        35265 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1864              :       return true;
    1865              :     else
    1866              :       {
    1867        31692 :         r = range_true_and_false (type);
    1868        31692 :         return true;
    1869              :       }
    1870        35265 :   }
    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        16076 : foperator_unordered_gt::op1_range (frange &r,
    1882              :                                    tree type,
    1883              :                                    const irange &lhs,
    1884              :                                    const frange &op2,
    1885              :                                    relation_trio) const
    1886              : {
    1887        16076 :   switch (get_bool_state (r, lhs, type))
    1888              :     {
    1889         5195 :     case BRS_TRUE:
    1890        10314 :       if (op2.maybe_isnan ())
    1891           76 :         r.set_varying (type);
    1892         5119 :       else if (op2.undefined_p ())
    1893              :         return false;
    1894              :       else
    1895         5119 :         build_gt (r, type, op2);
    1896              :       break;
    1897              : 
    1898        10283 :     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        10283 :       if (op2.known_isnan ())
    1902            0 :         r.set_undefined ();
    1903        10283 :       else if (op2.undefined_p ())
    1904              :         return false;
    1905        10283 :       else if (build_le (r, type, op2))
    1906        10283 :         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       173308 :   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       173308 :     if (op1.known_isnan () || op2.known_isnan ())
    1961              :       {
    1962           47 :         r = range_true (type);
    1963           47 :         return true;
    1964              :       }
    1965       173261 :     frange op1_no_nan = op1;
    1966       173261 :     frange op2_no_nan = op2;
    1967       186761 :     if (op1.maybe_isnan ())
    1968       159700 :       op1_no_nan.clear_nan ();
    1969       339433 :     if (op2.maybe_isnan ())
    1970         7083 :       op2_no_nan.clear_nan ();
    1971       173261 :     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       173261 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1977              :       return true;
    1978              :     else
    1979              :       {
    1980       159840 :         r = range_true_and_false (type);
    1981       159840 :         return true;
    1982              :       }
    1983       173261 :   }
    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       144094 : foperator_unordered_ge::op1_range (frange &r,
    1995              :                                    tree type,
    1996              :                                    const irange &lhs,
    1997              :                                    const frange &op2,
    1998              :                                    relation_trio) const
    1999              : {
    2000       144094 :   switch (get_bool_state (r, lhs, type))
    2001              :     {
    2002        61065 :     case BRS_TRUE:
    2003       117485 :       if (op2.maybe_isnan ())
    2004         4645 :         r.set_varying (type);
    2005        56420 :       else if (op2.undefined_p ())
    2006              :         return false;
    2007              :       else
    2008        56420 :         build_ge (r, type, op2);
    2009              :       break;
    2010              : 
    2011        82325 :     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        82325 :       if (op2.known_isnan ())
    2015            0 :         r.set_undefined ();
    2016        82325 :       else if (op2.undefined_p ())
    2017              :         return false;
    2018        82325 :       else if (build_lt (r, type, op2))
    2019        82321 :         r.clear_nan ();
    2020              :       break;
    2021              : 
    2022              :     default:
    2023              :       break;
    2024              :     }
    2025              :   return true;
    2026              : }
    2027              : 
    2028              : bool
    2029        14833 : foperator_unordered_ge::op2_range (frange &r, tree type,
    2030              :                                    const irange &lhs,
    2031              :                                    const frange &op1,
    2032              :                                    relation_trio) const
    2033              : {
    2034        14833 :   switch (get_bool_state (r, lhs, type))
    2035              :     {
    2036         8861 :     case BRS_TRUE:
    2037        13235 :       if (op1.maybe_isnan ())
    2038         4487 :         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         5388 :     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         5388 :       if (op1.known_isnan ())
    2049            0 :         r.set_undefined ();
    2050         5388 :       else if (op1.undefined_p ())
    2051              :         return false;
    2052         5388 :       else if (build_gt (r, type, op1))
    2053         5388 :         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         3611 :   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         3611 :     if (op1.known_isnan () || op2.known_isnan ())
    2073              :       {
    2074            0 :         r = range_true (type);
    2075            0 :         return true;
    2076              :       }
    2077         3611 :     frange op1_no_nan = op1;
    2078         3611 :     frange op2_no_nan = op2;
    2079         3931 :     if (op1.maybe_isnan ())
    2080         3291 :       op1_no_nan.clear_nan ();
    2081         4032 :     if (op2.maybe_isnan ())
    2082         3190 :       op2_no_nan.clear_nan ();
    2083         3611 :     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         3611 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    2089              :       return true;
    2090              :     else
    2091              :       {
    2092         3290 :         r = range_true_and_false (type);
    2093         3290 :         return true;
    2094              :       }
    2095         3611 :   }
    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         2136 :   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         2136 :     if (op1.known_isnan () || op2.known_isnan ())
    2156              :       {
    2157            2 :         r = range_false (type);
    2158            2 :         return true;
    2159              :       }
    2160         2134 :     frange op1_no_nan = op1;
    2161         2134 :     frange op2_no_nan = op2;
    2162         2454 :     if (op1.maybe_isnan ())
    2163         1798 :       op1_no_nan.clear_nan ();
    2164         2454 :     if (op2.maybe_isnan ())
    2165         1798 :       op2_no_nan.clear_nan ();
    2166         2134 :     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         2134 :     if (!maybe_isnan (op1, op2) || r == range_false (type))
    2172              :       return true;
    2173              :     else
    2174              :       {
    2175         1798 :         r = range_true_and_false (type);
    2176         1798 :         return true;
    2177              :       }
    2178         2134 :   }
    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         1574 : foperator_ltgt::op1_range (frange &r, tree type,
    2193              :                            const irange &lhs,
    2194              :                            const frange &op2,
    2195              :                            relation_trio) const
    2196              : {
    2197         1574 :   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           10 :     case BRS_FALSE:
    2214              :       // If it's false, the result is the same as OP2 plus a NAN.
    2215           10 :       r = op2;
    2216              :       // Add both zeros if there's the possibility of zero equality.
    2217           10 :       frange_add_zeros (r, type);
    2218              :       // Add the possibility of a NAN.
    2219           10 :       r.update_nan ();
    2220           10 :       break;
    2221              : 
    2222              :     default:
    2223              :       break;
    2224              :     }
    2225         1574 :   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       829736 : float_binary_op_range_finish (bool ret, frange &r, tree type,
    2233              :                               const frange &lhs, bool div_op2 = false)
    2234              : {
    2235       829736 :   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       829736 :   if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
    2246              :     {
    2247         6999 :       r.set_varying (type);
    2248         6999 :       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      1484795 :   if (!lhs.maybe_isnan ())
    2254              :     {
    2255       662058 :       r.clear_nan ();
    2256       662058 :       if (div_op2
    2257       686350 :           ? !(real_compare (LE_EXPR, &lhs.lower_bound (), &dconst0)
    2258        24292 :               && real_compare (GE_EXPR, &lhs.upper_bound (), &dconst0))
    2259      1138286 :           : !(real_isinf (&lhs.lower_bound ())
    2260       507896 :               || 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       488305 :         frange_drop_infs (r, type);
    2267              :     }
    2268              :   // If lhs is a maybe or known NAN, the operand could be
    2269              :   // NAN.
    2270              :   else
    2271       160679 :     r.update_nan ();
    2272              :   return true;
    2273              : }
    2274              : 
    2275              : // True if [lb, ub] is [+-0, +-0].
    2276              : static bool
    2277      5042348 : zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2278              : {
    2279      5042348 :   return real_iszero (&lb) && real_iszero (&ub);
    2280              : }
    2281              : 
    2282              : // True if +0 or -0 is in [lb, ub] range.
    2283              : static bool
    2284      4099105 : contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2285              : {
    2286      4099105 :   return (real_compare (LE_EXPR, &lb, &dconst0)
    2287      4099105 :           && real_compare (GE_EXPR, &ub, &dconst0));
    2288              : }
    2289              : 
    2290              : // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
    2291              : static bool
    2292      2834669 : singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2293              : {
    2294      2834669 :   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      1272840 : 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      1272840 :   if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
    2307      1272840 :       && real_isneg (&rh_lb) == real_isneg (&rh_ub))
    2308              :     {
    2309       111990 :       if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
    2310              :         return 1;
    2311              :       else
    2312         6555 :         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         6210 : zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2321              : {
    2322         6210 :   ub = lb = dconst0;
    2323         6210 :   if (signbit_known <= 0)
    2324         6064 :     lb = dconstm0;
    2325         6064 :   if (signbit_known < 0)
    2326           44 :     ub = lb;
    2327         6210 : }
    2328              : 
    2329              : // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
    2330              : // signbit_known.
    2331              : static void
    2332         4321 : inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2333              : {
    2334         4321 :   if (signbit_known > 0)
    2335          952 :     ub = lb = dconstinf;
    2336         3369 :   else if (signbit_known < 0)
    2337           96 :     ub = lb = dconstninf;
    2338              :   else
    2339              :     {
    2340         3273 :       lb = dconstninf;
    2341         3273 :       ub = dconstinf;
    2342              :     }
    2343         4321 : }
    2344              : 
    2345              : // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
    2346              : // signbit_known.
    2347              : static void
    2348       925108 : zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2349              : {
    2350       925108 :   if (signbit_known > 0)
    2351              :     {
    2352        10290 :       lb = dconst0;
    2353        10290 :       ub = dconstinf;
    2354              :     }
    2355       914818 :   else if (signbit_known < 0)
    2356              :     {
    2357          222 :       lb = dconstninf;
    2358          222 :       ub = dconstm0;
    2359              :     }
    2360              :   else
    2361              :     {
    2362       914596 :       lb = dconstninf;
    2363       914596 :       ub = dconstinf;
    2364              :     }
    2365       925108 : }
    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       809739 : float_widen_lhs_range (tree type, const frange &lhs)
    2378              : {
    2379       809739 :   frange ret = lhs;
    2380       809739 :   if (lhs.known_isnan ())
    2381              :     return ret;
    2382       802741 :   REAL_VALUE_TYPE lb = lhs.lower_bound ();
    2383       802741 :   REAL_VALUE_TYPE ub = lhs.upper_bound ();
    2384       802741 :   if (real_isfinite (&lb))
    2385              :     {
    2386       622073 :       frange_nextafter (TYPE_MODE (type), lb, dconstninf);
    2387       622073 :       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        55299 :           lb = dconstm1;
    2396       221196 :           SET_REAL_EXP (&lb, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
    2397              :         }
    2398      4354511 :       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       622073 :           REAL_VALUE_TYPE tem;
    2403       622073 :           real_arithmetic (&tem, PLUS_EXPR, &lhs.lower_bound (), &lb);
    2404       622073 :           real_arithmetic (&lb, RDIV_EXPR, &tem, &dconst2);
    2405              :         }
    2406              :     }
    2407       802741 :   if (real_isfinite (&ub))
    2408              :     {
    2409       552250 :       frange_nextafter (TYPE_MODE (type), ub, dconstinf);
    2410       552250 :       if (real_isinf (&ub))
    2411              :         {
    2412              :           /* For DBL_MAX similarly.  */
    2413        55884 :           ub = dconst1;
    2414       223536 :           SET_REAL_EXP (&ub, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
    2415              :         }
    2416      3865750 :       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       552250 :           REAL_VALUE_TYPE tem;
    2421       552250 :           real_arithmetic (&tem, PLUS_EXPR, &lhs.upper_bound (), &ub);
    2422       552250 :           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       802741 :   bool save_flag_finite_math_only = flag_finite_math_only;
    2429       802741 :   flag_finite_math_only = false;
    2430       802741 :   ret.set (type, lb, ub, lhs.get_nan_state ());
    2431       802741 :   flag_finite_math_only = save_flag_finite_math_only;
    2432       802741 :   return ret;
    2433              : }
    2434              : 
    2435              : bool
    2436       165948 : operator_plus::op1_range (frange &r, tree type, const frange &lhs,
    2437              :                           const frange &op2, relation_trio) const
    2438              : {
    2439       165948 :   if (lhs.undefined_p ())
    2440              :     return false;
    2441       165948 :   range_op_handler minus (MINUS_EXPR);
    2442       165948 :   if (!minus)
    2443              :     return false;
    2444       165948 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2445       165948 :   return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
    2446              :                                        r, type, wlhs);
    2447       165948 : }
    2448              : 
    2449              : bool
    2450        71428 : operator_plus::op2_range (frange &r, tree type,
    2451              :                           const frange &lhs, const frange &op1,
    2452              :                           relation_trio) const
    2453              : {
    2454        71428 :   return op1_range (r, type, lhs, op1);
    2455              : }
    2456              : 
    2457              : void
    2458      2453616 : 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      2453616 :   REAL_VALUE_TYPE lb, ub;
    2466      2453616 :   bool maybe_nan = false;
    2467              : 
    2468      2453616 :   frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
    2469      2453616 :   frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
    2470              : 
    2471              :   // [-INF] + [+INF] = NAN
    2472      2453616 :   if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
    2473              :     maybe_nan = true;
    2474              :   // [+INF] + [-INF] = NAN
    2475       792221 :   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      2453616 :   bool lb_nan = real_isnan (&lb);
    2481      2453616 :   bool ub_nan = real_isnan (&ub);
    2482      2453616 :   if (lb_nan && ub_nan)
    2483              :     {
    2484            0 :       r.set_nan (type);
    2485            0 :       return;
    2486              :     }
    2487      2453616 :   if (lb_nan)
    2488          374 :     lb = dconstninf;
    2489      2453242 :   else if (ub_nan)
    2490            0 :     ub = dconstinf;
    2491      2453616 :   r.set (type, lb, ub, nan_state (maybe_nan));
    2492              : }
    2493              : 
    2494              : 
    2495              : bool
    2496        83639 : operator_minus::op1_range (frange &r, tree type,
    2497              :                            const frange &lhs, const frange &op2,
    2498              :                            relation_trio) const
    2499              : {
    2500        83639 :   if (lhs.undefined_p ())
    2501              :     return false;
    2502        83639 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2503        83639 :   return float_binary_op_range_finish (
    2504       167278 :               range_op_handler (PLUS_EXPR).fold_range (r, type, wlhs, op2),
    2505              :               r, type, wlhs);
    2506        83639 : }
    2507              : 
    2508              : bool
    2509       132097 : operator_minus::op2_range (frange &r, tree type,
    2510              :                            const frange &lhs, const frange &op1,
    2511              :                            relation_trio) const
    2512              : {
    2513       132097 :   if (lhs.undefined_p ())
    2514              :     return false;
    2515       132097 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2516       132097 :   return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
    2517              :                                        r, type, wlhs);
    2518       132097 : }
    2519              : 
    2520              : void
    2521       908859 : 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       908859 :   REAL_VALUE_TYPE lb, ub;
    2529       908859 :   bool maybe_nan = false;
    2530              : 
    2531       908859 :   frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
    2532       908859 :   frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
    2533              : 
    2534              :   // [+INF] - [+INF] = NAN
    2535       908859 :   if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
    2536              :     maybe_nan = true;
    2537              :   // [-INF] - [-INF] = NAN
    2538       626249 :   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       908859 :   bool lb_nan = real_isnan (&lb);
    2544       908859 :   bool ub_nan = real_isnan (&ub);
    2545       908859 :   if (lb_nan && ub_nan)
    2546              :     {
    2547            0 :       r.set_nan (type);
    2548            0 :       return;
    2549              :     }
    2550       908859 :   if (lb_nan)
    2551          186 :     lb = dconstninf;
    2552       908673 :   else if (ub_nan)
    2553          312 :     ub = dconstinf;
    2554       908859 :   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      1065344 : find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
    2565              :             const REAL_VALUE_TYPE (&cp)[8])
    2566              : {
    2567      1065344 :   lb = cp[0];
    2568      1065344 :   ub = cp[4];
    2569      4261376 :   for (int i = 1; i < 4; ++i)
    2570              :     {
    2571      3196032 :       if (real_less (&cp[i], &lb)
    2572      3196032 :           || (real_iszero (&lb) && real_isnegzero (&cp[i])))
    2573       356507 :         lb = cp[i];
    2574      3196032 :       if (real_less (&ub, &cp[i + 4])
    2575      3196032 :           || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
    2576      1003236 :         ub = cp[i + 4];
    2577              :     }
    2578      1065344 : }
    2579              : 
    2580              : 
    2581              : bool
    2582       329195 : operator_mult::op1_range (frange &r, tree type,
    2583              :                           const frange &lhs, const frange &op2,
    2584              :                           relation_trio) const
    2585              : {
    2586       329195 :   if (lhs.undefined_p ())
    2587              :     return false;
    2588       329195 :   range_op_handler rdiv (RDIV_EXPR);
    2589       329195 :   if (!rdiv)
    2590              :     return false;
    2591       329195 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2592       329195 :   bool ret = rdiv.fold_range (r, type, wlhs, op2);
    2593       329195 :   if (ret == false)
    2594              :     return false;
    2595       329195 :   if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
    2596           16 :     return float_binary_op_range_finish (ret, r, type, wlhs);
    2597       329179 :   const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2598       329179 :   const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2599       329179 :   const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
    2600       329179 :   const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
    2601       610329 :   if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
    2602       476381 :       || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
    2603        39350 :           && (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       140962 :       REAL_VALUE_TYPE lb, ub;
    2609       140962 :       int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
    2610       140962 :       zero_to_inf_range (lb, ub, signbit_known);
    2611       140962 :       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       329179 :   return float_binary_op_range_finish (ret, r, type, wlhs);
    2618       329195 : }
    2619              : 
    2620              : bool
    2621        78895 : operator_mult::op2_range (frange &r, tree type,
    2622              :                           const frange &lhs, const frange &op1,
    2623              :                           relation_trio) const
    2624              : {
    2625        78895 :   return op1_range (r, type, lhs, op1);
    2626              : }
    2627              : 
    2628              : void
    2629      1145068 : 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      1145068 :   bool is_square
    2637              :     = (kind == VREL_EQ
    2638        36962 :        && real_equal (&lh_lb, &rh_lb)
    2639        36962 :        && real_equal (&lh_ub, &rh_ub)
    2640        36962 :        && real_isneg (&lh_lb) == real_isneg (&rh_lb)
    2641      1182030 :        && real_isneg (&lh_ub) == real_isneg (&rh_ub));
    2642      1108106 :   REAL_VALUE_TYPE lb, ub;
    2643      1836249 :   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      1108106 :   if (!is_square)
    2647              :     {
    2648              :       // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
    2649      1113512 :       if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
    2650      1113506 :           || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
    2651              :         {
    2652           37 :           r.set_nan (type);
    2653       416925 :           return;
    2654              :         }
    2655              : 
    2656              :       // Otherwise, if one range includes zero and the other ends with +-INF,
    2657              :       // it is a maybe NAN.
    2658      1108069 :       if ((contains_zero_p (lh_lb, lh_ub)
    2659      1004700 :            && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
    2660      1723735 :           || (contains_zero_p (rh_lb, rh_ub)
    2661       201467 :               && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
    2662              :         {
    2663       416888 :           maybe_nan = true;
    2664              : 
    2665       416888 :           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       416888 :           if (singleton_inf_p (lh_lb, lh_ub)
    2673       416888 :               || 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       415900 :           if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
    2683              :             {
    2684         5680 :               zero_range (lb, ub, signbit_known);
    2685         5680 :               r.set (type, lb, ub, nan_state (true));
    2686         5680 :               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       410220 :           zero_to_inf_range (lb, ub, signbit_known);
    2696       410220 :           r.set (type, lb, ub, nan_state (true));
    2697       410220 :           return;
    2698              :         }
    2699              :     }
    2700              : 
    2701       728143 :   REAL_VALUE_TYPE cp[8];
    2702              :   // Do a cross-product.  At this point none of the multiplications
    2703              :   // should produce a NAN.
    2704       728143 :   frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
    2705       728143 :   frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
    2706       728143 :   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        36962 :       if (contains_zero_p (lh_lb, lh_ub))
    2714              :         {
    2715        33926 :           if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
    2716         1155 :             cp[1] = dconst0;
    2717              :           else
    2718        32771 :             cp[1] = dconstm0;
    2719              :         }
    2720              :       else
    2721         3036 :         cp[1] = cp[0];
    2722        36962 :       cp[2] = cp[0];
    2723        36962 :       cp[5] = cp[4];
    2724        36962 :       cp[6] = cp[4];
    2725              :     }
    2726              :   else
    2727              :     {
    2728       691181 :       frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
    2729       691181 :       frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
    2730       691181 :       frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
    2731       691181 :       frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
    2732              :     }
    2733       728143 :   frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
    2734       728143 :   frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
    2735              : 
    2736       728143 :   find_range (lb, ub, cp);
    2737              : 
    2738       728143 :   gcc_checking_assert (!real_isnan (&lb));
    2739       728143 :   gcc_checking_assert (!real_isnan (&ub));
    2740       728143 :   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        24619 :   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        24619 :     if (lhs.undefined_p ())
    2755              :       return false;
    2756        24619 :     frange wlhs = float_widen_lhs_range (type, lhs);
    2757        24619 :     bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
    2758        24619 :     if (!ret)
    2759              :       return ret;
    2760        24619 :     if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
    2761            4 :       return float_binary_op_range_finish (ret, r, type, wlhs);
    2762        24615 :     const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2763        24615 :     const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2764        24615 :     const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
    2765        24615 :     const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
    2766        24615 :     if ((contains_zero_p (lhs_lb, lhs_ub)
    2767        17209 :          && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
    2768        31036 :         || ((contains_zero_p (op2_lb, op2_ub))
    2769         8186 :             && (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        18492 :         REAL_VALUE_TYPE lb, ub;
    2775        18492 :         int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
    2776        18492 :         zero_to_inf_range (lb, ub, signbit_known);
    2777        18492 :         r.set (type, lb, ub);
    2778              :       }
    2779        24615 :     return float_binary_op_range_finish (ret, r, type, wlhs);
    2780        24619 :   }
    2781        41088 :   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        41088 :     if (lhs.undefined_p ())
    2787              :       return false;
    2788        41088 :     frange wlhs = float_widen_lhs_range (type, lhs);
    2789        41088 :     bool ret = fold_range (r, type, op1, wlhs);
    2790        41088 :     if (!ret)
    2791              :       return ret;
    2792        41088 :     if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
    2793           20 :       return float_binary_op_range_finish (ret, r, type, wlhs, true);
    2794        41068 :     const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2795        41068 :     const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2796        41068 :     const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
    2797        41068 :     const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
    2798        72232 :     if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
    2799        44546 :         || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
    2800         7623 :             && (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        31998 :         REAL_VALUE_TYPE lb, ub;
    2806        31998 :         int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
    2807        31998 :         zero_to_inf_range (lb, ub, signbit_known);
    2808        31998 :         r.set (type, lb, ub);
    2809              :       }
    2810        41068 :     return float_binary_op_range_finish (ret, r, type, wlhs, true);
    2811        41088 :   }
    2812              : private:
    2813       665154 :   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       666330 :     if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
    2822       665682 :         || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
    2823              :       {
    2824          654 :         r.set_nan (type);
    2825       327953 :         return;
    2826              :       }
    2827              : 
    2828       664500 :     REAL_VALUE_TYPE lb, ub;
    2829       664500 :     bool maybe_nan = false;
    2830              :     // If +-0.0 is in both ranges, it is a maybe NAN.
    2831       664500 :     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       651165 :     else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
    2835       382388 :              && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
    2836              :       maybe_nan = true;
    2837              : 
    2838       664500 :     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       664500 :     if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
    2845              :       {
    2846          530 :         zero_range (lb, ub, signbit_known);
    2847          530 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2848          530 :         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       663970 :     if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
    2856              :       {
    2857         3333 :         inf_range (lb, ub, signbit_known);
    2858         3333 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2859         3333 :         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       660637 :     if (maybe_nan)
    2876              :       {
    2877       323436 :         zero_to_inf_range (lb, ub, signbit_known);
    2878       323436 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2879       323436 :         return;
    2880              :       }
    2881              : 
    2882       337201 :     REAL_VALUE_TYPE cp[8];
    2883              :     // Do a cross-division.  At this point none of the divisions should
    2884              :     // produce a NAN.
    2885       337201 :     frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
    2886       337201 :     frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
    2887       337201 :     frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
    2888       337201 :     frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
    2889       337201 :     frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
    2890       337201 :     frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
    2891       337201 :     frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
    2892       337201 :     frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
    2893              : 
    2894       337201 :     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       337201 :     if (contains_zero_p (rh_lb, rh_ub))
    2900              :       {
    2901        50314 :         if (signbit_known <= 0)
    2902        47899 :           real_inf (&lb, true);
    2903        47899 :         if (signbit_known >= 0)
    2904        50276 :           real_inf (&ub, false);
    2905              :       }
    2906              : 
    2907       337201 :     gcc_checking_assert (!real_isnan (&lb));
    2908       337201 :     gcc_checking_assert (!real_isnan (&ub));
    2909       337201 :     r.set (type, lb, ub, nan_state (maybe_nan));
    2910              :   }
    2911              : };
    2912              : static const foperator_div fop_div;
    2913              : 
    2914              : bool
    2915       913449 : operator_cast::fold_range (frange &r, tree type, const frange &op1,
    2916              :                            const frange &, relation_trio) const
    2917              : {
    2918       913449 :   REAL_VALUE_TYPE lb, ub;
    2919       913449 :   enum machine_mode mode = TYPE_MODE (type);
    2920      6394143 :   bool mode_composite = MODE_COMPOSITE_P (mode);
    2921              : 
    2922       913449 :   if (empty_range_varying (r, type, op1, op1))
    2923          819 :     return true;
    2924      3650520 :   if (!MODE_HAS_NANS (mode) && op1.maybe_isnan ())
    2925              :     {
    2926            0 :       r.set_varying (type);
    2927            0 :       return true;
    2928              :     }
    2929       912630 :   if (op1.known_isnan ())
    2930              :     {
    2931         3006 :       r.set_nan (type);
    2932         3006 :       return true;
    2933              :     }
    2934              : 
    2935       909624 :   const REAL_VALUE_TYPE &lh_lb = op1.lower_bound ();
    2936       909624 :   const REAL_VALUE_TYPE &lh_ub = op1.upper_bound ();
    2937       909624 :   real_convert (&lb, mode, &lh_lb);
    2938       909624 :   real_convert (&ub, mode, &lh_ub);
    2939              : 
    2940       909624 :   if (flag_rounding_math)
    2941              :     {
    2942        30557 :       if (real_less (&lh_lb, &lb))
    2943              :         {
    2944         2668 :           if (mode_composite
    2945         2668 :               && (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         2668 :             frange_nextafter (mode, lb, dconstninf);
    2956              :         }
    2957        30557 :       if (real_less (&ub, &lh_ub))
    2958              :         {
    2959         1070 :           if (mode_composite
    2960         1070 :               && (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         1070 :             frange_nextafter (mode, ub, dconstinf);
    2971              :         }
    2972              :     }
    2973              : 
    2974       909624 :   r.set (type, lb, ub, op1.get_nan_state ());
    2975              : 
    2976       909624 :   if (flag_trapping_math
    2977      4092891 :       && MODE_HAS_INFINITIES (TYPE_MODE (type))
    2978       795817 :       && r.known_isinf ()
    2979       909704 :       && !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       909624 :   r.flush_denormals_to_zero ();
    2995       909624 :   return true;
    2996              : }
    2997              : 
    2998              : // Implement fold for a cast from float to another float.
    2999              : bool
    3000        53150 : operator_cast::op1_range (frange &r, tree type, const frange &lhs,
    3001              :                           const frange &op2, relation_trio) const
    3002              : {
    3003        53150 :   if (lhs.undefined_p ())
    3004              :     return false;
    3005        53150 :   tree lhs_type = lhs.type ();
    3006        53150 :   enum machine_mode mode = TYPE_MODE (type);
    3007        53150 :   enum machine_mode lhs_mode = TYPE_MODE (lhs_type);
    3008        53150 :   frange wlhs;
    3009        53150 :   bool rm;
    3010        53150 :   if (REAL_MODE_FORMAT (mode)->ieee_bits
    3011        48786 :       && REAL_MODE_FORMAT (lhs_mode)->ieee_bits
    3012        45564 :       && (REAL_MODE_FORMAT (lhs_mode)->ieee_bits
    3013              :           >= REAL_MODE_FORMAT (mode)->ieee_bits)
    3014        73147 :       && 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        19997 :       rm = false;
    3020        19997 :       wlhs = lhs;
    3021              :     }
    3022              :   else
    3023              :     {
    3024        33153 :       rm = true;
    3025        33153 :       wlhs = float_widen_lhs_range (lhs_type, lhs);
    3026              :     }
    3027        53150 :   auto save_flag_rounding_math = flag_rounding_math;
    3028        53150 :   flag_rounding_math = rm;
    3029        53150 :   bool ret = float_binary_op_range_finish (fold_range (r, type, wlhs, op2),
    3030              :                                            r, type, lhs);
    3031        53150 :   flag_rounding_math = save_flag_rounding_math;
    3032        53150 :   return ret;
    3033        53150 : }
    3034              : 
    3035              : // Implement fold for a cast from float to an int.
    3036              : bool
    3037       209038 : operator_cast::fold_range (irange &r, tree type, const frange &op1,
    3038              :                            const irange &, relation_trio) const
    3039              : {
    3040       209038 :   if (empty_range_varying (r, type, op1, op1))
    3041          540 :     return true;
    3042       208498 :   if (op1.maybe_isnan () || op1.maybe_isinf ())
    3043              :     {
    3044       182151 :       r.set_varying (type);
    3045       182151 :       return true;
    3046              :     }
    3047        26347 :   REAL_VALUE_TYPE lb, ub;
    3048        26347 :   real_trunc (&lb, VOIDmode, &op1.lower_bound ());
    3049        26347 :   real_trunc (&ub, VOIDmode, &op1.upper_bound ());
    3050        26347 :   REAL_VALUE_TYPE l, u;
    3051        26347 :   l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
    3052        26347 :   if (real_less (&lb, &l))
    3053              :     {
    3054         9430 :       r.set_varying (type);
    3055         9430 :       return true;
    3056              :     }
    3057        16917 :   u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
    3058        16917 :   if (real_less (&u, &ub))
    3059              :     {
    3060         7945 :       r.set_varying (type);
    3061         7945 :       return true;
    3062              :     }
    3063         8972 :   bool fail = false;
    3064         8972 :   wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
    3065         8972 :   wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
    3066         8972 :   if (fail)
    3067              :     {
    3068            0 :       r.set_varying (type);
    3069            0 :       return true;
    3070              :     }
    3071         8972 :   r.set (type, wlb, wub);
    3072         8972 :   return true;
    3073         8972 : }
    3074              : 
    3075              : // Implement op1_range for a cast from float to an int.
    3076              : bool
    3077         7453 : operator_cast::op1_range (frange &r, tree type, const irange &lhs,
    3078              :                           const frange &, relation_trio) const
    3079              : {
    3080         7453 :   if (lhs.undefined_p ())
    3081              :     return false;
    3082         7453 :   REAL_VALUE_TYPE lb, lbo, ub, ubo;
    3083         7453 :   wide_int lhs_lb = lhs.lower_bound ();
    3084         7453 :   wide_int lhs_ub = lhs.upper_bound ();
    3085         7453 :   tree lhs_type = lhs.type ();
    3086         7453 :   enum machine_mode mode = TYPE_MODE (type);
    3087         7453 :   real_from_integer (&lbo, VOIDmode, lhs_lb, TYPE_SIGN (lhs_type));
    3088         7453 :   real_from_integer (&ubo, VOIDmode, lhs_ub, TYPE_SIGN (lhs_type));
    3089         7453 :   real_convert (&lb, mode, &lbo);
    3090         7453 :   real_convert (&ub, mode, &ubo);
    3091         7453 :   if (real_identical (&lb, &lbo))
    3092              :     {
    3093              :       /* If low bound is exactly representable in type,
    3094              :          use nextafter (lb - 1., +inf).  */
    3095         7324 :       real_arithmetic (&lb, PLUS_EXPR, &lbo, &dconstm1);
    3096         7324 :       real_convert (&lb, mode, &lb);
    3097         7324 :       if (!real_identical (&lb, &lbo))
    3098         6085 :         frange_nextafter (mode, lb, dconstinf);
    3099         7324 :       if (real_identical (&lb, &lbo))
    3100         1241 :         frange_nextafter (mode, lb, dconstninf);
    3101              :     }
    3102          129 :   else if (real_less (&lbo, &lb))
    3103           13 :     frange_nextafter (mode, lb, dconstninf);
    3104         7453 :   if (real_identical (&ub, &ubo))
    3105              :     {
    3106              :       /* If upper bound is exactly representable in type,
    3107              :          use nextafter (ub + 1., -inf).  */
    3108         5612 :       real_arithmetic (&ub, PLUS_EXPR, &ubo, &dconst1);
    3109         5612 :       real_convert (&ub, mode, &ub);
    3110         5612 :       if (!real_identical (&ub, &ubo))
    3111         5532 :         frange_nextafter (mode, ub, dconstninf);
    3112         5612 :       if (real_identical (&ub, &ubo))
    3113           80 :         frange_nextafter (mode, ub, dconstinf);
    3114              :     }
    3115         1841 :   else if (real_less (&ub, &ubo))
    3116            0 :     frange_nextafter (mode, ub, dconstinf);
    3117         7453 :   r.set (type, lb, ub, nan_state (false));
    3118         7453 :   return true;
    3119         7453 : }
    3120              : 
    3121              : // Implement fold for a cast from int to a float.
    3122              : bool
    3123       816920 : operator_cast::fold_range (frange &r, tree type, const irange &op1,
    3124              :                            const frange &, relation_trio) const
    3125              : {
    3126       816920 :   if (empty_range_varying (r, type, op1, op1))
    3127         1402 :     return true;
    3128       815518 :   REAL_VALUE_TYPE lb, ub;
    3129       815518 :   wide_int op1_lb = op1.lower_bound ();
    3130       815518 :   wide_int op1_ub = op1.upper_bound ();
    3131       815518 :   tree op1_type = op1.type ();
    3132       815518 :   enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
    3133       815518 :   real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
    3134       815518 :   real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
    3135       815518 :   if (flag_rounding_math)
    3136              :     {
    3137         1129 :       REAL_VALUE_TYPE lbo = lb, ubo = ub;
    3138         1129 :       mode = TYPE_MODE (type);
    3139         1129 :       real_convert (&lb, mode, &lb);
    3140         1129 :       real_convert (&ub, mode, &ub);
    3141         1129 :       if (real_less (&lbo, &lb))
    3142          322 :         frange_nextafter (mode, lb, dconstninf);
    3143         1129 :       if (real_less (&ub, &ubo))
    3144          192 :         frange_nextafter (mode, ub, dconstinf);
    3145              :     }
    3146       815518 :   r.set (type, lb, ub, nan_state (false));
    3147       815518 :   frange_drop_infs (r, type);
    3148       815518 :   if (r.undefined_p ())
    3149            4 :     r.set_varying (type);
    3150       815518 :   return true;
    3151       815530 : }
    3152              : 
    3153              : // Implement op1_range for a cast from int to a float.
    3154              : bool
    3155       211681 : operator_cast::op1_range (irange &r, tree type, const frange &lhs,
    3156              :                           const irange &, relation_trio) const
    3157              : {
    3158       211681 :   if (lhs.undefined_p ())
    3159              :     return false;
    3160       211681 :   if (lhs.known_isnan ())
    3161              :     {
    3162            0 :       r.set_varying (type);
    3163            0 :       return true;
    3164              :     }
    3165       211681 :   REAL_VALUE_TYPE lb = lhs.lower_bound ();
    3166       211681 :   REAL_VALUE_TYPE ub = lhs.upper_bound ();
    3167       211681 :   enum machine_mode mode = TYPE_MODE (lhs.type ());
    3168       211681 :   frange_nextafter (mode, lb, dconstninf);
    3169       211681 :   frange_nextafter (mode, ub, dconstinf);
    3170       211681 :   if (flag_rounding_math)
    3171              :     {
    3172           37 :       real_floor (&lb, mode, &lb);
    3173           37 :       real_ceil (&ub, mode, &ub);
    3174              :     }
    3175              :   else
    3176              :     {
    3177       211644 :       real_trunc (&lb, mode, &lb);
    3178       211644 :       real_trunc (&ub, mode, &ub);
    3179              :     }
    3180       211681 :   REAL_VALUE_TYPE l, u;
    3181       211681 :   wide_int wlb, wub;
    3182       211681 :   l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
    3183       211681 :   if (real_less (&lb, &l))
    3184        28577 :     wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3185              :   else
    3186              :     {
    3187       183104 :       bool fail = false;
    3188       183104 :       wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
    3189       183104 :       if (fail)
    3190            0 :         wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3191              :     }
    3192       211681 :   u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
    3193       211681 :   if (real_less (&u, &ub))
    3194        39630 :     wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3195              :   else
    3196              :     {
    3197       172051 :       bool fail = false;
    3198       172051 :       wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
    3199       172051 :       if (fail)
    3200            0 :         wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3201              :     }
    3202       211681 :   r.set (type, wlb, wub);
    3203       211681 :   return true;
    3204       211681 : }
    3205              : 
    3206              : // Initialize any float operators to the primary table
    3207              : 
    3208              : void
    3209       286916 : range_op_table::initialize_float_ops ()
    3210              : {
    3211       286916 :   set (UNLE_EXPR, fop_unordered_le);
    3212       286916 :   set (UNLT_EXPR, fop_unordered_lt);
    3213       286916 :   set (UNGE_EXPR, fop_unordered_ge);
    3214       286916 :   set (UNGT_EXPR, fop_unordered_gt);
    3215       286916 :   set (UNEQ_EXPR, fop_unordered_equal);
    3216       286916 :   set (ORDERED_EXPR, fop_ordered);
    3217       286916 :   set (UNORDERED_EXPR, fop_unordered);
    3218       286916 :   set (LTGT_EXPR, fop_ltgt);
    3219       286916 :   set (RDIV_EXPR, fop_div);
    3220       286916 : }
    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.