LCOV - code coverage report
Current view: top level - gcc - range-op-float.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.6 % 1342 1243
Test Date: 2026-02-28 14:20:25 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      5831965 : range_operator::fold_range (frange &r, tree type,
      54              :                             const frange &op1, const frange &op2,
      55              :                             relation_trio trio) const
      56              : {
      57      5831965 :   if (empty_range_varying (r, type, op1, op2))
      58         6396 :     return true;
      59      5825569 :   if (op1.known_isnan () || op2.known_isnan ())
      60              :     {
      61         7483 :       r.set_nan (type);
      62         7483 :       return true;
      63              :     }
      64              : 
      65      5818086 :   rv_fold (r, type,
      66              :            op1.lower_bound (), op1.upper_bound (),
      67              :            op2.lower_bound (), op2.upper_bound (), trio.op1_op2 ());
      68              : 
      69      5818086 :   if (r.known_isnan ())
      70              :     return true;
      71      9542281 :   if (op1.maybe_isnan () || op2.maybe_isnan ())
      72      4129948 :     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      5817464 :   if (flag_trapping_math
      79     27337351 :       && MODE_HAS_INFINITIES (TYPE_MODE (type))
      80     11197838 :       && r.known_isinf () && !op1.known_isinf () && !op2.known_isinf ())
      81              :     {
      82         1609 :       REAL_VALUE_TYPE inf = r.lower_bound ();
      83         1609 :       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         1513 :           REAL_VALUE_TYPE max = real_max_representable (type);
      91         1513 :           r.set (type, max, inf);
      92              :         }
      93              :     }
      94              : 
      95      5817464 :   r.flush_denormals_to_zero ();
      96              : 
      97      5817464 :   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       504478 : 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       504478 :   r.set (type, dconstninf, dconstinf, nan_state (true));
     111       504478 : }
     112              : 
     113              : bool
     114       101807 : 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       101807 :   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         6068 : 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         6068 :   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      5786196 : 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      5786196 :   return VREL_VARYING;
     190              : }
     191              : 
     192              : relation_kind
     193      1032708 : 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      1032708 :   return VREL_VARYING;
     199              : }
     200              : 
     201              : relation_kind
     202       169745 : 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       169745 :   return VREL_VARYING;
     208              : }
     209              : 
     210              : relation_kind
     211      3632923 : 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      3632923 :   return VREL_VARYING;
     217              : }
     218              : 
     219              : relation_kind
     220       353277 : range_operator::op1_op2_relation (const irange &,
     221              :                                   const frange &,
     222              :                                   const frange &) const
     223              : {
     224       353277 :   return VREL_VARYING;
     225              : }
     226              : 
     227              : 
     228              : relation_kind
     229       656035 : range_operator::op1_op2_relation (const frange &,
     230              :                                   const frange &,
     231              :                                   const frange &) const
     232              : {
     233       656035 :   return VREL_VARYING;
     234              : }
     235              : 
     236              : // Return TRUE if OP1 and OP2 may be a NAN.
     237              : 
     238              : static inline bool
     239      3624237 : maybe_isnan (const frange &op1, const frange &op2)
     240              : {
     241      6321354 :   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      2097308 : frelop_early_resolve (irange &r, tree type,
     260              :                       const frange &op1, const frange &op2,
     261              :                       relation_trio trio, relation_kind my_rel)
     262              : {
     263      2097308 :   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      2097308 :   if (!maybe_isnan (op1, op2) && relation_union (rel, my_rel) == my_rel)
     276              :     {
     277         1946 :       r = range_true (type);
     278         1946 :       return true;
     279              :     }
     280              : 
     281              :   // If known relation has no subset of this relation, always false.
     282      2095362 :   if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
     283              :     {
     284         1086 :       r = range_false (type);
     285         1086 :       return true;
     286              :     }
     287              : 
     288              :   // If either operand is undefined, return VARYING.
     289      2094276 :   if (empty_range_varying (r, type, op1, op2))
     290         2448 :     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      3925054 : frange_nextafter (enum machine_mode mode,
     299              :                   REAL_VALUE_TYPE &value,
     300              :                   const REAL_VALUE_TYPE &inf)
     301              : {
     302     27475378 :   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      3925054 :       REAL_VALUE_TYPE tmp;
     314      3925054 :       real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
     315      3925054 :       value = tmp;
     316              :     }
     317      3925054 : }
     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     15775210 : 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     15775210 :   REAL_VALUE_TYPE value;
     338     15775210 :   enum machine_mode mode = TYPE_MODE (type);
     339    110426470 :   bool mode_composite = MODE_COMPOSITE_P (mode);
     340              : 
     341     15775210 :   bool inexact = real_arithmetic (&value, code, &op1, &op2);
     342     15775210 :   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     15775210 :   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     15775276 :       && 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     15775210 :   bool round = false;
     365     15775210 :   if (mode_composite)
     366              :     round = true;
     367              :   else
     368              :     {
     369     15775210 :       bool low = real_isneg (&inf);
     370     15775210 :       round = (low ? !real_less (&result, &value)
     371      7887682 :                    : !real_less (&value, &result));
     372     15775210 :       if (real_isinf (&result, !low)
     373      1544689 :           && !real_isinf (&value)
     374     16167497 :           && !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       390386 :           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     15441526 :   if (round && (inexact || !real_identical (&result, &value)))
     400              :     {
     401      1488623 :       if (mode_composite
     402      1488623 :           && (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      1488623 :         frange_nextafter (mode, result, inf);
     412              :     }
     413     15775210 :   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     15775210 : }
     436              : 
     437              : // Crop R to [-INF, MAX] where MAX is the maximum representable number
     438              : // for TYPE.
     439              : 
     440              : static inline void
     441       175241 : frange_drop_inf (frange &r, tree type)
     442              : {
     443       175241 :   REAL_VALUE_TYPE max = real_max_representable (type);
     444       175241 :   frange tmp (type, r.lower_bound (), max);
     445       175241 :   r.intersect (tmp);
     446       175241 : }
     447              : 
     448              : // Crop R to [MIN, +INF] where MIN is the minimum representable number
     449              : // for TYPE.
     450              : 
     451              : static inline void
     452        94022 : frange_drop_ninf (frange &r, tree type)
     453              : {
     454        94022 :   REAL_VALUE_TYPE min = real_min_representable (type);
     455        94022 :   frange tmp (type, min, r.upper_bound ());
     456        94022 :   r.intersect (tmp);
     457        94022 : }
     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      1427761 : frange_drop_infs (frange &r, tree type)
     464              : {
     465      1427761 :   REAL_VALUE_TYPE max = real_max_representable (type);
     466      1427761 :   REAL_VALUE_TYPE min = real_min_representable (type);
     467      1427761 :   frange tmp (type, min, max);
     468      1427761 :   r.intersect (tmp);
     469      1427761 : }
     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       990834 : frange_add_zeros (frange &r, tree type)
     475              : {
     476       990834 :   if (r.undefined_p () || r.known_isnan ())
     477              :     return;
     478              : 
     479       990834 :   if (HONOR_SIGNED_ZEROS (type)
     480       990834 :       && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
     481              :     {
     482       159556 :       frange zero;
     483       159556 :       zero.set_zero (type);
     484       159556 :       r.union_ (zero);
     485       159556 :     }
     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       256408 : build_le (frange &r, tree type, const frange &val)
     494              : {
     495       256408 :   gcc_checking_assert (!val.known_isnan ());
     496              : 
     497       256408 :   REAL_VALUE_TYPE ninf = frange_val_min (type);
     498       256408 :   r.set (type, ninf, val.upper_bound ());
     499              : 
     500              :   // Add both zeros if there's the possibility of zero equality.
     501       256408 :   frange_add_zeros (r, type);
     502              : 
     503       256408 :   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       305077 : build_lt (frange &r, tree type, const frange &val)
     512              : {
     513       305077 :   gcc_checking_assert (!val.known_isnan ());
     514              : 
     515              :   // < -INF is outside the range.
     516       305077 :   if (real_isinf (&val.upper_bound (), 1))
     517              :     {
     518         1494 :       if (HONOR_NANS (type))
     519         1494 :         r.set_nan (type);
     520              :       else
     521            0 :         r.set_undefined ();
     522         1494 :       return false;
     523              :     }
     524              : 
     525       303583 :   REAL_VALUE_TYPE ninf = frange_val_min (type);
     526       303583 :   REAL_VALUE_TYPE prev = val.upper_bound ();
     527       303583 :   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      2125081 :   if (!MODE_COMPOSITE_P (mode))
     533       303583 :     frange_nextafter (mode, prev, ninf);
     534       303583 :   r.set (type, ninf, prev);
     535       303583 :   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       382773 : build_ge (frange &r, tree type, const frange &val)
     544              : {
     545       382773 :   gcc_checking_assert (!val.known_isnan ());
     546              : 
     547       382773 :   REAL_VALUE_TYPE inf = frange_val_max (type);
     548       382773 :   r.set (type, val.lower_bound (), inf);
     549              : 
     550              :   // Add both zeros if there's the possibility of zero equality.
     551       382773 :   frange_add_zeros (r, type);
     552              : 
     553       382773 :   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       206598 : build_gt (frange &r, tree type, const frange &val)
     562              : {
     563       206598 :   gcc_checking_assert (!val.known_isnan ());
     564              : 
     565              :   // > +INF is outside the range.
     566       206598 :   if (real_isinf (&val.lower_bound (), 0))
     567              :     {
     568         3376 :       if (HONOR_NANS (type))
     569         3376 :         r.set_nan (type);
     570              :       else
     571            0 :         r.set_undefined ();
     572         3376 :       return false;
     573              :     }
     574              : 
     575       203222 :   REAL_VALUE_TYPE inf = frange_val_max (type);
     576       203222 :   REAL_VALUE_TYPE next = val.lower_bound ();
     577       203222 :   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      1422554 :   if (!MODE_COMPOSITE_P (mode))
     583       203222 :     frange_nextafter (mode, next, inf);
     584       203222 :   r.set (type, next, inf);
     585       203222 :   return true;
     586              : }
     587              : 
     588              : 
     589              : bool
     590        55185 : operator_identity::fold_range (frange &r, tree, const frange &op1,
     591              :                                const frange &, relation_trio) const
     592              : {
     593        55185 :   r = op1;
     594        55185 :   return true;
     595              : }
     596              : 
     597              : bool
     598        17017 : operator_identity::op1_range (frange &r, tree, const frange &lhs,
     599              :                               const frange &, relation_trio) const
     600              : {
     601        17017 :   r = lhs;
     602        17017 :   return true;
     603              : }
     604              : 
     605              : bool
     606          979 : operator_cst::fold_range (frange &r, tree, const frange &op1,
     607              :                           const frange &, relation_trio) const
     608              : {
     609          979 :   r = op1;
     610          979 :   return true;
     611              : }
     612              : 
     613              : bool
     614        25695 : operator_equal::op2_range (frange &r, tree type,
     615              :                            const irange &lhs, const frange &op1,
     616              :                            relation_trio rel) const
     617              : {
     618        25695 :   return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
     619              : }
     620              : 
     621              : bool
     622       171423 : operator_equal::fold_range (irange &r, tree type,
     623              :                             const frange &op1, const frange &op2,
     624              :                             relation_trio rel) const
     625              : {
     626       171423 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
     627              :     return true;
     628              : 
     629       169660 :   if (op1.known_isnan () || op2.known_isnan ())
     630          529 :     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       169131 :   else if (op1.singleton_p () && op2.singleton_p ())
     634              :     {
     635          491 :       if (op1 == op2)
     636          142 :         r = range_true (type);
     637              :       // If one operand is -0.0 and other 0.0, they are still equal.
     638          349 :       else if (real_iszero (&op1.lower_bound ())
     639          349 :                && real_iszero (&op2.lower_bound ()))
     640           30 :         r = range_true (type);
     641              :       else
     642          319 :         r = range_false (type);
     643              :     }
     644       168640 :   else if (real_iszero (&op1.lower_bound ())
     645         5744 :            && real_iszero (&op1.upper_bound ())
     646          726 :            && real_iszero (&op2.lower_bound ())
     647          300 :            && real_iszero (&op2.upper_bound ())
     648       168940 :            && !maybe_isnan (op1, op2))
     649              :     // [-0.0, 0.0] == [-0.0, 0.0] or similar.
     650          157 :     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       168483 :       frange tmp = op1;
     656       168483 :       tmp.intersect (op2);
     657       168483 :       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       167871 :         r = range_true_and_false (type);
     672       168483 :     }
     673              :   return true;
     674              : }
     675              : 
     676              : bool
     677       136492 : operator_equal::op1_range (frange &r, tree type,
     678              :                            const irange &lhs,
     679              :                            const frange &op2,
     680              :                            relation_trio trio) const
     681              : {
     682       136492 :   relation_kind rel = trio.op1_op2 ();
     683       136492 :   switch (get_bool_state (r, lhs, type))
     684              :     {
     685        37438 :     case BRS_TRUE:
     686              :       // The TRUE side of x == NAN is unreachable.
     687        37438 :       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        37438 :           r = op2;
     693              :           // Add both zeros if there's the possibility of zero equality.
     694        37438 :           frange_add_zeros (r, type);
     695              :           // The TRUE side of op1 == op2 implies op1 is !NAN.
     696        37438 :           r.clear_nan ();
     697              :         }
     698              :       break;
     699              : 
     700        97296 :     case BRS_FALSE:
     701              :       // The FALSE side of op1 == op1 implies op1 is a NAN.
     702        97296 :       if (rel == VREL_EQ)
     703         2217 :         r.set_nan (type);
     704              :       // On the FALSE side of x == NAN, we know nothing about x.
     705        95079 :       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        95079 :       else if (op2.singleton_p ()
     710       104138 :                || (!op2.maybe_isnan () && op2.zero_p ()))
     711              :         {
     712        62594 :           REAL_VALUE_TYPE tmp = op2.lower_bound ();
     713        62594 :           r.set (type, tmp, tmp, VR_ANTI_RANGE);
     714              :         }
     715              :       else
     716        32485 :         r.set_varying (type);
     717              :       break;
     718              : 
     719              :     default:
     720              :       break;
     721              :     }
     722       136492 :   return true;
     723              : }
     724              : 
     725              : // Check if the LHS range indicates a relation between OP1 and OP2.
     726              : 
     727              : relation_kind
     728       134185 : operator_equal::op1_op2_relation (const irange &lhs, const frange &,
     729              :                                   const frange &) const
     730              : {
     731       134185 :   if (lhs.undefined_p ())
     732              :     return VREL_UNDEFINED;
     733              : 
     734              :   // FALSE = op1 == op2 indicates NE_EXPR.
     735       134185 :   if (lhs.zero_p ())
     736              :     return VREL_NE;
     737              : 
     738              :   // TRUE = op1 == op2 indicates EQ_EXPR.
     739        70104 :   if (!contains_zero_p (lhs))
     740        68530 :     return VREL_EQ;
     741              :   return VREL_VARYING;
     742              : }
     743              : 
     744              : bool
     745       858713 : operator_not_equal::fold_range (irange &r, tree type,
     746              :                                 const frange &op1, const frange &op2,
     747              :                                 relation_trio trio) const
     748              : {
     749       858713 :   relation_kind rel = trio.op1_op2 ();
     750              : 
     751              :   // VREL_NE & NE_EXPR is always true, even with NANs.
     752       858713 :   if (rel == VREL_NE)
     753              :     {
     754           26 :       r = range_true (type);
     755           26 :       return true;
     756              :     }
     757       858687 :   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              :     }
     763       831643 :   else if (frelop_early_resolve (r, type, op1, op2, trio, VREL_NE))
     764              :     return true;
     765              : 
     766              :   // x != NAN is always TRUE.
     767       857328 :   if (op1.known_isnan () || op2.known_isnan ())
     768         1267 :     r = range_true (type);
     769              :   // We can be sure the values are always equal or not if both ranges
     770              :   // consist of a single value, and then compare them.
     771       856061 :   else if (op1.singleton_p () && op2.singleton_p ())
     772              :     {
     773         1358 :       if (op1 == op2)
     774          873 :         r = range_false (type);
     775              :       // If one operand is -0.0 and other 0.0, they are still equal.
     776          485 :       else if (real_iszero (&op1.lower_bound ())
     777          485 :                && real_iszero (&op2.lower_bound ()))
     778            0 :         r = range_false (type);
     779              :       else
     780          485 :         r = range_true (type);
     781              :     }
     782       854703 :   else if (real_iszero (&op1.lower_bound ())
     783         7184 :            && real_iszero (&op1.upper_bound ())
     784          403 :            && real_iszero (&op2.lower_bound ())
     785          224 :            && real_iszero (&op2.upper_bound ())
     786       854927 :            && !maybe_isnan (op1, op2))
     787              :     // [-0.0, 0.0] != [-0.0, 0.0] or similar.
     788          136 :     r = range_false (type);
     789              :   else
     790              :     {
     791              :       // If ranges do not intersect, we know the range is not equal,
     792              :       // otherwise we don't know anything for sure.
     793       854567 :       frange tmp = op1;
     794       854567 :       tmp.intersect (op2);
     795       854567 :       if (tmp.undefined_p ())
     796              :         {
     797              :           // If one range is [whatever, -0.0] and another
     798              :           // [0.0, whatever2], we don't know anything either,
     799              :           // because -0.0 == 0.0.
     800          542 :           if ((real_iszero (&op1.upper_bound ())
     801            5 :                && real_iszero (&op2.lower_bound ()))
     802          547 :               || (real_iszero (&op1.lower_bound ())
     803           10 :                   && real_iszero (&op2.upper_bound ())))
     804            0 :             r = range_true_and_false (type);
     805              :           else
     806          542 :             r = range_true (type);
     807              :         }
     808              :       else
     809       854025 :         r = range_true_and_false (type);
     810       854567 :     }
     811              :   return true;
     812              : }
     813              : 
     814              : bool
     815       363302 : operator_not_equal::op1_range (frange &r, tree type,
     816              :                                const irange &lhs,
     817              :                                const frange &op2,
     818              :                                relation_trio trio) const
     819              : {
     820       363302 :   relation_kind rel = trio.op1_op2 ();
     821       363302 :   switch (get_bool_state (r, lhs, type))
     822              :     {
     823        47346 :     case BRS_TRUE:
     824              :       // If the result is true, the only time we know anything is if
     825              :       // OP2 is a constant.
     826        47346 :       if (op2.singleton_p ())
     827              :         {
     828              :           // This is correct even if op1 is NAN, because the following
     829              :           // range would be ~[tmp, tmp] with the NAN property set to
     830              :           // maybe (VARYING).
     831        23266 :           REAL_VALUE_TYPE tmp = op2.lower_bound ();
     832        23266 :           r.set (type, tmp, tmp, VR_ANTI_RANGE);
     833              :         }
     834              :       // The TRUE side of op1 != op1 implies op1 is NAN.
     835        24080 :       else if (rel == VREL_EQ)
     836         5907 :         r.set_nan (type);
     837              :       else
     838        18173 :         r.set_varying (type);
     839              :       break;
     840              : 
     841       314372 :     case BRS_FALSE:
     842              :       // The FALSE side of x != NAN is impossible.
     843       314372 :       if (op2.known_isnan ())
     844          170 :         r.set_undefined ();
     845              :       else
     846              :         {
     847              :           // If it's false, the result is the same as OP2.
     848       314202 :           r = op2;
     849              :           // Add both zeros if there's the possibility of zero equality.
     850       314202 :           frange_add_zeros (r, type);
     851              :           // The FALSE side of op1 != op2 implies op1 is !NAN.
     852       314202 :           r.clear_nan ();
     853              :         }
     854              :       break;
     855              : 
     856              :     default:
     857              :       break;
     858              :     }
     859       363302 :   return true;
     860              : }
     861              : 
     862              : bool
     863       245393 : operator_not_equal::op2_range (frange &r, tree type,
     864              :                                const irange &lhs,
     865              :                                const frange &op1,
     866              :                                relation_trio trio) const
     867              : {
     868       245393 :   return op1_range (r, type, lhs, op1, trio);
     869              : }
     870              : 
     871              : // Check if the LHS range indicates a relation between OP1 and OP2.
     872              : 
     873              : relation_kind
     874       734367 : operator_not_equal::op1_op2_relation (const irange &lhs, const frange &,
     875              :                                       const frange &) const
     876              : {
     877       734367 :   if (lhs.undefined_p ())
     878              :     return VREL_UNDEFINED;
     879              : 
     880              :   // FALSE = op1 != op2  indicates EQ_EXPR.
     881       734367 :   if (lhs.zero_p ())
     882              :     return VREL_EQ;
     883              : 
     884              :   // TRUE = op1 != op2  indicates NE_EXPR.
     885       118262 :   if (!contains_zero_p (lhs))
     886       116705 :     return VREL_NE;
     887              :   return VREL_VARYING;
     888              : }
     889              : 
     890              : bool
     891       274607 : operator_lt::fold_range (irange &r, tree type,
     892              :                          const frange &op1, const frange &op2,
     893              :                          relation_trio trio) const
     894              : {
     895       274607 :   if (frelop_early_resolve (r, type, op1, op2, trio, VREL_LT))
     896              :     return true;
     897              : 
     898       273946 :   if (op1.known_isnan ()
     899       273490 :       || op2.known_isnan ()
     900       547189 :       || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
     901         2946 :     r = range_false (type);
     902       271000 :   else if (!maybe_isnan (op1, op2)
     903       271000 :            && real_less (&op1.upper_bound (), &op2.lower_bound ()))
     904         1083 :     r = range_true (type);
     905              :   else
     906       269917 :     r = range_true_and_false (type);
     907              :   return true;
     908              : }
     909              : 
     910              : bool
     911       430248 : operator_lt::op1_range (frange &r,
     912              :                         tree type,
     913              :                         const irange &lhs,
     914              :                         const frange &op2,
     915              :                         relation_trio) const
     916              : {
     917       430248 :   switch (get_bool_state (r, lhs, type))
     918              :     {
     919       146767 :     case BRS_TRUE:
     920              :       // The TRUE side of x < NAN is unreachable.
     921       146767 :       if (op2.known_isnan ())
     922           68 :         r.set_undefined ();
     923       146699 :       else if (op2.undefined_p ())
     924              :         return false;
     925       146699 :       else if (build_lt (r, type, op2))
     926              :         {
     927       146699 :           r.clear_nan ();
     928              :           // x < y implies x is not +INF.
     929       146699 :           frange_drop_inf (r, type);
     930              :         }
     931              :       break;
     932              : 
     933       282901 :     case BRS_FALSE:
     934              :       // On the FALSE side of x < NAN, we know nothing about x.
     935       534297 :       if (op2.maybe_isnan ())
     936        31505 :         r.set_varying (type);
     937              :       else
     938       251396 :         build_ge (r, type, op2);
     939              :       break;
     940              : 
     941              :     default:
     942              :       break;
     943              :     }
     944              :   return true;
     945              : }
     946              : 
     947              : bool
     948        68048 : operator_lt::op2_range (frange &r,
     949              :                         tree type,
     950              :                         const irange &lhs,
     951              :                         const frange &op1,
     952              :                         relation_trio) const
     953              : {
     954        68048 :   switch (get_bool_state (r, lhs, type))
     955              :     {
     956        27421 :     case BRS_TRUE:
     957              :       // The TRUE side of NAN < x is unreachable.
     958        27421 :       if (op1.known_isnan ())
     959           22 :         r.set_undefined ();
     960        27399 :       else if (op1.undefined_p ())
     961              :         return false;
     962        27399 :       else if (build_gt (r, type, op1))
     963              :         {
     964        27399 :           r.clear_nan ();
     965              :           // x < y implies y is not -INF.
     966        27399 :           frange_drop_ninf (r, type);
     967              :         }
     968              :       break;
     969              : 
     970        40236 :     case BRS_FALSE:
     971              :       // On the FALSE side of NAN < x, we know nothing about x.
     972        44228 :       if (op1.maybe_isnan ())
     973        36244 :         r.set_varying (type);
     974              :       else
     975         3992 :         build_le (r, type, op1);
     976              :       break;
     977              : 
     978              :     default:
     979              :       break;
     980              :     }
     981              :   return true;
     982              : }
     983              : 
     984              : 
     985              : // Check if the LHS range indicates a relation between OP1 and OP2.
     986              : 
     987              : relation_kind
     988       260157 : operator_lt::op1_op2_relation (const irange &lhs, const frange &,
     989              :                                const frange &) const
     990              : {
     991       260157 :   if (lhs.undefined_p ())
     992              :     return VREL_UNDEFINED;
     993              : 
     994              :   // FALSE = op1 < op2 indicates GE_EXPR.
     995       260157 :   if (lhs.zero_p ())
     996              :     return VREL_GE;
     997              : 
     998              :   // TRUE = op1 < op2 indicates LT_EXPR.
     999       119438 :   if (!contains_zero_p (lhs))
    1000       118686 :     return VREL_LT;
    1001              :   return VREL_VARYING;
    1002              : }
    1003              : 
    1004              : bool
    1005       272758 : operator_le::fold_range (irange &r, tree type,
    1006              :                          const frange &op1, const frange &op2,
    1007              :                          relation_trio rel) const
    1008              : {
    1009       272758 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
    1010              :     return true;
    1011              : 
    1012       272183 :   if (op1.known_isnan ()
    1013       271129 :       || op2.known_isnan ()
    1014       543278 :       || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1015         2522 :     r = range_false (type);
    1016       269661 :   else if (!maybe_isnan (op1, op2)
    1017       269661 :            && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1018          855 :     r = range_true (type);
    1019              :   else
    1020       268806 :     r = range_true_and_false (type);
    1021              :   return true;
    1022              : }
    1023              : 
    1024              : bool
    1025        99837 : operator_le::op1_range (frange &r,
    1026              :                         tree type,
    1027              :                         const irange &lhs,
    1028              :                         const frange &op2,
    1029              :                         relation_trio) const
    1030              : {
    1031        99837 :   switch (get_bool_state (r, lhs, type))
    1032              :     {
    1033        68408 :     case BRS_TRUE:
    1034              :       // The TRUE side of x <= NAN is unreachable.
    1035        68408 :       if (op2.known_isnan ())
    1036            0 :         r.set_undefined ();
    1037        68408 :       else if (op2.undefined_p ())
    1038              :         return false;
    1039        68408 :       else if (build_le (r, type, op2))
    1040        68408 :         r.clear_nan ();
    1041              :       break;
    1042              : 
    1043        31090 :     case BRS_FALSE:
    1044              :       // On the FALSE side of x <= NAN, we know nothing about x.
    1045        56627 :       if (op2.maybe_isnan ())
    1046         5553 :         r.set_varying (type);
    1047              :       else
    1048        25537 :         build_gt (r, type, op2);
    1049              :       break;
    1050              : 
    1051              :     default:
    1052              :       break;
    1053              :     }
    1054              :   return true;
    1055              : }
    1056              : 
    1057              : bool
    1058        15954 : operator_le::op2_range (frange &r,
    1059              :                         tree type,
    1060              :                         const irange &lhs,
    1061              :                         const frange &op1,
    1062              :                         relation_trio) const
    1063              : {
    1064        15954 :   switch (get_bool_state (r, lhs, type))
    1065              :     {
    1066         4434 :     case BRS_TRUE:
    1067              :       // The TRUE side of NAN <= x is unreachable.
    1068         4434 :       if (op1.known_isnan ())
    1069            0 :         r.set_undefined ();
    1070         4434 :       else if (op1.undefined_p ())
    1071              :         return false;
    1072         4434 :       else if (build_ge (r, type, op1))
    1073         4434 :         r.clear_nan ();
    1074              :       break;
    1075              : 
    1076        11217 :     case BRS_FALSE:
    1077              :       // On the FALSE side of NAN <= x, we know nothing about x.
    1078        12063 :       if (op1.maybe_isnan ())
    1079        10371 :         r.set_varying (type);
    1080          846 :       else if (op1.undefined_p ())
    1081              :         return false;
    1082              :       else
    1083          846 :         build_lt (r, type, op1);
    1084              :       break;
    1085              : 
    1086              :     default:
    1087              :       break;
    1088              :     }
    1089              :   return true;
    1090              : }
    1091              : 
    1092              : // Check if the LHS range indicates a relation between OP1 and OP2.
    1093              : 
    1094              : relation_kind
    1095        64989 : operator_le::op1_op2_relation (const irange &lhs, const frange &,
    1096              :                                const frange &) const
    1097              : {
    1098        64989 :   if (lhs.undefined_p ())
    1099              :     return VREL_UNDEFINED;
    1100              : 
    1101              :   // FALSE = op1 <= op2 indicates GT_EXPR.
    1102        64989 :   if (lhs.zero_p ())
    1103              :     return VREL_GT;
    1104              : 
    1105              :   // TRUE = op1 <= op2 indicates LE_EXPR.
    1106        32443 :   if (!contains_zero_p (lhs))
    1107        31833 :     return VREL_LE;
    1108              :   return VREL_VARYING;
    1109              : }
    1110              : 
    1111              : bool
    1112       277067 : operator_gt::fold_range (irange &r, tree type,
    1113              :                          const frange &op1, const frange &op2,
    1114              :                          relation_trio trio) const
    1115              : {
    1116       277067 :   if (frelop_early_resolve (r, type, op1, op2, trio, VREL_GT))
    1117              :     return true;
    1118              : 
    1119       276324 :   if (op1.known_isnan ()
    1120       275971 :       || op2.known_isnan ()
    1121       552046 :       || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1122         4528 :     r = range_false (type);
    1123       271796 :   else if (!maybe_isnan (op1, op2)
    1124       271796 :            && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1125          689 :     r = range_true (type);
    1126              :   else
    1127       271107 :     r = range_true_and_false (type);
    1128              :   return true;
    1129              : }
    1130              : 
    1131              : bool
    1132       172463 : operator_gt::op1_range (frange &r,
    1133              :                         tree type,
    1134              :                         const irange &lhs,
    1135              :                         const frange &op2,
    1136              :                         relation_trio) const
    1137              : {
    1138       172463 :   switch (get_bool_state (r, lhs, type))
    1139              :     {
    1140        66651 :     case BRS_TRUE:
    1141              :       // The TRUE side of x > NAN is unreachable.
    1142        66651 :       if (op2.known_isnan ())
    1143           28 :         r.set_undefined ();
    1144        66623 :       else if (op2.undefined_p ())
    1145              :         return false;
    1146        66623 :       else if (build_gt (r, type, op2))
    1147              :         {
    1148        66623 :           r.clear_nan ();
    1149              :           // x > y implies x is not -INF.
    1150        66623 :           frange_drop_ninf (r, type);
    1151              :         }
    1152              :       break;
    1153              : 
    1154       105065 :     case BRS_FALSE:
    1155              :       // On the FALSE side of x > NAN, we know nothing about x.
    1156       180184 :       if (op2.maybe_isnan ())
    1157        29946 :         r.set_varying (type);
    1158        75119 :       else if (op2.undefined_p ())
    1159              :         return false;
    1160              :       else
    1161        75119 :         build_le (r, type, op2);
    1162              :       break;
    1163              : 
    1164              :     default:
    1165              :       break;
    1166              :     }
    1167              :   return true;
    1168              : }
    1169              : 
    1170              : bool
    1171        72494 : operator_gt::op2_range (frange &r,
    1172              :                         tree type,
    1173              :                         const irange &lhs,
    1174              :                         const frange &op1,
    1175              :                         relation_trio) const
    1176              : {
    1177        72494 :   switch (get_bool_state (r, lhs, type))
    1178              :     {
    1179        28564 :     case BRS_TRUE:
    1180              :       // The TRUE side of NAN > x is unreachable.
    1181        28564 :       if (op1.known_isnan ())
    1182           22 :         r.set_undefined ();
    1183        28542 :       else if (op1.undefined_p ())
    1184              :         return false;
    1185        28542 :       else if (build_lt (r, type, op1))
    1186              :         {
    1187        28542 :           r.clear_nan ();
    1188              :           // x > y implies y is not +INF.
    1189        28542 :           frange_drop_inf (r, type);
    1190              :         }
    1191              :       break;
    1192              : 
    1193        43517 :     case BRS_FALSE:
    1194              :       // On The FALSE side of NAN > x, we know nothing about x.
    1195        46862 :       if (op1.maybe_isnan ())
    1196        40172 :         r.set_varying (type);
    1197         3345 :       else if (op1.undefined_p ())
    1198              :         return false;
    1199              :       else
    1200         3345 :         build_ge (r, type, op1);
    1201              :       break;
    1202              : 
    1203              :     default:
    1204              :       break;
    1205              :     }
    1206              :   return true;
    1207              : }
    1208              : 
    1209              : // Check if the LHS range indicates a relation between OP1 and OP2.
    1210              : 
    1211              : relation_kind
    1212       276205 : operator_gt::op1_op2_relation (const irange &lhs, const frange &,
    1213              :                                const frange &) const
    1214              : {
    1215       276205 :   if (lhs.undefined_p ())
    1216              :     return VREL_UNDEFINED;
    1217              : 
    1218              :   // FALSE = op1 > op2 indicates LE_EXPR.
    1219       276205 :   if (lhs.zero_p ())
    1220              :     return VREL_LE;
    1221              : 
    1222              :   // TRUE = op1 > op2 indicates GT_EXPR.
    1223       124885 :   if (!contains_zero_p (lhs))
    1224       124023 :     return VREL_GT;
    1225              :   return VREL_VARYING;
    1226              : }
    1227              : 
    1228              : bool
    1229       269810 : operator_ge::fold_range (irange &r, tree type,
    1230              :                          const frange &op1, const frange &op2,
    1231              :                          relation_trio rel) const
    1232              : {
    1233       269810 :   if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
    1234              :     return true;
    1235              : 
    1236       269431 :   if (op1.known_isnan ()
    1237       268613 :       || op2.known_isnan ()
    1238       538013 :       || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
    1239         1498 :     r = range_false (type);
    1240       267933 :   else if (!maybe_isnan (op1, op2)
    1241       267933 :            && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
    1242         2509 :     r = range_true (type);
    1243              :   else
    1244       265424 :     r = range_true_and_false (type);
    1245              :   return true;
    1246              : }
    1247              : 
    1248              : bool
    1249       109119 : operator_ge::op1_range (frange &r,
    1250              :                         tree type,
    1251              :                         const irange &lhs,
    1252              :                         const frange &op2,
    1253              :                         relation_trio) const
    1254              : {
    1255       109119 :   switch (get_bool_state (r, lhs, type))
    1256              :     {
    1257        60576 :     case BRS_TRUE:
    1258              :       // The TRUE side of x >= NAN is unreachable.
    1259        60576 :       if (op2.known_isnan ())
    1260            0 :         r.set_undefined ();
    1261        60576 :       else if (op2.undefined_p ())
    1262              :         return false;
    1263        60576 :       else if (build_ge (r, type, op2))
    1264        60576 :         r.clear_nan ();
    1265              :       break;
    1266              : 
    1267        48240 :     case BRS_FALSE:
    1268              :       // On the FALSE side of x >= NAN, we know nothing about x.
    1269        89403 :       if (op2.maybe_isnan ())
    1270         7077 :         r.set_varying (type);
    1271        41163 :       else if (op2.undefined_p ())
    1272              :         return false;
    1273              :       else
    1274        41163 :         build_lt (r, type, op2);
    1275              :       break;
    1276              : 
    1277              :     default:
    1278              :       break;
    1279              :     }
    1280              :   return true;
    1281              : }
    1282              : 
    1283              : bool
    1284        14295 : operator_ge::op2_range (frange &r, tree type,
    1285              :                         const irange &lhs,
    1286              :                         const frange &op1,
    1287              :                         relation_trio) const
    1288              : {
    1289        14295 :   switch (get_bool_state (r, lhs, type))
    1290              :     {
    1291         5671 :     case BRS_TRUE:
    1292              :       // The TRUE side of NAN >= x is unreachable.
    1293         5671 :       if (op1.known_isnan ())
    1294            0 :         r.set_undefined ();
    1295         5671 :       else if (op1.undefined_p ())
    1296              :         return false;
    1297         5671 :       else if (build_le (r, type, op1))
    1298         5671 :         r.clear_nan ();
    1299              :       break;
    1300              : 
    1301         8357 :     case BRS_FALSE:
    1302              :       // On the FALSE side of NAN >= x, we know nothing about x.
    1303         9120 :       if (op1.maybe_isnan ())
    1304         7594 :         r.set_varying (type);
    1305          763 :       else if (op1.undefined_p ())
    1306              :         return false;
    1307              :       else
    1308          763 :         build_gt (r, type, op1);
    1309              :       break;
    1310              : 
    1311              :     default:
    1312              :       break;
    1313              :     }
    1314              :   return true;
    1315              : }
    1316              : 
    1317              : // Check if the LHS range indicates a relation between OP1 and OP2.
    1318              : 
    1319              : relation_kind
    1320        61197 : operator_ge::op1_op2_relation (const irange &lhs, const frange &,
    1321              :                                const frange &) const
    1322              : {
    1323        61197 :   if (lhs.undefined_p ())
    1324              :     return VREL_UNDEFINED;
    1325              : 
    1326              :   // FALSE = op1 >= op2 indicates LT_EXPR.
    1327        61197 :   if (lhs.zero_p ())
    1328              :     return VREL_LT;
    1329              : 
    1330              :   // TRUE = op1 >= op2 indicates GE_EXPR.
    1331        31660 :   if (!contains_zero_p (lhs))
    1332        31122 :     return VREL_GE;
    1333              :   return VREL_VARYING;
    1334              : }
    1335              : 
    1336              : // UNORDERED_EXPR comparison.
    1337              : 
    1338              : class foperator_unordered : public range_operator
    1339              : {
    1340              :   using range_operator::fold_range;
    1341              :   using range_operator::op1_range;
    1342              :   using range_operator::op2_range;
    1343              : public:
    1344              :   bool fold_range (irange &r, tree type,
    1345              :                    const frange &op1, const frange &op2,
    1346              :                    relation_trio = TRIO_VARYING) const final override;
    1347              :   bool op1_range (frange &r, tree type,
    1348              :                   const irange &lhs, const frange &op2,
    1349              :                   relation_trio = TRIO_VARYING) const final override;
    1350        56460 :   bool op2_range (frange &r, tree type,
    1351              :                   const irange &lhs, const frange &op1,
    1352              :                   relation_trio rel = TRIO_VARYING) const final override
    1353              :   {
    1354        56460 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    1355              :   }
    1356              : } fop_unordered;
    1357              : 
    1358              : bool
    1359        54138 : foperator_unordered::fold_range (irange &r, tree type,
    1360              :                                  const frange &op1, const frange &op2,
    1361              :                                  relation_trio) const
    1362              : {
    1363              :   // UNORDERED is TRUE if either operand is a NAN.
    1364        54138 :   if (op1.known_isnan () || op2.known_isnan ())
    1365          115 :     r = range_true (type);
    1366              :   // UNORDERED is FALSE if neither operand is a NAN.
    1367        56483 :   else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
    1368         1232 :     r = range_false (type);
    1369              :   else
    1370        52791 :     r = range_true_and_false (type);
    1371        54138 :   return true;
    1372              : }
    1373              : 
    1374              : bool
    1375       103100 : foperator_unordered::op1_range (frange &r, tree type,
    1376              :                                 const irange &lhs,
    1377              :                                 const frange &op2,
    1378              :                                 relation_trio trio) const
    1379              : {
    1380       103100 :   relation_kind rel = trio.op1_op2 ();
    1381       103100 :   switch (get_bool_state (r, lhs, type))
    1382              :     {
    1383        37810 :     case BRS_TRUE:
    1384              :       // Since at least one operand must be NAN, if one of them is
    1385              :       // not, the other must be.
    1386        37810 :       if (rel == VREL_EQ || !op2.maybe_isnan ())
    1387         9557 :         r.set_nan (type);
    1388              :       else
    1389        28253 :         r.set_varying (type);
    1390              :       break;
    1391              : 
    1392        57447 :     case BRS_FALSE:
    1393              :       // A false UNORDERED means both operands are !NAN, so it's
    1394              :       // impossible for op2 to be a NAN.
    1395        57447 :       if (op2.known_isnan ())
    1396            0 :         r.set_undefined ();
    1397              :       else
    1398              :         {
    1399        57447 :           r.set_varying (type);
    1400        57447 :           r.clear_nan ();
    1401              :         }
    1402              :       break;
    1403              : 
    1404              :     default:
    1405              :       break;
    1406              :     }
    1407       103100 :   return true;
    1408              : }
    1409              : 
    1410              : // ORDERED_EXPR comparison.
    1411              : 
    1412              : class foperator_ordered : public range_operator
    1413              : {
    1414              :   using range_operator::fold_range;
    1415              :   using range_operator::op1_range;
    1416              :   using range_operator::op2_range;
    1417              : public:
    1418              :   bool fold_range (irange &r, tree type,
    1419              :                    const frange &op1, const frange &op2,
    1420              :                    relation_trio = TRIO_VARYING) const final override;
    1421              :   bool op1_range (frange &r, tree type,
    1422              :                   const irange &lhs, const frange &op2,
    1423              :                   relation_trio = TRIO_VARYING) const final override;
    1424        30098 :   bool op2_range (frange &r, tree type,
    1425              :                   const irange &lhs, const frange &op1,
    1426              :                   relation_trio rel = TRIO_VARYING) const final override
    1427              :   {
    1428        30098 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    1429              :   }
    1430              : } fop_ordered;
    1431              : 
    1432              : bool
    1433        32907 : foperator_ordered::fold_range (irange &r, tree type,
    1434              :                                const frange &op1, const frange &op2,
    1435              :                                relation_trio) const
    1436              : {
    1437        32907 :   if (op1.known_isnan () || op2.known_isnan ())
    1438          366 :     r = range_false (type);
    1439        35491 :   else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
    1440         1472 :     r = range_true (type);
    1441              :   else
    1442        31069 :     r = range_true_and_false (type);
    1443        32907 :   return true;
    1444              : }
    1445              : 
    1446              : bool
    1447        63999 : foperator_ordered::op1_range (frange &r, tree type,
    1448              :                               const irange &lhs,
    1449              :                               const frange &op2,
    1450              :                               relation_trio trio) const
    1451              : {
    1452        63999 :   relation_kind rel = trio.op1_op2 ();
    1453        63999 :   switch (get_bool_state (r, lhs, type))
    1454              :     {
    1455        57326 :     case BRS_TRUE:
    1456              :       // The TRUE side of ORDERED means both operands are !NAN, so
    1457              :       // it's impossible for op2 to be a NAN.
    1458        57326 :       if (op2.known_isnan ())
    1459           10 :         r.set_undefined ();
    1460              :       else
    1461              :         {
    1462        57316 :           r.set_varying (type);
    1463        57316 :           r.clear_nan ();
    1464              :         }
    1465              :       break;
    1466              : 
    1467         4690 :     case BRS_FALSE:
    1468              :       // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
    1469         4690 :       if (rel == VREL_EQ)
    1470         2175 :         r.set_nan (type);
    1471              :       else
    1472         2515 :         r.set_varying (type);
    1473              :       break;
    1474              : 
    1475              :     default:
    1476              :       break;
    1477              :     }
    1478        63999 :   return true;
    1479              : }
    1480              : 
    1481              : bool
    1482       241327 : operator_negate::fold_range (frange &r, tree type,
    1483              :                              const frange &op1, const frange &op2,
    1484              :                              relation_trio) const
    1485              : {
    1486       241327 :   if (empty_range_varying (r, type, op1, op2))
    1487          353 :     return true;
    1488       240974 :   if (op1.known_isnan ())
    1489              :     {
    1490          398 :       bool sign;
    1491          398 :       if (op1.nan_signbit_p (sign))
    1492           38 :         r.set_nan (type, !sign);
    1493              :       else
    1494          360 :         r.set_nan (type);
    1495          398 :       return true;
    1496              :     }
    1497              : 
    1498       240576 :   REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
    1499       240576 :   REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
    1500       240576 :   lh_lb = real_value_negate (&lh_lb);
    1501       240576 :   lh_ub = real_value_negate (&lh_ub);
    1502       240576 :   r.set (type, lh_ub, lh_lb);
    1503       430232 :   if (op1.maybe_isnan ())
    1504              :     {
    1505        50924 :       bool sign;
    1506        50924 :       if (op1.nan_signbit_p (sign))
    1507         2396 :         r.update_nan (!sign);
    1508              :       else
    1509        48528 :         r.update_nan ();
    1510              :     }
    1511              :   else
    1512       189652 :     r.clear_nan ();
    1513              :   return true;
    1514              : }
    1515              : 
    1516              : bool
    1517         3166 : operator_negate::op1_range (frange &r, tree type,
    1518              :                             const frange &lhs, const frange &op2,
    1519              :                             relation_trio rel) const
    1520              : {
    1521         3166 :   return fold_range (r, type, lhs, op2, rel);
    1522              : }
    1523              : 
    1524              : bool
    1525       572406 : operator_abs::fold_range (frange &r, tree type,
    1526              :                           const frange &op1, const frange &op2,
    1527              :                           relation_trio) const
    1528              : {
    1529       572406 :   if (empty_range_varying (r, type, op1, op2))
    1530          113 :     return true;
    1531       572293 :   if (op1.known_isnan ())
    1532              :     {
    1533          586 :       r.set_nan (type, /*sign=*/false);
    1534          586 :       return true;
    1535              :     }
    1536              : 
    1537       571707 :   const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
    1538       571707 :   const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
    1539              :   // Handle the easy case where everything is positive.
    1540       571707 :   if (real_compare (GE_EXPR, &lh_lb, &dconst0)
    1541       161543 :       && !real_iszero (&lh_lb, /*sign=*/true)
    1542       730688 :       && !op1.maybe_isnan (/*sign=*/true))
    1543              :     {
    1544       158616 :       r = op1;
    1545       158616 :       return true;
    1546              :     }
    1547              : 
    1548       413091 :   REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
    1549       413091 :   REAL_VALUE_TYPE max = real_value_abs (&lh_ub);
    1550              :   // If the range contains zero then we know that the minimum value in the
    1551              :   // range will be zero.
    1552       413091 :   if (real_compare (LE_EXPR, &lh_lb, &dconst0)
    1553       413091 :       && real_compare (GE_EXPR, &lh_ub, &dconst0))
    1554              :     {
    1555       412224 :       if (real_compare (GT_EXPR, &min, &max))
    1556         5414 :         max = min;
    1557       412224 :       min = dconst0;
    1558              :     }
    1559              :   else
    1560              :     {
    1561              :       // If the range was reversed, swap MIN and MAX.
    1562          867 :       if (real_compare (GT_EXPR, &min, &max))
    1563          788 :         std::swap (min, max);
    1564              :     }
    1565              : 
    1566       413091 :   r.set (type, min, max);
    1567       439139 :   if (op1.maybe_isnan ())
    1568       388974 :     r.update_nan (/*sign=*/false);
    1569              :   else
    1570        24117 :     r.clear_nan ();
    1571              :   return true;
    1572              : }
    1573              : 
    1574              : bool
    1575       323490 : operator_abs::op1_range (frange &r, tree type,
    1576              :                          const frange &lhs, const frange &op2,
    1577              :                          relation_trio) const
    1578              : {
    1579       323490 :   if (empty_range_varying (r, type, lhs, op2))
    1580            0 :     return true;
    1581       323490 :   if (lhs.known_isnan ())
    1582              :     {
    1583         2853 :       r.set_nan (type);
    1584         2853 :       return true;
    1585              :     }
    1586              : 
    1587              :   // Start with the positives because negatives are an impossible result.
    1588       320637 :   frange positives (type, dconst0, frange_val_max (type));
    1589       320637 :   positives.update_nan (/*sign=*/false);
    1590       320637 :   positives.intersect (lhs);
    1591       320637 :   r = positives;
    1592              :   // Add -NAN if relevant.
    1593       484495 :   if (r.maybe_isnan ())
    1594              :     {
    1595       156719 :       frange neg_nan;
    1596       156719 :       neg_nan.set_nan (type, true);
    1597       156719 :       r.union_ (neg_nan);
    1598       156719 :     }
    1599       320637 :   if (r.known_isnan () || r.undefined_p ())
    1600              :     return true;
    1601              :   // Then add the negative of each pair:
    1602              :   // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
    1603       320565 :   frange negatives (type, real_value_negate (&positives.upper_bound ()),
    1604       320565 :                     real_value_negate (&positives.lower_bound ()));
    1605       320565 :   negatives.clear_nan ();
    1606       320565 :   r.union_ (negatives);
    1607       320565 :   return true;
    1608       641202 : }
    1609              : 
    1610              : class foperator_unordered_lt : public range_operator
    1611              : {
    1612              :   using range_operator::fold_range;
    1613              :   using range_operator::op1_range;
    1614              :   using range_operator::op2_range;
    1615              : public:
    1616        11078 :   bool fold_range (irange &r, tree type,
    1617              :                    const frange &op1, const frange &op2,
    1618              :                    relation_trio trio = TRIO_VARYING) const final override
    1619              :   {
    1620        11078 :     if (op1.known_isnan () || op2.known_isnan ())
    1621              :       {
    1622           33 :         r = range_true (type);
    1623           33 :         return true;
    1624              :       }
    1625        11045 :     frange op1_no_nan = op1;
    1626        11045 :     frange op2_no_nan = op2;
    1627        13650 :     if (op1.maybe_isnan ())
    1628         8424 :       op1_no_nan.clear_nan ();
    1629        18506 :     if (op2.maybe_isnan ())
    1630         3584 :       op2_no_nan.clear_nan ();
    1631        11045 :     if (!range_op_handler (LT_EXPR).fold_range (r, type, op1_no_nan,
    1632              :                                                 op2_no_nan, trio))
    1633              :       return false;
    1634              :     // The result is the same as the ordered version when the
    1635              :     // comparison is true or when the operands cannot be NANs.
    1636        11045 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1637              :       return true;
    1638              :     else
    1639              :       {
    1640         8320 :         r = range_true_and_false (type);
    1641         8320 :         return true;
    1642              :       }
    1643        11045 :   }
    1644              :   bool op1_range (frange &r, tree type,
    1645              :                   const irange &lhs,
    1646              :                   const frange &op2,
    1647              :                   relation_trio trio) const final override;
    1648              :   bool op2_range (frange &r, tree type,
    1649              :                   const irange &lhs,
    1650              :                   const frange &op1,
    1651              :                   relation_trio trio) const final override;
    1652              : } fop_unordered_lt;
    1653              : 
    1654              : bool
    1655         3606 : foperator_unordered_lt::op1_range (frange &r, tree type,
    1656              :                                    const irange &lhs,
    1657              :                                    const frange &op2,
    1658              :                                    relation_trio) const
    1659              : {
    1660         3606 :   switch (get_bool_state (r, lhs, type))
    1661              :     {
    1662         1740 :     case BRS_TRUE:
    1663         3424 :       if (op2.maybe_isnan ())
    1664           56 :         r.set_varying (type);
    1665         1684 :       else if (op2.undefined_p ())
    1666              :         return false;
    1667              :       else
    1668         1684 :         build_lt (r, type, op2);
    1669              :       break;
    1670              : 
    1671         1236 :     case BRS_FALSE:
    1672              :       // A false UNORDERED_LT means both operands are !NAN, so it's
    1673              :       // impossible for op2 to be a NAN.
    1674         1236 :       if (op2.known_isnan ())
    1675            0 :         r.set_undefined ();
    1676         1236 :       else if (op2.undefined_p ())
    1677              :         return false;
    1678         1236 :       else if (build_ge (r, type, op2))
    1679         1236 :         r.clear_nan ();
    1680              :       break;
    1681              : 
    1682              :     default:
    1683              :       break;
    1684              :     }
    1685              :   return true;
    1686              : }
    1687              : 
    1688              : bool
    1689          686 : foperator_unordered_lt::op2_range (frange &r, tree type,
    1690              :                                    const irange &lhs,
    1691              :                                    const frange &op1,
    1692              :                                    relation_trio) const
    1693              : {
    1694          686 :   switch (get_bool_state (r, lhs, type))
    1695              :     {
    1696           56 :     case BRS_TRUE:
    1697           56 :       if (op1.maybe_isnan ())
    1698           56 :         r.set_varying (type);
    1699            0 :       else if (op1.undefined_p ())
    1700              :         return false;
    1701              :       else
    1702            0 :         build_gt (r, type, op1);
    1703              :       break;
    1704              : 
    1705            0 :     case BRS_FALSE:
    1706              :       // A false UNORDERED_LT means both operands are !NAN, so it's
    1707              :       // impossible for op1 to be a NAN.
    1708            0 :       if (op1.known_isnan ())
    1709            0 :         r.set_undefined ();
    1710            0 :       else if (op1.undefined_p ())
    1711              :         return false;
    1712            0 :       else if (build_le (r, type, op1))
    1713            0 :         r.clear_nan ();
    1714              :       break;
    1715              : 
    1716              :     default:
    1717              :       break;
    1718              :     }
    1719              :   return true;
    1720              : }
    1721              : 
    1722              : class foperator_unordered_le : public range_operator
    1723              : {
    1724              :   using range_operator::fold_range;
    1725              :   using range_operator::op1_range;
    1726              :   using range_operator::op2_range;
    1727              : public:
    1728       180006 :   bool fold_range (irange &r, tree type,
    1729              :                    const frange &op1, const frange &op2,
    1730              :                    relation_trio trio = TRIO_VARYING) const final override
    1731              :   {
    1732       180006 :     if (op1.known_isnan () || op2.known_isnan ())
    1733              :       {
    1734           98 :         r = range_true (type);
    1735           98 :         return true;
    1736              :       }
    1737       179908 :     frange op1_no_nan = op1;
    1738       179908 :     frange op2_no_nan = op2;
    1739       205990 :     if (op1.maybe_isnan ())
    1740       153800 :       op1_no_nan.clear_nan ();
    1741       352623 :     if (op2.maybe_isnan ())
    1742         7187 :       op2_no_nan.clear_nan ();
    1743       179908 :     if (!range_op_handler (LE_EXPR).fold_range (r, type, op1_no_nan,
    1744              :                                                 op2_no_nan, trio))
    1745              :       return false;
    1746              :     // The result is the same as the ordered version when the
    1747              :     // comparison is true or when the operands cannot be NANs.
    1748       179908 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1749              :       return true;
    1750              :     else
    1751              :       {
    1752       155564 :         r = range_true_and_false (type);
    1753       155564 :         return true;
    1754              :       }
    1755       179908 :   }
    1756              :   bool op1_range (frange &r, tree type,
    1757              :                   const irange &lhs, const frange &op2,
    1758              :                   relation_trio = TRIO_VARYING) const final override;
    1759              :   bool op2_range (frange &r, tree type,
    1760              :                   const irange &lhs, const frange &op1,
    1761              :                   relation_trio = TRIO_VARYING) const final override;
    1762              : } fop_unordered_le;
    1763              : 
    1764              : bool
    1765       167175 : foperator_unordered_le::op1_range (frange &r, tree type,
    1766              :                                    const irange &lhs, const frange &op2,
    1767              :                                    relation_trio) const
    1768              : {
    1769       167175 :   switch (get_bool_state (r, lhs, type))
    1770              :     {
    1771        92219 :     case BRS_TRUE:
    1772       179321 :       if (op2.maybe_isnan ())
    1773         5117 :         r.set_varying (type);
    1774        87102 :       else if (op2.undefined_p ())
    1775              :         return false;
    1776              :       else
    1777        87102 :         build_le (r, type, op2);
    1778              :       break;
    1779              : 
    1780        74312 :     case BRS_FALSE:
    1781              :       // A false UNORDERED_LE means both operands are !NAN, so it's
    1782              :       // impossible for op2 to be a NAN.
    1783        74312 :       if (op2.known_isnan ())
    1784            0 :         r.set_undefined ();
    1785        74312 :       else if (build_gt (r, type, op2))
    1786        74310 :         r.clear_nan ();
    1787              :       break;
    1788              : 
    1789              :     default:
    1790              :       break;
    1791              :     }
    1792              :   return true;
    1793              : }
    1794              : 
    1795              : bool
    1796        14100 : foperator_unordered_le::op2_range (frange &r,
    1797              :                                    tree type,
    1798              :                                    const irange &lhs,
    1799              :                                    const frange &op1,
    1800              :                                    relation_trio) const
    1801              : {
    1802        14100 :   switch (get_bool_state (r, lhs, type))
    1803              :     {
    1804         9851 :     case BRS_TRUE:
    1805        14857 :       if (op1.maybe_isnan ())
    1806         4845 :         r.set_varying (type);
    1807         5006 :       else if (op1.undefined_p ())
    1808              :         return false;
    1809              :       else
    1810         5006 :         build_ge (r, type, op1);
    1811              :       break;
    1812              : 
    1813         3605 :     case BRS_FALSE:
    1814              :       // A false UNORDERED_LE means both operands are !NAN, so it's
    1815              :       // impossible for op1 to be a NAN.
    1816         3605 :       if (op1.known_isnan ())
    1817            0 :         r.set_undefined ();
    1818         3605 :       else if (op1.undefined_p ())
    1819              :         return false;
    1820         3605 :       else if (build_lt (r, type, op1))
    1821         3605 :         r.clear_nan ();
    1822              :       break;
    1823              : 
    1824              :     default:
    1825              :       break;
    1826              :     }
    1827              :   return true;
    1828              : }
    1829              : 
    1830              : class foperator_unordered_gt : public range_operator
    1831              : {
    1832              :   using range_operator::fold_range;
    1833              :   using range_operator::op1_range;
    1834              :   using range_operator::op2_range;
    1835              : public:
    1836        48269 :   bool fold_range (irange &r, tree type,
    1837              :                    const frange &op1, const frange &op2,
    1838              :                    relation_trio trio = TRIO_VARYING) const final override
    1839              :   {
    1840        48269 :     if (op1.known_isnan () || op2.known_isnan ())
    1841              :       {
    1842          159 :         r = range_true (type);
    1843          159 :         return true;
    1844              :       }
    1845        48110 :     frange op1_no_nan = op1;
    1846        48110 :     frange op2_no_nan = op2;
    1847        52074 :     if (op1.maybe_isnan ())
    1848        44127 :       op1_no_nan.clear_nan ();
    1849        92544 :     if (op2.maybe_isnan ())
    1850         3676 :       op2_no_nan.clear_nan ();
    1851        48110 :     if (!range_op_handler (GT_EXPR).fold_range (r, type, op1_no_nan,
    1852              :                                                 op2_no_nan, trio))
    1853              :       return false;
    1854              :     // The result is the same as the ordered version when the
    1855              :     // comparison is true or when the operands cannot be NANs.
    1856        48110 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1857              :       return true;
    1858              :     else
    1859              :       {
    1860        44020 :         r = range_true_and_false (type);
    1861        44020 :         return true;
    1862              :       }
    1863        48110 :   }
    1864              :   bool op1_range (frange &r, tree type,
    1865              :                   const irange &lhs, const frange &op2,
    1866              :                   relation_trio = TRIO_VARYING) const final override;
    1867              :   bool op2_range (frange &r, tree type,
    1868              :                   const irange &lhs, const frange &op1,
    1869              :                   relation_trio = TRIO_VARYING) const final override;
    1870              : } fop_unordered_gt;
    1871              : 
    1872              : bool
    1873        18994 : foperator_unordered_gt::op1_range (frange &r,
    1874              :                                    tree type,
    1875              :                                    const irange &lhs,
    1876              :                                    const frange &op2,
    1877              :                                    relation_trio) const
    1878              : {
    1879        18994 :   switch (get_bool_state (r, lhs, type))
    1880              :     {
    1881         6652 :     case BRS_TRUE:
    1882        13228 :       if (op2.maybe_isnan ())
    1883           76 :         r.set_varying (type);
    1884         6576 :       else if (op2.undefined_p ())
    1885              :         return false;
    1886              :       else
    1887         6576 :         build_gt (r, type, op2);
    1888              :       break;
    1889              : 
    1890        11742 :     case BRS_FALSE:
    1891              :       // A false UNORDERED_GT means both operands are !NAN, so it's
    1892              :       // impossible for op2 to be a NAN.
    1893        11742 :       if (op2.known_isnan ())
    1894            0 :         r.set_undefined ();
    1895        11742 :       else if (op2.undefined_p ())
    1896              :         return false;
    1897        11742 :       else if (build_le (r, type, op2))
    1898        11742 :         r.clear_nan ();
    1899              :       break;
    1900              : 
    1901              :     default:
    1902              :       break;
    1903              :     }
    1904              :   return true;
    1905              : }
    1906              : 
    1907              : bool
    1908          676 : foperator_unordered_gt::op2_range (frange &r,
    1909              :                                    tree type,
    1910              :                                    const irange &lhs,
    1911              :                                    const frange &op1,
    1912              :                                    relation_trio) const
    1913              : {
    1914          676 :   switch (get_bool_state (r, lhs, type))
    1915              :     {
    1916           76 :     case BRS_TRUE:
    1917           76 :       if (op1.maybe_isnan ())
    1918           76 :         r.set_varying (type);
    1919            0 :       else if (op1.undefined_p ())
    1920              :         return false;
    1921              :       else
    1922            0 :         build_lt (r, type, op1);
    1923              :       break;
    1924              : 
    1925            0 :     case BRS_FALSE:
    1926              :       // A false UNORDERED_GT means both operands are !NAN, so it's
    1927              :       // impossible for op1 to be a NAN.
    1928            0 :       if (op1.known_isnan ())
    1929            0 :         r.set_undefined ();
    1930            0 :       else if (op1.undefined_p ())
    1931              :         return false;
    1932            0 :       else if (build_ge (r, type, op1))
    1933            0 :         r.clear_nan ();
    1934              :       break;
    1935              : 
    1936              :     default:
    1937              :       break;
    1938              :     }
    1939              :   return true;
    1940              : }
    1941              : 
    1942              : class foperator_unordered_ge : public range_operator
    1943              : {
    1944              :   using range_operator::fold_range;
    1945              :   using range_operator::op1_range;
    1946              :   using range_operator::op2_range;
    1947              : public:
    1948       173527 :   bool fold_range (irange &r, tree type,
    1949              :                    const frange &op1, const frange &op2,
    1950              :                    relation_trio trio = TRIO_VARYING) const final override
    1951              :   {
    1952       173527 :     if (op1.known_isnan () || op2.known_isnan ())
    1953              :       {
    1954           49 :         r = range_true (type);
    1955           49 :         return true;
    1956              :       }
    1957       173478 :     frange op1_no_nan = op1;
    1958       173478 :     frange op2_no_nan = op2;
    1959       186990 :     if (op1.maybe_isnan ())
    1960       159905 :       op1_no_nan.clear_nan ();
    1961       339849 :     if (op2.maybe_isnan ())
    1962         7101 :       op2_no_nan.clear_nan ();
    1963       173478 :     if (!range_op_handler (GE_EXPR).fold_range (r, type, op1_no_nan,
    1964              :                                                 op2_no_nan, trio))
    1965              :       return false;
    1966              :     // The result is the same as the ordered version when the
    1967              :     // comparison is true or when the operands cannot be NANs.
    1968       173478 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    1969              :       return true;
    1970              :     else
    1971              :       {
    1972       160027 :         r = range_true_and_false (type);
    1973       160027 :         return true;
    1974              :       }
    1975       173478 :   }
    1976              :   bool op1_range (frange &r, tree type,
    1977              :                   const irange &lhs, const frange &op2,
    1978              :                   relation_trio = TRIO_VARYING) const final override;
    1979              :   bool op2_range (frange &r, tree type,
    1980              :                   const irange &lhs, const frange &op1,
    1981              :                   relation_trio = TRIO_VARYING) const final override;
    1982              : } fop_unordered_ge;
    1983              : 
    1984              : bool
    1985       144669 : foperator_unordered_ge::op1_range (frange &r,
    1986              :                                    tree type,
    1987              :                                    const irange &lhs,
    1988              :                                    const frange &op2,
    1989              :                                    relation_trio) const
    1990              : {
    1991       144669 :   switch (get_bool_state (r, lhs, type))
    1992              :     {
    1993        61425 :     case BRS_TRUE:
    1994       118205 :       if (op2.maybe_isnan ())
    1995         4645 :         r.set_varying (type);
    1996        56780 :       else if (op2.undefined_p ())
    1997              :         return false;
    1998              :       else
    1999        56780 :         build_ge (r, type, op2);
    2000              :       break;
    2001              : 
    2002        82538 :     case BRS_FALSE:
    2003              :       // A false UNORDERED_GE means both operands are !NAN, so it's
    2004              :       // impossible for op2 to be a NAN.
    2005        82538 :       if (op2.known_isnan ())
    2006            0 :         r.set_undefined ();
    2007        82538 :       else if (op2.undefined_p ())
    2008              :         return false;
    2009        82538 :       else if (build_lt (r, type, op2))
    2010        82534 :         r.clear_nan ();
    2011              :       break;
    2012              : 
    2013              :     default:
    2014              :       break;
    2015              :     }
    2016              :   return true;
    2017              : }
    2018              : 
    2019              : bool
    2020        14835 : foperator_unordered_ge::op2_range (frange &r, tree type,
    2021              :                                    const irange &lhs,
    2022              :                                    const frange &op1,
    2023              :                                    relation_trio) const
    2024              : {
    2025        14835 :   switch (get_bool_state (r, lhs, type))
    2026              :     {
    2027         8861 :     case BRS_TRUE:
    2028        13235 :       if (op1.maybe_isnan ())
    2029         4487 :         r.set_varying (type);
    2030         4374 :       else if (op1.undefined_p ())
    2031              :         return false;
    2032              :       else
    2033         4374 :         build_le (r, type, op1);
    2034              :       break;
    2035              : 
    2036         5388 :     case BRS_FALSE:
    2037              :       // A false UNORDERED_GE means both operands are !NAN, so it's
    2038              :       // impossible for op1 to be a NAN.
    2039         5388 :       if (op1.known_isnan ())
    2040            0 :         r.set_undefined ();
    2041         5388 :       else if (op1.undefined_p ())
    2042              :         return false;
    2043         5388 :       else if (build_gt (r, type, op1))
    2044         5388 :         r.clear_nan ();
    2045              :       break;
    2046              : 
    2047              :     default:
    2048              :       break;
    2049              :     }
    2050              :   return true;
    2051              : }
    2052              : 
    2053              : class foperator_unordered_equal : public range_operator
    2054              : {
    2055              :   using range_operator::fold_range;
    2056              :   using range_operator::op1_range;
    2057              :   using range_operator::op2_range;
    2058              : public:
    2059         3633 :   bool fold_range (irange &r, tree type,
    2060              :                    const frange &op1, const frange &op2,
    2061              :                    relation_trio trio = TRIO_VARYING) const final override
    2062              :   {
    2063         3633 :     if (op1.known_isnan () || op2.known_isnan ())
    2064              :       {
    2065            0 :         r = range_true (type);
    2066            0 :         return true;
    2067              :       }
    2068         3633 :     frange op1_no_nan = op1;
    2069         3633 :     frange op2_no_nan = op2;
    2070         3953 :     if (op1.maybe_isnan ())
    2071         3313 :       op1_no_nan.clear_nan ();
    2072         4054 :     if (op2.maybe_isnan ())
    2073         3212 :       op2_no_nan.clear_nan ();
    2074         3633 :     if (!range_op_handler (EQ_EXPR).fold_range (r, type, op1_no_nan,
    2075              :                                                 op2_no_nan, trio))
    2076              :       return false;
    2077              :     // The result is the same as the ordered version when the
    2078              :     // comparison is true or when the operands cannot be NANs.
    2079         3633 :     if (!maybe_isnan (op1, op2) || r == range_true (type))
    2080              :       return true;
    2081              :     else
    2082              :       {
    2083         3312 :         r = range_true_and_false (type);
    2084         3312 :         return true;
    2085              :       }
    2086         3633 :   }
    2087              :   bool op1_range (frange &r, tree type,
    2088              :                   const irange &lhs, const frange &op2,
    2089              :                   relation_trio = TRIO_VARYING) const final override;
    2090          632 :   bool op2_range (frange &r, tree type,
    2091              :                   const irange &lhs, const frange &op1,
    2092              :                   relation_trio rel = TRIO_VARYING) const final override
    2093              :   {
    2094          632 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    2095              :   }
    2096              : } fop_unordered_equal;
    2097              : 
    2098              : bool
    2099         1267 : foperator_unordered_equal::op1_range (frange &r, tree type,
    2100              :                                       const irange &lhs,
    2101              :                                       const frange &op2,
    2102              :                                       relation_trio) const
    2103              : {
    2104         1267 :   switch (get_bool_state (r, lhs, type))
    2105              :     {
    2106            3 :     case BRS_TRUE:
    2107              :       // If it's true, the result is the same as OP2 plus a NAN.
    2108            3 :       r = op2;
    2109              :       // Add both zeros if there's the possibility of zero equality.
    2110            3 :       frange_add_zeros (r, type);
    2111              :       // Add the possibility of a NAN.
    2112            3 :       r.update_nan ();
    2113            3 :       break;
    2114              : 
    2115            0 :     case BRS_FALSE:
    2116              :       // A false UNORDERED_EQ means both operands are !NAN, so it's
    2117              :       // impossible for op2 to be a NAN.
    2118            0 :       if (op2.known_isnan ())
    2119            0 :         r.set_undefined ();
    2120              :       else
    2121              :         {
    2122              :           // The false side indicates !NAN and not equal.  We can at least
    2123              :           // represent !NAN.
    2124            0 :           r.set_varying (type);
    2125            0 :           r.clear_nan ();
    2126              :         }
    2127              :       break;
    2128              : 
    2129              :     default:
    2130              :       break;
    2131              :     }
    2132         1267 :   return true;
    2133              : }
    2134              : 
    2135              : class foperator_ltgt : public range_operator
    2136              : {
    2137              :   using range_operator::fold_range;
    2138              :   using range_operator::op1_range;
    2139              :   using range_operator::op2_range;
    2140              : public:
    2141         2143 :   bool fold_range (irange &r, tree type,
    2142              :                    const frange &op1, const frange &op2,
    2143              :                    relation_trio trio = TRIO_VARYING) const final override
    2144              :   {
    2145         2143 :     if (op1.known_isnan () || op2.known_isnan ())
    2146              :       {
    2147            2 :         r = range_false (type);
    2148            2 :         return true;
    2149              :       }
    2150         2141 :     frange op1_no_nan = op1;
    2151         2141 :     frange op2_no_nan = op2;
    2152         2461 :     if (op1.maybe_isnan ())
    2153         1805 :       op1_no_nan.clear_nan ();
    2154         2461 :     if (op2.maybe_isnan ())
    2155         1805 :       op2_no_nan.clear_nan ();
    2156         2141 :     if (!range_op_handler (NE_EXPR).fold_range (r, type, op1_no_nan,
    2157              :                                                 op2_no_nan, trio))
    2158              :       return false;
    2159              :     // The result is the same as the ordered version when the
    2160              :     // comparison is true or when the operands cannot be NANs.
    2161         2141 :     if (!maybe_isnan (op1, op2) || r == range_false (type))
    2162              :       return true;
    2163              :     else
    2164              :       {
    2165         1805 :         r = range_true_and_false (type);
    2166         1805 :         return true;
    2167              :       }
    2168         2141 :   }
    2169              :   bool op1_range (frange &r, tree type,
    2170              :                   const irange &lhs, const frange &op2,
    2171              :                   relation_trio = TRIO_VARYING) const final override;
    2172          794 :   bool op2_range (frange &r, tree type,
    2173              :                   const irange &lhs, const frange &op1,
    2174              :                   relation_trio rel = TRIO_VARYING) const final override
    2175              :   {
    2176          794 :     return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
    2177              :   }
    2178              : } fop_ltgt;
    2179              : 
    2180              : bool
    2181         1578 : foperator_ltgt::op1_range (frange &r, tree type,
    2182              :                            const irange &lhs,
    2183              :                            const frange &op2,
    2184              :                            relation_trio) const
    2185              : {
    2186         1578 :   switch (get_bool_state (r, lhs, type))
    2187              :     {
    2188            0 :     case BRS_TRUE:
    2189              :       // A true LTGT means both operands are !NAN, so it's
    2190              :       // impossible for op2 to be a NAN.
    2191            0 :       if (op2.known_isnan ())
    2192            0 :         r.set_undefined ();
    2193              :       else
    2194              :         {
    2195              :           // The true side indicates !NAN and not equal.  We can at least
    2196              :           // represent !NAN.
    2197            0 :           r.set_varying (type);
    2198            0 :           r.clear_nan ();
    2199              :         }
    2200              :       break;
    2201              : 
    2202           10 :     case BRS_FALSE:
    2203              :       // If it's false, the result is the same as OP2 plus a NAN.
    2204           10 :       r = op2;
    2205              :       // Add both zeros if there's the possibility of zero equality.
    2206           10 :       frange_add_zeros (r, type);
    2207              :       // Add the possibility of a NAN.
    2208           10 :       r.update_nan ();
    2209           10 :       break;
    2210              : 
    2211              :     default:
    2212              :       break;
    2213              :     }
    2214         1578 :   return true;
    2215              : }
    2216              : 
    2217              : // Final tweaks for float binary op op1_range/op2_range.
    2218              : // Return TRUE if the operation is performed and a valid range is available.
    2219              : 
    2220              : static bool
    2221       933635 : float_binary_op_range_finish (bool ret, frange &r, tree type,
    2222              :                               const frange &lhs, bool div_op2 = false)
    2223              : {
    2224       933635 :   if (!ret)
    2225              :     return false;
    2226              : 
    2227              :   // If we get a known NAN from reverse op, it means either that
    2228              :   // the other operand was known NAN (in that case we know nothing),
    2229              :   // or the reverse operation introduced a known NAN.
    2230              :   // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
    2231              :   // 0 / 0 is known NAN.  Just punt in that case.
    2232              :   // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
    2233              :   // Or if lhs is a known NAN, we also don't know anything.
    2234       933635 :   if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
    2235              :     {
    2236         7033 :       r.set_varying (type);
    2237         7033 :       return true;
    2238              :     }
    2239              : 
    2240              :   // If lhs isn't NAN, then neither operand could be NAN,
    2241              :   // even if the reverse operation does introduce a maybe_nan.
    2242      1690546 :   if (!lhs.maybe_isnan ())
    2243              :     {
    2244       763944 :       r.clear_nan ();
    2245       763944 :       if (div_op2
    2246       788237 :           ? !(real_compare (LE_EXPR, &lhs.lower_bound (), &dconst0)
    2247        24293 :               && real_compare (GE_EXPR, &lhs.upper_bound (), &dconst0))
    2248      1340433 :           : !(real_isinf (&lhs.lower_bound ())
    2249       608158 :               || real_isinf (&lhs.upper_bound ())))
    2250              :         // For reverse + or - or * or op1 of /, if result is finite, then
    2251              :         // r must be finite too, as X + INF or X - INF or X * INF or
    2252              :         // INF / X is always +-INF or NAN.  For op2 of /, if result is
    2253              :         // non-zero and not NAN, r must be finite, as X / INF is always
    2254              :         // 0 or NAN.
    2255       588222 :         frange_drop_infs (r, type);
    2256              :     }
    2257              :   // If lhs is a maybe or known NAN, the operand could be
    2258              :   // NAN.
    2259              :   else
    2260       162658 :     r.update_nan ();
    2261              :   return true;
    2262              : }
    2263              : 
    2264              : // True if [lb, ub] is [+-0, +-0].
    2265              : static bool
    2266      5218532 : zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2267              : {
    2268      5218532 :   return real_iszero (&lb) && real_iszero (&ub);
    2269              : }
    2270              : 
    2271              : // True if +0 or -0 is in [lb, ub] range.
    2272              : static bool
    2273      4353159 : contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2274              : {
    2275      4353159 :   return (real_compare (LE_EXPR, &lb, &dconst0)
    2276      4353159 :           && real_compare (GE_EXPR, &ub, &dconst0));
    2277              : }
    2278              : 
    2279              : // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
    2280              : static bool
    2281      2955299 : singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
    2282              : {
    2283      2955299 :   return real_isinf (&lb) && real_isinf (&ub, real_isneg (&lb));
    2284              : }
    2285              : 
    2286              : // Return -1 if binary op result must have sign bit set,
    2287              : // 1 if binary op result must have sign bit clear,
    2288              : // 0 otherwise.
    2289              : // Sign bit of binary op result is exclusive or of the
    2290              : // operand's sign bits.
    2291              : static int
    2292      1314844 : signbit_known_p (const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
    2293              :                  const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub)
    2294              : {
    2295      1314844 :   if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
    2296      1314844 :       && real_isneg (&rh_lb) == real_isneg (&rh_ub))
    2297              :     {
    2298       111983 :       if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
    2299              :         return 1;
    2300              :       else
    2301         6552 :         return -1;
    2302              :     }
    2303              :   return 0;
    2304              : }
    2305              : 
    2306              : // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
    2307              : // signbit_known.
    2308              : static void
    2309         6180 : zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2310              : {
    2311         6180 :   ub = lb = dconst0;
    2312         6180 :   if (signbit_known <= 0)
    2313         6110 :     lb = dconstm0;
    2314         6110 :   if (signbit_known < 0)
    2315           42 :     ub = lb;
    2316         6180 : }
    2317              : 
    2318              : // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
    2319              : // signbit_known.
    2320              : static void
    2321         4319 : inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2322              : {
    2323         4319 :   if (signbit_known > 0)
    2324          950 :     ub = lb = dconstinf;
    2325         3369 :   else if (signbit_known < 0)
    2326           96 :     ub = lb = dconstninf;
    2327              :   else
    2328              :     {
    2329         3273 :       lb = dconstninf;
    2330         3273 :       ub = dconstinf;
    2331              :     }
    2332         4319 : }
    2333              : 
    2334              : // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
    2335              : // signbit_known.
    2336              : static void
    2337       928080 : zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
    2338              : {
    2339       928080 :   if (signbit_known > 0)
    2340              :     {
    2341        10259 :       lb = dconst0;
    2342        10259 :       ub = dconstinf;
    2343              :     }
    2344       917821 :   else if (signbit_known < 0)
    2345              :     {
    2346          222 :       lb = dconstninf;
    2347          222 :       ub = dconstm0;
    2348              :     }
    2349              :   else
    2350              :     {
    2351       917599 :       lb = dconstninf;
    2352       917599 :       ub = dconstinf;
    2353              :     }
    2354       928080 : }
    2355              : 
    2356              : /* Extend the LHS range by 1ulp in each direction.  For op1_range
    2357              :    or op2_range of binary operations just computing the inverse
    2358              :    operation on ranges isn't sufficient.  Consider e.g.
    2359              :    [1., 1.] = op1 + [1., 1.].  op1's range is not [0., 0.], but
    2360              :    [-0x1.0p-54, 0x1.0p-53] (when not -frounding-math), any value for
    2361              :    which adding 1. to it results in 1. after rounding to nearest.
    2362              :    So, for op1_range/op2_range extend the lhs range by 1ulp (or 0.5ulp)
    2363              :    in each direction.  See PR109008 for more details.  */
    2364              : 
    2365              : static frange
    2366       905672 : float_widen_lhs_range (tree type, const frange &lhs)
    2367              : {
    2368       905672 :   frange ret = lhs;
    2369       905672 :   if (lhs.known_isnan ())
    2370              :     return ret;
    2371       898640 :   REAL_VALUE_TYPE lb = lhs.lower_bound ();
    2372       898640 :   REAL_VALUE_TYPE ub = lhs.upper_bound ();
    2373       898640 :   if (real_isfinite (&lb))
    2374              :     {
    2375       714948 :       frange_nextafter (TYPE_MODE (type), lb, dconstninf);
    2376       714948 :       if (real_isinf (&lb))
    2377              :         {
    2378              :           /* For -DBL_MAX, instead of -Inf use
    2379              :              nexttoward (-DBL_MAX, -LDBL_MAX) in a hypothetical
    2380              :              wider type with the same mantissa precision but larger
    2381              :              exponent range; it is outside of range of double values,
    2382              :              but makes it clear it is just one ulp larger rather than
    2383              :              infinite amount larger.  */
    2384        55357 :           lb = dconstm1;
    2385       221428 :           SET_REAL_EXP (&lb, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
    2386              :         }
    2387      5004636 :       if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
    2388              :         {
    2389              :           /* If not -frounding-math nor IBM double double, actually widen
    2390              :              just by 0.5ulp rather than 1ulp.  */
    2391       714948 :           REAL_VALUE_TYPE tem;
    2392       714948 :           real_arithmetic (&tem, PLUS_EXPR, &lhs.lower_bound (), &lb);
    2393       714948 :           real_arithmetic (&lb, RDIV_EXPR, &tem, &dconst2);
    2394              :         }
    2395              :     }
    2396       898640 :   if (real_isfinite (&ub))
    2397              :     {
    2398       646116 :       frange_nextafter (TYPE_MODE (type), ub, dconstinf);
    2399       646116 :       if (real_isinf (&ub))
    2400              :         {
    2401              :           /* For DBL_MAX similarly.  */
    2402        56042 :           ub = dconst1;
    2403       224168 :           SET_REAL_EXP (&ub, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
    2404              :         }
    2405      4522812 :       if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
    2406              :         {
    2407              :           /* If not -frounding-math nor IBM double double, actually widen
    2408              :              just by 0.5ulp rather than 1ulp.  */
    2409       646116 :           REAL_VALUE_TYPE tem;
    2410       646116 :           real_arithmetic (&tem, PLUS_EXPR, &lhs.upper_bound (), &ub);
    2411       646116 :           real_arithmetic (&ub, RDIV_EXPR, &tem, &dconst2);
    2412              :         }
    2413              :     }
    2414              :   /* Temporarily disable -ffinite-math-only, so that frange::set doesn't
    2415              :      reduce the range back to real_min_representable (type) as lower bound
    2416              :      or real_max_representable (type) as upper bound.  */
    2417       898640 :   bool save_flag_finite_math_only = flag_finite_math_only;
    2418       898640 :   flag_finite_math_only = false;
    2419       898640 :   ret.set (type, lb, ub, lhs.get_nan_state ());
    2420       898640 :   flag_finite_math_only = save_flag_finite_math_only;
    2421       898640 :   return ret;
    2422              : }
    2423              : 
    2424              : bool
    2425       166175 : operator_plus::op1_range (frange &r, tree type, const frange &lhs,
    2426              :                           const frange &op2, relation_trio) const
    2427              : {
    2428       166175 :   if (lhs.undefined_p ())
    2429              :     return false;
    2430       166175 :   range_op_handler minus (MINUS_EXPR);
    2431       166175 :   if (!minus)
    2432              :     return false;
    2433       166175 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2434       166175 :   return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
    2435              :                                        r, type, wlhs);
    2436       166175 : }
    2437              : 
    2438              : bool
    2439        71515 : operator_plus::op2_range (frange &r, tree type,
    2440              :                           const frange &lhs, const frange &op1,
    2441              :                           relation_trio) const
    2442              : {
    2443        71515 :   return op1_range (r, type, lhs, op1);
    2444              : }
    2445              : 
    2446              : void
    2447      2456934 : operator_plus::rv_fold (frange &r, tree type,
    2448              :                         const REAL_VALUE_TYPE &lh_lb,
    2449              :                         const REAL_VALUE_TYPE &lh_ub,
    2450              :                         const REAL_VALUE_TYPE &rh_lb,
    2451              :                         const REAL_VALUE_TYPE &rh_ub,
    2452              :                         relation_kind) const
    2453              : {
    2454      2456934 :   REAL_VALUE_TYPE lb, ub;
    2455      2456934 :   bool maybe_nan = false;
    2456              : 
    2457      2456934 :   frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
    2458      2456934 :   frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
    2459              : 
    2460              :   // [-INF] + [+INF] = NAN
    2461      2456934 :   if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
    2462              :     maybe_nan = true;
    2463              :   // [+INF] + [-INF] = NAN
    2464       798278 :   else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
    2465              :     maybe_nan = true;
    2466              : 
    2467              :   // Handle possible NANs by saturating to the appropriate INF if only
    2468              :   // one end is a NAN.  If both ends are a NAN, just return a NAN.
    2469      2456934 :   bool lb_nan = real_isnan (&lb);
    2470      2456934 :   bool ub_nan = real_isnan (&ub);
    2471      2456934 :   if (lb_nan && ub_nan)
    2472              :     {
    2473            0 :       r.set_nan (type);
    2474            0 :       return;
    2475              :     }
    2476      2456934 :   if (lb_nan)
    2477          374 :     lb = dconstninf;
    2478      2456560 :   else if (ub_nan)
    2479            0 :     ub = dconstinf;
    2480      2456934 :   r.set (type, lb, ub, nan_state (maybe_nan));
    2481              : }
    2482              : 
    2483              : 
    2484              : bool
    2485        91979 : operator_minus::op1_range (frange &r, tree type,
    2486              :                            const frange &lhs, const frange &op2,
    2487              :                            relation_trio) const
    2488              : {
    2489        91979 :   if (lhs.undefined_p ())
    2490              :     return false;
    2491        91979 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2492        91979 :   return float_binary_op_range_finish (
    2493       183958 :               range_op_handler (PLUS_EXPR).fold_range (r, type, wlhs, op2),
    2494              :               r, type, wlhs);
    2495        91979 : }
    2496              : 
    2497              : bool
    2498       178153 : operator_minus::op2_range (frange &r, tree type,
    2499              :                            const frange &lhs, const frange &op1,
    2500              :                            relation_trio) const
    2501              : {
    2502       178153 :   if (lhs.undefined_p ())
    2503              :     return false;
    2504       178153 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2505       178153 :   return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
    2506              :                                        r, type, wlhs);
    2507       178153 : }
    2508              : 
    2509              : void
    2510       978981 : operator_minus::rv_fold (frange &r, tree type,
    2511              :                          const REAL_VALUE_TYPE &lh_lb,
    2512              :                          const REAL_VALUE_TYPE &lh_ub,
    2513              :                          const REAL_VALUE_TYPE &rh_lb,
    2514              :                          const REAL_VALUE_TYPE &rh_ub,
    2515              :                          relation_kind) const
    2516              : {
    2517       978981 :   REAL_VALUE_TYPE lb, ub;
    2518       978981 :   bool maybe_nan = false;
    2519              : 
    2520       978981 :   frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
    2521       978981 :   frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
    2522              : 
    2523              :   // [+INF] - [+INF] = NAN
    2524       978981 :   if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
    2525              :     maybe_nan = true;
    2526              :   // [-INF] - [-INF] = NAN
    2527       694965 :   else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
    2528              :     maybe_nan = true;
    2529              : 
    2530              :   // Handle possible NANs by saturating to the appropriate INF if only
    2531              :   // one end is a NAN.  If both ends are a NAN, just return a NAN.
    2532       978981 :   bool lb_nan = real_isnan (&lb);
    2533       978981 :   bool ub_nan = real_isnan (&ub);
    2534       978981 :   if (lb_nan && ub_nan)
    2535              :     {
    2536            0 :       r.set_nan (type);
    2537            0 :       return;
    2538              :     }
    2539       978981 :   if (lb_nan)
    2540          182 :     lb = dconstninf;
    2541       978799 :   else if (ub_nan)
    2542          310 :     ub = dconstinf;
    2543       978981 :   r.set (type, lb, ub, nan_state (maybe_nan));
    2544              : }
    2545              : 
    2546              : 
    2547              : // Given CP[0] to CP[3] floating point values rounded to -INF,
    2548              : // set LB to the smallest of them (treating -0 as smaller to +0).
    2549              : // Given CP[4] to CP[7] floating point values rounded to +INF,
    2550              : // set UB to the largest of them (treating -0 as smaller to +0).
    2551              : 
    2552              : static void
    2553      1131407 : find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
    2554              :             const REAL_VALUE_TYPE (&cp)[8])
    2555              : {
    2556      1131407 :   lb = cp[0];
    2557      1131407 :   ub = cp[4];
    2558      4525628 :   for (int i = 1; i < 4; ++i)
    2559              :     {
    2560      3394221 :       if (real_less (&cp[i], &lb)
    2561      3394221 :           || (real_iszero (&lb) && real_isnegzero (&cp[i])))
    2562       357499 :         lb = cp[i];
    2563      3394221 :       if (real_less (&ub, &cp[i + 4])
    2564      3394221 :           || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
    2565      1107261 :         ub = cp[i + 4];
    2566              :     }
    2567      1131407 : }
    2568              : 
    2569              : 
    2570              : bool
    2571       369824 : operator_mult::op1_range (frange &r, tree type,
    2572              :                           const frange &lhs, const frange &op2,
    2573              :                           relation_trio) const
    2574              : {
    2575       369824 :   if (lhs.undefined_p ())
    2576              :     return false;
    2577       369824 :   range_op_handler rdiv (RDIV_EXPR);
    2578       369824 :   if (!rdiv)
    2579              :     return false;
    2580       369824 :   frange wlhs = float_widen_lhs_range (type, lhs);
    2581       369824 :   bool ret = rdiv.fold_range (r, type, wlhs, op2);
    2582       369824 :   if (ret == false)
    2583              :     return false;
    2584       369824 :   if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
    2585           16 :     return float_binary_op_range_finish (ret, r, type, wlhs);
    2586       369808 :   const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2587       369808 :   const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2588       369808 :   const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
    2589       369808 :   const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
    2590       691261 :   if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
    2591       556135 :       || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
    2592        40543 :           && (real_isinf (&op2_lb) || real_isinf (&op2_ub))))
    2593              :     {
    2594              :       // If both lhs and op2 could be zeros or both could be infinities,
    2595              :       // we don't know anything about op1 except maybe for the sign
    2596              :       // and perhaps if it can be NAN or not.
    2597       142387 :       REAL_VALUE_TYPE lb, ub;
    2598       142387 :       int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
    2599       142387 :       zero_to_inf_range (lb, ub, signbit_known);
    2600       142387 :       r.set (type, lb, ub);
    2601              :     }
    2602              :   // Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
    2603              :   // or if lhs must be zero and op2 doesn't include zero, it would be
    2604              :   // UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
    2605              :   // range.  Those are supersets of UNDEFINED, so let's keep that way.
    2606       369808 :   return float_binary_op_range_finish (ret, r, type, wlhs);
    2607       369824 : }
    2608              : 
    2609              : bool
    2610        79626 : operator_mult::op2_range (frange &r, tree type,
    2611              :                           const frange &lhs, const frange &op1,
    2612              :                           relation_trio) const
    2613              : {
    2614        79626 :   return op1_range (r, type, lhs, op1);
    2615              : }
    2616              : 
    2617              : void
    2618      1172978 : operator_mult::rv_fold (frange &r, tree type,
    2619              :                         const REAL_VALUE_TYPE &lh_lb,
    2620              :                         const REAL_VALUE_TYPE &lh_ub,
    2621              :                         const REAL_VALUE_TYPE &rh_lb,
    2622              :                         const REAL_VALUE_TYPE &rh_ub,
    2623              :                         relation_kind kind) const
    2624              : {
    2625      1172978 :   bool is_square
    2626              :     = (kind == VREL_EQ
    2627        37072 :        && real_equal (&lh_lb, &rh_lb)
    2628        37072 :        && real_equal (&lh_ub, &rh_ub)
    2629        37072 :        && real_isneg (&lh_lb) == real_isneg (&rh_lb)
    2630      1210050 :        && real_isneg (&lh_ub) == real_isneg (&rh_ub));
    2631      1135906 :   REAL_VALUE_TYPE lb, ub;
    2632      1891048 :   bool maybe_nan = false;
    2633              :   // x * x never produces a new NAN and we only multiply the same
    2634              :   // values, so the 0 * INF problematic cases never appear there.
    2635      1135906 :   if (!is_square)
    2636              :     {
    2637              :       // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
    2638      1141290 :       if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
    2639      1141284 :           || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
    2640              :         {
    2641           37 :           r.set_nan (type);
    2642       417836 :           return;
    2643              :         }
    2644              : 
    2645              :       // Otherwise, if one range includes zero and the other ends with +-INF,
    2646              :       // it is a maybe NAN.
    2647      1135869 :       if ((contains_zero_p (lh_lb, lh_ub)
    2648      1031955 :            && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
    2649      1777908 :           || (contains_zero_p (rh_lb, rh_ub)
    2650       202246 :               && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
    2651              :         {
    2652       417799 :           maybe_nan = true;
    2653              : 
    2654       417799 :           int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
    2655              : 
    2656              :           // If one of the ranges that includes INF is singleton
    2657              :           // and the other range includes zero, the resulting
    2658              :           // range is INF and NAN, because the 0 * INF boundary
    2659              :           // case will be NAN, but already nextafter (0, 1) * INF
    2660              :           // is INF.
    2661       417799 :           if (singleton_inf_p (lh_lb, lh_ub)
    2662       417799 :               || singleton_inf_p (rh_lb, rh_ub))
    2663              :             {
    2664          988 :               inf_range (lb, ub, signbit_known);
    2665          988 :               r.set (type, lb, ub, nan_state (true));
    2666          988 :               return;
    2667              :             }
    2668              : 
    2669              :           // If one of the multiplicands must be zero, the resulting
    2670              :           // range is +-0 and NAN.
    2671       416811 :           if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
    2672              :             {
    2673         5650 :               zero_range (lb, ub, signbit_known);
    2674         5650 :               r.set (type, lb, ub, nan_state (true));
    2675         5650 :               return;
    2676              :             }
    2677              : 
    2678              :           // Otherwise one of the multiplicands could be
    2679              :           // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
    2680              :           // or similarly with different signs.  0.0 * DBL_MAX
    2681              :           // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
    2682              :           // so if the signs are always the same or always different,
    2683              :           // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
    2684       411161 :           zero_to_inf_range (lb, ub, signbit_known);
    2685       411161 :           r.set (type, lb, ub, nan_state (true));
    2686       411161 :           return;
    2687              :         }
    2688              :     }
    2689              : 
    2690       755142 :   REAL_VALUE_TYPE cp[8];
    2691              :   // Do a cross-product.  At this point none of the multiplications
    2692              :   // should produce a NAN.
    2693       755142 :   frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
    2694       755142 :   frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
    2695       755142 :   if (is_square)
    2696              :     {
    2697              :       // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
    2698              :       // as maximum and -0.0 as minimum if 0.0 is in the range,
    2699              :       // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
    2700              :       // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
    2701              :       // x and y are bitwise equal, just that they compare equal.
    2702        37072 :       if (contains_zero_p (lh_lb, lh_ub))
    2703              :         {
    2704        34040 :           if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
    2705         1135 :             cp[1] = dconst0;
    2706              :           else
    2707        32905 :             cp[1] = dconstm0;
    2708              :         }
    2709              :       else
    2710         3032 :         cp[1] = cp[0];
    2711        37072 :       cp[2] = cp[0];
    2712        37072 :       cp[5] = cp[4];
    2713        37072 :       cp[6] = cp[4];
    2714              :     }
    2715              :   else
    2716              :     {
    2717       718070 :       frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
    2718       718070 :       frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
    2719       718070 :       frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
    2720       718070 :       frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
    2721              :     }
    2722       755142 :   frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
    2723       755142 :   frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
    2724              : 
    2725       755142 :   find_range (lb, ub, cp);
    2726              : 
    2727       755142 :   gcc_checking_assert (!real_isnan (&lb));
    2728       755142 :   gcc_checking_assert (!real_isnan (&ub));
    2729       755142 :   r.set (type, lb, ub, nan_state (maybe_nan));
    2730              : }
    2731              : 
    2732              : 
    2733              : class foperator_div : public range_operator
    2734              : {
    2735              :   using range_operator::op1_range;
    2736              :   using range_operator::op2_range;
    2737              : public:
    2738        24673 :   virtual bool op1_range (frange &r, tree type,
    2739              :                           const frange &lhs,
    2740              :                           const frange &op2,
    2741              :                           relation_trio = TRIO_VARYING) const final override
    2742              :   {
    2743        24673 :     if (lhs.undefined_p ())
    2744              :       return false;
    2745        24673 :     frange wlhs = float_widen_lhs_range (type, lhs);
    2746        24673 :     bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
    2747        24673 :     if (!ret)
    2748              :       return ret;
    2749        24673 :     if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
    2750            4 :       return float_binary_op_range_finish (ret, r, type, wlhs);
    2751        24669 :     const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2752        24669 :     const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2753        24669 :     const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
    2754        24669 :     const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
    2755        24669 :     if ((contains_zero_p (lhs_lb, lhs_ub)
    2756        17231 :          && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
    2757        31096 :         || ((contains_zero_p (op2_lb, op2_ub))
    2758         8188 :             && (real_isinf (&lhs_lb) || real_isinf (&lhs_ub))))
    2759              :       {
    2760              :         // If both lhs could be zero and op2 infinity or vice versa,
    2761              :         // we don't know anything about op1 except maybe for the sign
    2762              :         // and perhaps if it can be NAN or not.
    2763        18510 :         REAL_VALUE_TYPE lb, ub;
    2764        18510 :         int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
    2765        18510 :         zero_to_inf_range (lb, ub, signbit_known);
    2766        18510 :         r.set (type, lb, ub);
    2767              :       }
    2768        24669 :     return float_binary_op_range_finish (ret, r, type, wlhs);
    2769        24673 :   }
    2770        41111 :   virtual bool op2_range (frange &r, tree type,
    2771              :                           const frange &lhs,
    2772              :                           const frange &op1,
    2773              :                           relation_trio = TRIO_VARYING) const final override
    2774              :   {
    2775        41111 :     if (lhs.undefined_p ())
    2776              :       return false;
    2777        41111 :     frange wlhs = float_widen_lhs_range (type, lhs);
    2778        41111 :     bool ret = fold_range (r, type, op1, wlhs);
    2779        41111 :     if (!ret)
    2780              :       return ret;
    2781        41111 :     if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
    2782           20 :       return float_binary_op_range_finish (ret, r, type, wlhs, true);
    2783        41091 :     const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
    2784        41091 :     const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
    2785        41091 :     const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
    2786        41091 :     const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
    2787        72275 :     if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
    2788        44569 :         || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
    2789         7626 :             && (real_isinf (&op1_lb) || real_isinf (&op1_ub))))
    2790              :       {
    2791              :         // If both lhs and op1 could be zeros or both could be infinities,
    2792              :         // we don't know anything about op2 except maybe for the sign
    2793              :         // and perhaps if it can be NAN or not.
    2794        32018 :         REAL_VALUE_TYPE lb, ub;
    2795        32018 :         int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
    2796        32018 :         zero_to_inf_range (lb, ub, signbit_known);
    2797        32018 :         r.set (type, lb, ub);
    2798              :       }
    2799        41091 :     return float_binary_op_range_finish (ret, r, type, wlhs, true);
    2800        41111 :   }
    2801              : private:
    2802       704715 :   void rv_fold (frange &r, tree type,
    2803              :                 const REAL_VALUE_TYPE &lh_lb,
    2804              :                 const REAL_VALUE_TYPE &lh_ub,
    2805              :                 const REAL_VALUE_TYPE &rh_lb,
    2806              :                 const REAL_VALUE_TYPE &rh_ub,
    2807              :                 relation_kind) const final override
    2808              :   {
    2809              :     // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
    2810       705822 :     if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
    2811       705243 :         || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
    2812              :       {
    2813          585 :         r.set_nan (type);
    2814       328450 :         return;
    2815              :       }
    2816              : 
    2817       704130 :     REAL_VALUE_TYPE lb, ub;
    2818       704130 :     bool maybe_nan = false;
    2819              :     // If +-0.0 is in both ranges, it is a maybe NAN.
    2820       704130 :     if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
    2821              :       maybe_nan = true;
    2822              :     // If +-INF is in both ranges, it is a maybe NAN.
    2823       728780 :     else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
    2824       421972 :              && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
    2825              :       maybe_nan = true;
    2826              : 
    2827       704130 :     int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
    2828              : 
    2829              :     // If dividend must be zero, the range is just +-0
    2830              :     // (including if the divisor is +-INF).
    2831              :     // If divisor must be +-INF, the range is just +-0
    2832              :     // (including if the dividend is zero).
    2833       704130 :     if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
    2834              :       {
    2835          530 :         zero_range (lb, ub, signbit_known);
    2836          530 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2837          530 :         return;
    2838              :       }
    2839              : 
    2840              :     // If divisor must be zero, the range is just +-INF
    2841              :     // (including if the dividend is +-INF).
    2842              :     // If dividend must be +-INF, the range is just +-INF
    2843              :     // (including if the dividend is zero).
    2844       703600 :     if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
    2845              :       {
    2846         3331 :         inf_range (lb, ub, signbit_known);
    2847         3331 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2848         3331 :         return;
    2849              :       }
    2850              : 
    2851              :     // Otherwise if both operands may be zero, divisor could be
    2852              :     // nextafter(0.0, +-1.0) and dividend +-0.0
    2853              :     // in which case result is going to INF or vice versa and
    2854              :     // result +0.0.  So, all we can say for that case is if the
    2855              :     // signs of divisor and dividend are always the same we have
    2856              :     // [+0.0, +INF], if they are always different we have
    2857              :     // [-INF, -0.0].  If they vary, VARYING.
    2858              :     // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
    2859              :     // in which case result is going to INF or vice versa and
    2860              :     // result +0.0.  So, all we can say for that case is if the
    2861              :     // signs of divisor and dividend are always the same we have
    2862              :     // [+0.0, +INF], if they are always different we have
    2863              :     // [-INF, -0.0].  If they vary, VARYING.
    2864       700269 :     if (maybe_nan)
    2865              :       {
    2866       324004 :         zero_to_inf_range (lb, ub, signbit_known);
    2867       324004 :         r.set (type, lb, ub, nan_state (maybe_nan));
    2868       324004 :         return;
    2869              :       }
    2870              : 
    2871       376265 :     REAL_VALUE_TYPE cp[8];
    2872              :     // Do a cross-division.  At this point none of the divisions should
    2873              :     // produce a NAN.
    2874       376265 :     frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
    2875       376265 :     frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
    2876       376265 :     frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
    2877       376265 :     frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
    2878       376265 :     frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
    2879       376265 :     frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
    2880       376265 :     frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
    2881       376265 :     frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
    2882              : 
    2883       376265 :     find_range (lb, ub, cp);
    2884              : 
    2885              :     // If divisor may be zero (but is not known to be only zero),
    2886              :     // and dividend can't be zero, the range can go up to -INF or +INF
    2887              :     // depending on the signs.
    2888       376265 :     if (contains_zero_p (rh_lb, rh_ub))
    2889              :       {
    2890        50154 :         if (signbit_known <= 0)
    2891        47731 :           real_inf (&lb, true);
    2892        47731 :         if (signbit_known >= 0)
    2893        50118 :           real_inf (&ub, false);
    2894              :       }
    2895              : 
    2896       376265 :     gcc_checking_assert (!real_isnan (&lb));
    2897       376265 :     gcc_checking_assert (!real_isnan (&ub));
    2898       376265 :     r.set (type, lb, ub, nan_state (maybe_nan));
    2899              :   }
    2900              : } fop_div;
    2901              : 
    2902              : bool
    2903       945348 : operator_cast::fold_range (frange &r, tree type, const frange &op1,
    2904              :                            const frange &, relation_trio) const
    2905              : {
    2906       945348 :   REAL_VALUE_TYPE lb, ub;
    2907       945348 :   enum machine_mode mode = TYPE_MODE (type);
    2908      6617436 :   bool mode_composite = MODE_COMPOSITE_P (mode);
    2909              : 
    2910       945348 :   if (empty_range_varying (r, type, op1, op1))
    2911          819 :     return true;
    2912      3778116 :   if (!MODE_HAS_NANS (mode) && op1.maybe_isnan ())
    2913              :     {
    2914            0 :       r.set_varying (type);
    2915            0 :       return true;
    2916              :     }
    2917       944529 :   if (op1.known_isnan ())
    2918              :     {
    2919         3004 :       r.set_nan (type);
    2920         3004 :       return true;
    2921              :     }
    2922              : 
    2923       941525 :   const REAL_VALUE_TYPE &lh_lb = op1.lower_bound ();
    2924       941525 :   const REAL_VALUE_TYPE &lh_ub = op1.upper_bound ();
    2925       941525 :   real_convert (&lb, mode, &lh_lb);
    2926       941525 :   real_convert (&ub, mode, &lh_ub);
    2927              : 
    2928       941525 :   if (flag_rounding_math)
    2929              :     {
    2930        31161 :       if (real_less (&lh_lb, &lb))
    2931              :         {
    2932         2668 :           if (mode_composite
    2933         2668 :               && (real_isdenormal (&lb, mode) || real_iszero (&lb)))
    2934              :             {
    2935              :               // IBM extended denormals only have DFmode precision.
    2936            0 :               REAL_VALUE_TYPE tmp, tmp2;
    2937            0 :               real_convert (&tmp2, DFmode, &lh_lb);
    2938            0 :               real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
    2939              :                               &dconstninf);
    2940            0 :               real_convert (&lb, mode, &tmp);
    2941              :             }
    2942              :           else
    2943         2668 :             frange_nextafter (mode, lb, dconstninf);
    2944              :         }
    2945        31161 :       if (real_less (&ub, &lh_ub))
    2946              :         {
    2947         1070 :           if (mode_composite
    2948         1070 :               && (real_isdenormal (&ub, mode) || real_iszero (&ub)))
    2949              :             {
    2950              :               // IBM extended denormals only have DFmode precision.
    2951            0 :               REAL_VALUE_TYPE tmp, tmp2;
    2952            0 :               real_convert (&tmp2, DFmode, &lh_ub);
    2953            0 :               real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
    2954              :                               &dconstinf);
    2955            0 :               real_convert (&ub, mode, &tmp);
    2956              :             }
    2957              :           else
    2958         1070 :             frange_nextafter (mode, ub, dconstinf);
    2959              :         }
    2960              :     }
    2961              : 
    2962       941525 :   r.set (type, lb, ub, op1.get_nan_state ());
    2963              : 
    2964       941525 :   if (flag_trapping_math
    2965      4248080 :       && MODE_HAS_INFINITIES (TYPE_MODE (type))
    2966       826639 :       && r.known_isinf ()
    2967       941599 :       && !op1.known_isinf ())
    2968              :     {
    2969            1 :       REAL_VALUE_TYPE inf = r.lower_bound ();
    2970            1 :       if (real_isneg (&inf))
    2971              :         {
    2972            0 :           REAL_VALUE_TYPE min = real_min_representable (type);
    2973            0 :           r.set (type, inf, min);
    2974              :         }
    2975              :       else
    2976              :         {
    2977            1 :           REAL_VALUE_TYPE max = real_max_representable (type);
    2978            1 :           r.set (type, max, inf);
    2979              :         }
    2980              :     }
    2981              : 
    2982       941525 :   r.flush_denormals_to_zero ();
    2983       941525 :   return true;
    2984              : }
    2985              : 
    2986              : // Implement fold for a cast from float to another float.
    2987              : bool
    2988        61720 : operator_cast::op1_range (frange &r, tree type, const frange &lhs,
    2989              :                           const frange &op2, relation_trio) const
    2990              : {
    2991        61720 :   if (lhs.undefined_p ())
    2992              :     return false;
    2993        61720 :   tree lhs_type = lhs.type ();
    2994        61720 :   enum machine_mode mode = TYPE_MODE (type);
    2995        61720 :   enum machine_mode lhs_mode = TYPE_MODE (lhs_type);
    2996        61720 :   frange wlhs;
    2997        61720 :   bool rm;
    2998        61720 :   if (REAL_MODE_FORMAT (mode)->ieee_bits
    2999        57356 :       && REAL_MODE_FORMAT (lhs_mode)->ieee_bits
    3000        54134 :       && (REAL_MODE_FORMAT (lhs_mode)->ieee_bits
    3001              :           >= REAL_MODE_FORMAT (mode)->ieee_bits)
    3002        89683 :       && pow2p_hwi (REAL_MODE_FORMAT (mode)->ieee_bits))
    3003              :     {
    3004              :       /* If the cast is widening from IEEE exchange mode to
    3005              :          wider exchange mode or extended mode, no need to extend
    3006              :          the range on reverse operation.  */
    3007        27963 :       rm = false;
    3008        27963 :       wlhs = lhs;
    3009              :     }
    3010              :   else
    3011              :     {
    3012        33757 :       rm = true;
    3013        33757 :       wlhs = float_widen_lhs_range (lhs_type, lhs);
    3014              :     }
    3015        61720 :   auto save_flag_rounding_math = flag_rounding_math;
    3016        61720 :   flag_rounding_math = rm;
    3017        61720 :   bool ret = float_binary_op_range_finish (fold_range (r, type, wlhs, op2),
    3018              :                                            r, type, lhs);
    3019        61720 :   flag_rounding_math = save_flag_rounding_math;
    3020        61720 :   return ret;
    3021        61720 : }
    3022              : 
    3023              : // Implement fold for a cast from float to an int.
    3024              : bool
    3025       208702 : operator_cast::fold_range (irange &r, tree type, const frange &op1,
    3026              :                            const irange &, relation_trio) const
    3027              : {
    3028       208702 :   if (empty_range_varying (r, type, op1, op1))
    3029          541 :     return true;
    3030       208161 :   if (op1.maybe_isnan () || op1.maybe_isinf ())
    3031              :     {
    3032       182057 :       r.set_varying (type);
    3033       182057 :       return true;
    3034              :     }
    3035        26104 :   REAL_VALUE_TYPE lb, ub;
    3036        26104 :   real_trunc (&lb, VOIDmode, &op1.lower_bound ());
    3037        26104 :   real_trunc (&ub, VOIDmode, &op1.upper_bound ());
    3038        26104 :   REAL_VALUE_TYPE l, u;
    3039        26104 :   l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
    3040        26104 :   if (real_less (&lb, &l))
    3041              :     {
    3042         9430 :       r.set_varying (type);
    3043         9430 :       return true;
    3044              :     }
    3045        16674 :   u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
    3046        16674 :   if (real_less (&u, &ub))
    3047              :     {
    3048         7922 :       r.set_varying (type);
    3049         7922 :       return true;
    3050              :     }
    3051         8752 :   bool fail = false;
    3052         8752 :   wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
    3053         8752 :   wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
    3054         8752 :   if (fail)
    3055              :     {
    3056            0 :       r.set_varying (type);
    3057            0 :       return true;
    3058              :     }
    3059         8752 :   r.set (type, wlb, wub);
    3060         8752 :   return true;
    3061         8752 : }
    3062              : 
    3063              : // Implement op1_range for a cast from float to an int.
    3064              : bool
    3065         7165 : operator_cast::op1_range (frange &r, tree type, const irange &lhs,
    3066              :                           const frange &, relation_trio) const
    3067              : {
    3068         7165 :   if (lhs.undefined_p ())
    3069              :     return false;
    3070         7165 :   REAL_VALUE_TYPE lb, lbo, ub, ubo;
    3071         7165 :   wide_int lhs_lb = lhs.lower_bound ();
    3072         7165 :   wide_int lhs_ub = lhs.upper_bound ();
    3073         7165 :   tree lhs_type = lhs.type ();
    3074         7165 :   enum machine_mode mode = TYPE_MODE (type);
    3075         7165 :   real_from_integer (&lbo, VOIDmode, lhs_lb, TYPE_SIGN (lhs_type));
    3076         7165 :   real_from_integer (&ubo, VOIDmode, lhs_ub, TYPE_SIGN (lhs_type));
    3077         7165 :   real_convert (&lb, mode, &lbo);
    3078         7165 :   real_convert (&ub, mode, &ubo);
    3079         7165 :   if (real_identical (&lb, &lbo))
    3080              :     {
    3081              :       /* If low bound is exactly representable in type,
    3082              :          use nextafter (lb - 1., +inf).  */
    3083         7036 :       real_arithmetic (&lb, PLUS_EXPR, &lbo, &dconstm1);
    3084         7036 :       real_convert (&lb, mode, &lb);
    3085         7036 :       if (!real_identical (&lb, &lbo))
    3086         5806 :         frange_nextafter (mode, lb, dconstinf);
    3087         7036 :       if (real_identical (&lb, &lbo))
    3088         1232 :         frange_nextafter (mode, lb, dconstninf);
    3089              :     }
    3090          129 :   else if (real_less (&lbo, &lb))
    3091           13 :     frange_nextafter (mode, lb, dconstninf);
    3092         7165 :   if (real_identical (&ub, &ubo))
    3093              :     {
    3094              :       /* If upper bound is exactly representable in type,
    3095              :          use nextafter (ub + 1., -inf).  */
    3096         5333 :       real_arithmetic (&ub, PLUS_EXPR, &ubo, &dconst1);
    3097         5333 :       real_convert (&ub, mode, &ub);
    3098         5333 :       if (!real_identical (&ub, &ubo))
    3099         5273 :         frange_nextafter (mode, ub, dconstninf);
    3100         5333 :       if (real_identical (&ub, &ubo))
    3101           60 :         frange_nextafter (mode, ub, dconstinf);
    3102              :     }
    3103         1832 :   else if (real_less (&ub, &ubo))
    3104            0 :     frange_nextafter (mode, ub, dconstinf);
    3105         7165 :   r.set (type, lb, ub, nan_state (false));
    3106         7165 :   return true;
    3107         7165 : }
    3108              : 
    3109              : // Implement fold for a cast from int to a float.
    3110              : bool
    3111       840941 : operator_cast::fold_range (frange &r, tree type, const irange &op1,
    3112              :                            const frange &, relation_trio) const
    3113              : {
    3114       840941 :   if (empty_range_varying (r, type, op1, op1))
    3115         1402 :     return true;
    3116       839539 :   REAL_VALUE_TYPE lb, ub;
    3117       839539 :   wide_int op1_lb = op1.lower_bound ();
    3118       839539 :   wide_int op1_ub = op1.upper_bound ();
    3119       839539 :   tree op1_type = op1.type ();
    3120       839539 :   enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
    3121       839539 :   real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
    3122       839539 :   real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
    3123       839539 :   if (flag_rounding_math)
    3124              :     {
    3125         1129 :       REAL_VALUE_TYPE lbo = lb, ubo = ub;
    3126         1129 :       mode = TYPE_MODE (type);
    3127         1129 :       real_convert (&lb, mode, &lb);
    3128         1129 :       real_convert (&ub, mode, &ub);
    3129         1129 :       if (real_less (&lbo, &lb))
    3130          322 :         frange_nextafter (mode, lb, dconstninf);
    3131         1129 :       if (real_less (&ub, &ubo))
    3132          192 :         frange_nextafter (mode, ub, dconstinf);
    3133              :     }
    3134       839539 :   r.set (type, lb, ub, nan_state (false));
    3135       839539 :   frange_drop_infs (r, type);
    3136       839539 :   if (r.undefined_p ())
    3137            4 :     r.set_varying (type);
    3138       839539 :   return true;
    3139       839551 : }
    3140              : 
    3141              : // Implement op1_range for a cast from int to a float.
    3142              : bool
    3143       243279 : operator_cast::op1_range (irange &r, tree type, const frange &lhs,
    3144              :                           const irange &, relation_trio) const
    3145              : {
    3146       243279 :   if (lhs.undefined_p ())
    3147              :     return false;
    3148       243279 :   if (lhs.known_isnan ())
    3149              :     {
    3150            0 :       r.set_varying (type);
    3151            0 :       return true;
    3152              :     }
    3153       243279 :   REAL_VALUE_TYPE lb = lhs.lower_bound ();
    3154       243279 :   REAL_VALUE_TYPE ub = lhs.upper_bound ();
    3155       243279 :   enum machine_mode mode = TYPE_MODE (lhs.type ());
    3156       243279 :   frange_nextafter (mode, lb, dconstninf);
    3157       243279 :   frange_nextafter (mode, ub, dconstinf);
    3158       243279 :   if (flag_rounding_math)
    3159              :     {
    3160           37 :       real_floor (&lb, mode, &lb);
    3161           37 :       real_ceil (&ub, mode, &ub);
    3162              :     }
    3163              :   else
    3164              :     {
    3165       243242 :       real_trunc (&lb, mode, &lb);
    3166       243242 :       real_trunc (&ub, mode, &ub);
    3167              :     }
    3168       243279 :   REAL_VALUE_TYPE l, u;
    3169       243279 :   wide_int wlb, wub;
    3170       243279 :   l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
    3171       243279 :   if (real_less (&lb, &l))
    3172        28757 :     wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3173              :   else
    3174              :     {
    3175       214522 :       bool fail = false;
    3176       214522 :       wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
    3177       214522 :       if (fail)
    3178            0 :         wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3179              :     }
    3180       243279 :   u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
    3181       243279 :   if (real_less (&u, &ub))
    3182        39885 :     wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3183              :   else
    3184              :     {
    3185       203394 :       bool fail = false;
    3186       203394 :       wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
    3187       203394 :       if (fail)
    3188            0 :         wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
    3189              :     }
    3190       243279 :   r.set (type, wlb, wub);
    3191       243279 :   return true;
    3192       243279 : }
    3193              : 
    3194              : // Initialize any float operators to the primary table
    3195              : 
    3196              : void
    3197       284591 : range_op_table::initialize_float_ops ()
    3198              : {
    3199       284591 :   set (UNLE_EXPR, fop_unordered_le);
    3200       284591 :   set (UNLT_EXPR, fop_unordered_lt);
    3201       284591 :   set (UNGE_EXPR, fop_unordered_ge);
    3202       284591 :   set (UNGT_EXPR, fop_unordered_gt);
    3203       284591 :   set (UNEQ_EXPR, fop_unordered_equal);
    3204       284591 :   set (ORDERED_EXPR, fop_ordered);
    3205       284591 :   set (UNORDERED_EXPR, fop_unordered);
    3206       284591 :   set (LTGT_EXPR, fop_ltgt);
    3207       284591 :   set (RDIV_EXPR, fop_div);
    3208       284591 : }
    3209              : 
    3210              : #if CHECKING_P
    3211              : #include "selftest.h"
    3212              : 
    3213              : namespace selftest
    3214              : {
    3215              : 
    3216              : // Build an frange from string endpoints.
    3217              : 
    3218              : static inline frange
    3219           16 : frange_float (const char *lb, const char *ub, tree type = float_type_node)
    3220              : {
    3221           16 :   REAL_VALUE_TYPE min, max;
    3222           16 :   gcc_assert (real_from_string (&min, lb) == 0);
    3223           16 :   gcc_assert (real_from_string (&max, ub) == 0);
    3224           16 :   return frange (type, min, max);
    3225              : }
    3226              : 
    3227              : void
    3228            4 : range_op_float_tests ()
    3229              : {
    3230            4 :   frange r, r0, r1;
    3231            4 :   frange trange (float_type_node);
    3232              : 
    3233              :   // negate([-5, +10]) => [-10, 5]
    3234            4 :   r0 = frange_float ("-5", "10");
    3235            4 :   range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
    3236            4 :   ASSERT_EQ (r, frange_float ("-10", "5"));
    3237              : 
    3238              :   // negate([0, 1] -NAN) => [-1, -0] +NAN
    3239            4 :   r0 = frange_float ("0", "1");
    3240            4 :   r0.update_nan (true);
    3241            4 :   range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
    3242            4 :   r1 = frange_float ("-1", "-0");
    3243            4 :   r1.update_nan (false);
    3244            4 :   ASSERT_EQ (r, r1);
    3245              : 
    3246              :   // [-INF,+INF] + [-INF,+INF] could be a NAN.
    3247            4 :   range_op_handler plus (PLUS_EXPR);
    3248            4 :   r0.set_varying (float_type_node);
    3249            4 :   r1.set_varying (float_type_node);
    3250            4 :   r0.clear_nan ();
    3251            4 :   r1.clear_nan ();
    3252            4 :   plus.fold_range (r, float_type_node, r0, r1);
    3253            4 :   if (HONOR_NANS (float_type_node))
    3254            8 :     ASSERT_TRUE (r.maybe_isnan ());
    3255            4 : }
    3256              : 
    3257              : } // namespace selftest
    3258              : 
    3259              : #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.