LCOV - code coverage report
Current view: top level - gcc - gimple-range-op.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.3 % 846 705
Test Date: 2026-10-17 16:30:31 Functions: 86.0 % 43 37
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Code for GIMPLE range op related routines.
       2              :    Copyright (C) 2019-2026 Free Software Foundation, Inc.
       3              :    Contributed by Andrew MacLeod <amacleod@redhat.com>
       4              :    and Aldy Hernandez <aldyh@redhat.com>.
       5              : 
       6              : This file is part of GCC.
       7              : 
       8              : GCC is free software; you can redistribute it and/or modify
       9              : it under the terms of the GNU General Public License as published by
      10              : the Free Software Foundation; either version 3, or (at your option)
      11              : any later version.
      12              : 
      13              : GCC is distributed in the hope that it will be useful,
      14              : but WITHOUT ANY WARRANTY; without even the implied warranty of
      15              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16              : GNU General Public License for more details.
      17              : 
      18              : You should have received a copy of the GNU General Public License
      19              : along with GCC; see the file COPYING3.  If not see
      20              : <http://www.gnu.org/licenses/>.  */
      21              : 
      22              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "backend.h"
      26              : #include "insn-codes.h"
      27              : #include "tree.h"
      28              : #include "gimple.h"
      29              : #include "ssa.h"
      30              : #include "gimple-pretty-print.h"
      31              : #include "optabs-tree.h"
      32              : #include "gimple-iterator.h"
      33              : #include "gimple-fold.h"
      34              : #include "wide-int.h"
      35              : #include "fold-const.h"
      36              : #include "case-cfn-macros.h"
      37              : #include "omp-general.h"
      38              : #include "cfgloop.h"
      39              : #include "tree-ssa-loop.h"
      40              : #include "tree-scalar-evolution.h"
      41              : #include "langhooks.h"
      42              : #include "vr-values.h"
      43              : #include "range.h"
      44              : #include "value-query.h"
      45              : #include "gimple-range.h"
      46              : #include "attr-fnspec.h"
      47              : #include "realmpfr.h"
      48              : 
      49              : // Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
      50              : // on the statement.  For efficiency, it is an error to not pass in enough
      51              : // elements for the vector.  Return the number of ssa-names.
      52              : 
      53              : unsigned
      54    342832292 : gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt)
      55              : {
      56    342832292 :   tree ssa;
      57    342832292 :   int count = 0;
      58              : 
      59    342832292 :   gimple_range_op_handler handler (stmt);
      60    342832292 :   if (handler)
      61              :     {
      62     90285589 :       gcc_checking_assert (vec_size >= 2);
      63     90285589 :       if ((ssa = gimple_range_ssa_p (handler.operand1 ())))
      64     76783328 :         vec[count++] = ssa;
      65     90285589 :       if ((ssa = gimple_range_ssa_p (handler.operand2 ())))
      66     20849397 :         vec[count++] = ssa;
      67              :     }
      68    252546703 :   else if (is_a<gassign *> (stmt)
      69    252546703 :            && gimple_assign_rhs_code (stmt) == COND_EXPR)
      70              :     {
      71       114181 :       gcc_checking_assert (vec_size >= 3);
      72       114181 :       gassign *st = as_a<gassign *> (stmt);
      73       114181 :       if ((ssa = gimple_range_ssa_p (gimple_assign_rhs1 (st))))
      74       114181 :         vec[count++] = ssa;
      75       228362 :       if ((ssa = gimple_range_ssa_p (gimple_assign_rhs2 (st))))
      76       105588 :         vec[count++] = ssa;
      77       228362 :       if ((ssa = gimple_range_ssa_p (gimple_assign_rhs3 (st))))
      78        39113 :         vec[count++] = ssa;
      79              :     }
      80    342832292 :   return count;
      81              : }
      82              : 
      83              : // Return the base of the RHS of an assignment.
      84              : 
      85              : static tree
      86   1017500506 : gimple_range_base_of_assignment (const gimple *stmt)
      87              : {
      88   1017500506 :   gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
      89   1017500506 :   tree op1 = gimple_assign_rhs1 (stmt);
      90   1017500506 :   if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
      91     13718031 :     return get_base_address (TREE_OPERAND (op1, 0));
      92              :   return op1;
      93              : }
      94              : 
      95              : // If statement is supported by range-ops, set the CODE and return the TYPE.
      96              : 
      97              : static inline enum tree_code
      98   2543543985 : get_code (gimple *s)
      99              : {
     100   2543543985 :   if (const gassign *ass = dyn_cast<const gassign *> (s))
     101   1417075610 :     return gimple_assign_rhs_code (ass);
     102   1126468375 :   if (const gcond *cond = dyn_cast<const gcond *> (s))
     103    467599010 :     return gimple_cond_code (cond);
     104              :   return ERROR_MARK;
     105              : }
     106              : 
     107              : // If statement S has a supported range_op handler return TRUE.
     108              : 
     109              : bool
     110    435537380 : gimple_range_op_handler::supported_p (gimple *s)
     111              : {
     112    435537380 :   enum tree_code code = get_code (s);
     113    435537380 :   if (range_op_handler (code))
     114              :     return true;
     115    108669202 :   if (is_a <gcall *> (s) && gimple_range_op_handler (s))
     116       758000 :     return true;
     117              :   return false;
     118              : }
     119              : 
     120              : // Construct a handler object for statement S.
     121              : 
     122   2108006605 : gimple_range_op_handler::gimple_range_op_handler (gimple *s)
     123              : {
     124   2108006605 :   range_op_handler oper (get_code (s));
     125   2108006605 :   m_stmt = s;
     126   2108006605 :   m_op1 = NULL_TREE;
     127   2108006605 :   m_op2 = NULL_TREE;
     128              :   // Recomputation defaults to TRUE.
     129   2108006605 :   m_recomputable = true;
     130              : 
     131   2108006605 :   if (oper)
     132   1247320285 :     switch (gimple_code (m_stmt))
     133              :       {
     134    229819779 :         case GIMPLE_COND:
     135    229819779 :           m_op1 = gimple_cond_lhs (m_stmt);
     136    229819779 :           m_op2 = gimple_cond_rhs (m_stmt);
     137              :           // Check that operands are supported types.  One check is enough.
     138    229819779 :           if (value_range::supports_type_p (TREE_TYPE (m_op1)))
     139    229758651 :             m_operator = oper.range_op ();
     140    229819779 :           gcc_checking_assert (m_operator);
     141   1247320285 :           return;
     142   1017500506 :         case GIMPLE_ASSIGN:
     143   1017500506 :           m_op1 = gimple_range_base_of_assignment (m_stmt);
     144   1017500506 :           if (m_op1 && TREE_CODE (m_op1) == MEM_REF)
     145              :             {
     146              :               // If the base address is an SSA_NAME, we return it
     147              :               // here.  This allows processing of the range of that
     148              :               // name, while the rest of the expression is simply
     149              :               // ignored.  The code in range_ops will see the
     150              :               // ADDR_EXPR and do the right thing.
     151     13189759 :               tree ssa = TREE_OPERAND (m_op1, 0);
     152     13189759 :               if (TREE_CODE (ssa) == SSA_NAME)
     153     13189654 :                 m_op1 = ssa;
     154              :             }
     155              :           // VIEW_CONVERT_EXPR needs to descend one level deeper to pick
     156              :           // up the symbolic operand.
     157   1017500506 :           if (TREE_CODE (m_op1) == VIEW_CONVERT_EXPR)
     158      2696094 :             m_op1 = TREE_OPERAND (m_op1, 0);
     159   1017500506 :           if (gimple_num_ops (m_stmt) >= 3)
     160    778185135 :             m_op2 = gimple_assign_rhs2 (m_stmt);
     161              :           // Check that operands are supported types.  One check is enough.
     162   1017500506 :           if ((m_op1 && !value_range::supports_type_p (TREE_TYPE (m_op1))))
     163              :             return;
     164   1016816121 :           m_operator = oper.range_op ();
     165   1016816121 :           gcc_checking_assert (m_operator);
     166              :           return;
     167            0 :         default:
     168            0 :           gcc_unreachable ();
     169              :           return;
     170              :       }
     171              :   // If no range-op table entry handled this stmt, check for other supported
     172              :   // statements.
     173    860686320 :   if (is_a <gcall *> (m_stmt))
     174     75645517 :     maybe_builtin_call ();
     175              :   else
     176    785040803 :     maybe_non_standard ();
     177    860686320 :   gcc_checking_assert (m_operator);
     178              : }
     179              : 
     180              : // Calculate what we can determine of the range of this unary
     181              : // statement's operand if the lhs of the expression has the range
     182              : // LHS_RANGE.  Return false if nothing can be determined.
     183              : 
     184              : bool
     185        27499 : gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range)
     186              : {
     187              :   // Give up on empty ranges.
     188        27499 :   if (lhs_range.undefined_p ())
     189              :     return false;
     190              : 
     191              :   // Unary operations require the type of the first operand in the
     192              :   // second range position.
     193        27499 :   tree type = TREE_TYPE (operand1 ());
     194        27499 :   value_range type_range (type);
     195        27499 :   type_range.set_varying (type);
     196        27499 :   return op1_range (r, type, lhs_range, type_range);
     197        27499 : }
     198              : 
     199              : // Calculate what we can determine of the range of this statement's
     200              : // first operand if the lhs of the expression has the range LHS_RANGE
     201              : // and the second operand has the range OP2_RANGE.  Return false if
     202              : // nothing can be determined.
     203              : 
     204              : bool
     205    114948099 : gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range,
     206              :                                    const vrange &op2_range, relation_trio k)
     207              : {
     208              :   // Give up on empty ranges.
     209    114948099 :   if (lhs_range.undefined_p ())
     210              :     return false;
     211              : 
     212              :   // Unary operation are allowed to pass a range in for second operand
     213              :   // as there are often additional restrictions beyond the type which
     214              :   // can be imposed.  See operator_cast::op1_range().
     215    114948099 :   tree type = TREE_TYPE (operand1 ());
     216              :   // If op2 is undefined, solve as if it is varying.
     217    114948099 :   if (op2_range.undefined_p ())
     218              :     {
     219        52089 :       if (gimple_num_ops (m_stmt) < 3)
     220              :         return false;
     221        15851 :       tree op2_type;
     222              :       // This is sometimes invoked on single operand stmts.
     223        15851 :       if (operand2 ())
     224        11929 :         op2_type = TREE_TYPE (operand2 ());
     225              :       else
     226         3922 :         op2_type = TREE_TYPE (operand1 ());
     227        15851 :       value_range trange (op2_type);
     228        15851 :       trange.set_varying (op2_type);
     229        15851 :       return op1_range (r, type, lhs_range, trange, k);
     230        15851 :     }
     231    114896010 :   return op1_range (r, type, lhs_range, op2_range, k);
     232              : }
     233              : 
     234              : // Calculate what we can determine of the range of this statement's
     235              : // second operand if the lhs of the expression has the range LHS_RANGE
     236              : // and the first operand has the range OP1_RANGE.  Return false if
     237              : // nothing can be determined.
     238              : 
     239              : bool
     240     32381820 : gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
     241              :                                    const vrange &op1_range, relation_trio k)
     242              : {
     243              :   // Give up on empty ranges.
     244     32381820 :   if (lhs_range.undefined_p ())
     245              :     return false;
     246              : 
     247     32381820 :   tree type = TREE_TYPE (operand2 ());
     248              :   // If op1 is undefined, solve as if it is varying.
     249     32381820 :   if (op1_range.undefined_p ())
     250              :     {
     251        10398 :       tree op1_type = TREE_TYPE (operand1 ());
     252        10398 :       value_range trange (op1_type);
     253        10398 :       trange.set_varying (op1_type);
     254        10398 :       return op2_range (r, type, lhs_range, trange, k);
     255        10398 :     }
     256     32371422 :   return op2_range (r, type, lhs_range, op1_range, k);
     257              : }
     258              : 
     259              : // --------------------------------------------------------------------
     260              : 
     261              : // Implement range operator for float CFN_BUILT_IN_CONSTANT_P.
     262              : class cfn_constant_float_p : public range_operator
     263              : {
     264              : public:
     265              :   using range_operator::fold_range;
     266          174 :   virtual bool fold_range (irange &r, tree type, const frange &lh,
     267              :                            const irange &, relation_trio) const
     268              :   {
     269          174 :     if (lh.singleton_p ())
     270              :       {
     271            0 :         wide_int one = wi::one (TYPE_PRECISION (type));
     272            0 :         r.set (type, one, one);
     273            0 :         return true;
     274            0 :       }
     275          174 :     if (cfun->after_inlining)
     276              :       {
     277           56 :         r.set_zero (type);
     278           56 :         return true;
     279              :       }
     280              :     return false;
     281              :   }
     282              : } op_cfn_constant_float_p;
     283              : 
     284              : // Implement range operator for integral CFN_BUILT_IN_CONSTANT_P.
     285              : class cfn_constant_p : public range_operator
     286              : {
     287              : public:
     288              :   using range_operator::fold_range;
     289       165578 :   virtual bool fold_range (irange &r, tree type, const irange &lh,
     290              :                            const irange &, relation_trio) const
     291              :   {
     292       165578 :     if (lh.singleton_p ())
     293              :       {
     294          926 :         wide_int one = wi::one (TYPE_PRECISION (type));
     295          926 :         r.set (type, one, one);
     296          926 :         return true;
     297          926 :       }
     298       164652 :     if (cfun->after_inlining)
     299              :       {
     300        84736 :         r.set_zero (type);
     301        84736 :         return true;
     302              :       }
     303              :     return false;
     304              :   }
     305              : } op_cfn_constant_p;
     306              : 
     307              : // Implement range operator for integral/pointer functions returning
     308              : // the first argument.
     309              : class cfn_pass_through_arg1 : public range_operator
     310              : {
     311              : public:
     312              :   using range_operator::fold_range;
     313              :   using range_operator::op1_range;
     314       219854 :   virtual bool fold_range (irange &r, tree, const irange &lh,
     315              :                            const irange &, relation_trio) const
     316              :   {
     317       219854 :     r = lh;
     318       219854 :     return true;
     319              :   }
     320        82125 :   virtual bool fold_range (prange &r, tree, const prange &lh,
     321              :                            const prange &, relation_trio) const
     322              :   {
     323        82125 :     r = lh;
     324        82125 :     return true;
     325              :   }
     326       313252 :   virtual bool op1_range (irange &r, tree, const irange &lhs,
     327              :                           const irange &, relation_trio) const
     328              :   {
     329       313252 :     r = lhs;
     330       313252 :     return true;
     331              :   }
     332        10382 :   virtual bool op1_range (prange &r, tree, const prange &lhs,
     333              :                           const prange &, relation_trio) const
     334              :   {
     335        10382 :     r = lhs;
     336        10382 :     return true;
     337              :   }
     338              : } op_cfn_pass_through_arg1;
     339              : 
     340              : // Implement range operator for CFN_BUILT_IN_SIGNBIT.
     341              : class cfn_signbit : public range_operator
     342              : {
     343              : public:
     344              :   using range_operator::fold_range;
     345              :   using range_operator::op1_range;
     346        55834 :   virtual bool fold_range (irange &r, tree type, const frange &lh,
     347              :                            const irange &, relation_trio) const override
     348              :   {
     349        55834 :     bool signbit;
     350        55834 :     if (lh.signbit_p (signbit))
     351              :       {
     352         2868 :         if (signbit)
     353         1465 :           r.set_nonzero (type);
     354              :         else
     355         1403 :           r.set_zero (type);
     356              :         return true;
     357              :       }
     358              :    return false;
     359              :   }
     360        11000 :   virtual bool op1_range (frange &r, tree type, const irange &lhs,
     361              :                           const frange &, relation_trio) const override
     362              :   {
     363        11000 :     if (lhs.zero_p ())
     364              :       {
     365         5154 :         r.set (type, dconst0, frange_val_max (type));
     366         5154 :         r.update_nan (false);
     367         5154 :         return true;
     368              :       }
     369         5846 :     if (!lhs.contains_p (wi::zero (TYPE_PRECISION (lhs.type ()))))
     370              :       {
     371         5846 :         r.set (type, frange_val_min (type), dconstm0);
     372         5846 :         r.update_nan (true);
     373         5846 :         return true;
     374              :       }
     375              :     return false;
     376              :   }
     377              : } op_cfn_signbit;
     378              : 
     379              : // Implement range operator for CFN_BUILT_IN_COPYSIGN
     380              : class cfn_copysign : public range_operator
     381              : {
     382              : public:
     383              :   using range_operator::fold_range;
     384       155780 :   virtual bool fold_range (frange &r, tree type, const frange &lh,
     385              :                            const frange &rh, relation_trio) const override
     386              :   {
     387       155780 :     frange neg;
     388       155780 :     if (!range_op_handler (ABS_EXPR).fold_range (r, type, lh, frange (type)))
     389              :       return false;
     390       311560 :     if (!range_op_handler (NEGATE_EXPR).fold_range (neg, type, r,
     391       155780 :                                                     frange (type)))
     392              :       return false;
     393              : 
     394       155780 :     bool signbit;
     395       155780 :     if (rh.signbit_p (signbit))
     396              :       {
     397              :         // If the sign is negative, flip the result from ABS,
     398              :         // otherwise leave things positive.
     399          385 :         if (signbit)
     400          381 :           r = neg;
     401              :       }
     402              :     else
     403              :       // If the sign is unknown, keep the positive and negative
     404              :       // alternatives.
     405       155395 :       r.union_ (neg);
     406              :     return true;
     407       155780 :   }
     408              : } op_cfn_copysign;
     409              : 
     410              : /* Compute FUNC (ARG) where FUNC is a mpfr function.  If RES_LOW is non-NULL,
     411              :    set it to low bound of possible range if the function is expected to have
     412              :    ULPS precision and similarly if RES_HIGH is non-NULL, set it to high bound.
     413              :    If the function returns false, the results weren't set.  */
     414              : 
     415              : static bool
     416        50608 : frange_mpfr_arg1 (REAL_VALUE_TYPE *res_low, REAL_VALUE_TYPE *res_high,
     417              :                   int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
     418              :                   const REAL_VALUE_TYPE &arg, tree type, unsigned ulps)
     419              : {
     420        50608 :   if (ulps == ~0U || !real_isfinite (&arg))
     421              :     return false;
     422        24051 :   machine_mode mode = TYPE_MODE (type);
     423        24051 :   const real_format *format = REAL_MODE_FORMAT (mode);
     424        24051 :   auto_mpfr m (format->p);
     425        24051 :   mpfr_from_real (m, &arg, MPFR_RNDN);
     426        24051 :   mpfr_clear_flags ();
     427        24051 :   bool inexact = func (m, m, MPFR_RNDN);
     428        24051 :   if (!mpfr_number_p (m) || mpfr_overflow_p () || mpfr_underflow_p ())
     429              :     return false;
     430              : 
     431        22556 :   REAL_VALUE_TYPE value, result;
     432        22556 :   real_from_mpfr (&value, m, format, MPFR_RNDN);
     433        22556 :   if (!real_isfinite (&value))
     434              :     return false;
     435        22556 :   if ((value.cl == rvc_zero) != (mpfr_zero_p (m) != 0))
     436            0 :     inexact = true;
     437              : 
     438        22556 :   real_convert (&result, format, &value);
     439        22556 :   if (!real_isfinite (&result))
     440              :     return false;
     441        22556 :   bool round_low = false;
     442        22556 :   bool round_high = false;
     443        22556 :   if (!ulps && flag_rounding_math)
     444            0 :     ++ulps;
     445        22556 :   if (inexact || !real_identical (&result, &value))
     446              :     {
     447        50162 :       if (MODE_COMPOSITE_P (mode))
     448              :         round_low = round_high = true;
     449              :       else
     450              :         {
     451         7166 :           round_low = !real_less (&result, &value);
     452         7166 :           round_high = !real_less (&value, &result);
     453              :         }
     454              :     }
     455        22556 :   if (res_low)
     456              :     {
     457        15829 :       *res_low = result;
     458        18228 :       for (unsigned int i = 0; i < ulps + round_low; ++i)
     459         2399 :         frange_nextafter (mode, *res_low, dconstninf);
     460              :     }
     461        22556 :   if (res_high)
     462              :     {
     463         7755 :       *res_high = result;
     464        14732 :       for (unsigned int i = 0; i < ulps + round_high; ++i)
     465         6977 :         frange_nextafter (mode, *res_high, dconstinf);
     466              :     }
     467              :   return true;
     468        24051 : }
     469              : 
     470              : class cfn_sqrt : public range_operator
     471              : {
     472              : public:
     473              :   using range_operator::fold_range;
     474              :   using range_operator::op1_range;
     475        33056 :   virtual bool fold_range (frange &r, tree type,
     476              :                            const frange &lh, const frange &,
     477              :                            relation_trio) const final override
     478              :   {
     479        33056 :     if (lh.undefined_p ())
     480              :       return false;
     481        32773 :     if (lh.known_isnan () || real_less (&lh.upper_bound (), &dconstm0))
     482              :       {
     483         7859 :         r.set_nan (type);
     484         7859 :         return true;
     485              :       }
     486        24914 :     unsigned bulps
     487        24914 :       = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), true);
     488        24914 :     if (bulps == ~0U)
     489            0 :       r.set_varying (type);
     490        24914 :     else if (bulps == 0)
     491        24914 :       r.set (type, dconstm0, dconstinf);
     492              :     else
     493              :       {
     494            0 :         REAL_VALUE_TYPE boundmin = dconstm0;
     495            0 :         while (bulps--)
     496            0 :           frange_nextafter (TYPE_MODE (type), boundmin, dconstninf);
     497            0 :         r.set (type, boundmin, dconstinf);
     498              :       }
     499        32022 :     if (!lh.maybe_isnan () && !real_less (&lh.lower_bound (), &dconst0))
     500         5330 :       r.clear_nan ();
     501              : 
     502        24914 :     unsigned ulps
     503        24914 :       = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), false);
     504        24914 :     if (ulps == ~0U)
     505              :       return true;
     506        24790 :     REAL_VALUE_TYPE lb = lh.lower_bound ();
     507        24790 :     REAL_VALUE_TYPE ub = lh.upper_bound ();
     508        24790 :     if (!frange_mpfr_arg1 (&lb, NULL, mpfr_sqrt, lb, type, ulps))
     509         9989 :       lb = dconstninf;
     510        24790 :     if (!frange_mpfr_arg1 (NULL, &ub, mpfr_sqrt, ub, type, ulps))
     511        18063 :       ub = dconstinf;
     512        24790 :     frange r2;
     513        24790 :     r2.set (type, lb, ub);
     514        24790 :     r2.flush_denormals_to_zero ();
     515        24790 :     r.intersect (r2);
     516        24790 :     return true;
     517        24790 :   }
     518         1147 :   virtual bool op1_range (frange &r, tree type,
     519              :                           const frange &lhs, const frange &,
     520              :                           relation_trio) const final override
     521              :   {
     522         1147 :     if (lhs.undefined_p ())
     523              :       return false;
     524              : 
     525              :     // A known NAN means the input is [-INF,-0.) U +-NAN.
     526         1147 :     if (lhs.known_isnan ())
     527              :       {
     528            0 :       known_nan:
     529            0 :         REAL_VALUE_TYPE ub = dconstm0;
     530            0 :         frange_nextafter (TYPE_MODE (type), ub, dconstninf);
     531            0 :         r.set (type, dconstninf, ub);
     532              :         // No r.flush_denormals_to_zero (); here - it is a reverse op.
     533            0 :         return true;
     534              :       }
     535              : 
     536              :     // Results outside of [-0.0, +Inf] are impossible.
     537         1147 :     unsigned bulps
     538         1147 :       = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), true);
     539         1147 :     if (bulps != ~0U)
     540              :       {
     541         1147 :         const REAL_VALUE_TYPE &ub = lhs.upper_bound ();
     542         1147 :         REAL_VALUE_TYPE m0 = dconstm0;
     543         1147 :         while (bulps--)
     544            0 :           frange_nextafter (TYPE_MODE (type), m0, dconstninf);
     545         1147 :         if (real_less (&ub, &m0))
     546              :           {
     547            0 :             if (!lhs.maybe_isnan ())
     548            0 :               r.set_undefined ();
     549              :             else
     550              :               // If lhs could be NAN and finite result is impossible,
     551              :               // the range is like lhs.known_isnan () above.
     552            0 :               goto known_nan;
     553            0 :             return true;
     554              :           }
     555              :       }
     556              : 
     557         1786 :     if (!lhs.maybe_isnan ())
     558              :       // If NAN is not valid result, the input cannot include either
     559              :       // a NAN nor values smaller than -0.
     560          639 :       r.set (type, dconstm0, dconstinf, nan_state (false, false));
     561              :     else
     562          508 :       r.set_varying (type);
     563              : 
     564         1147 :     unsigned ulps
     565         1147 :       = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), false);
     566         1147 :     if (ulps == ~0U)
     567              :       return true;
     568         1147 :     REAL_VALUE_TYPE lb = lhs.lower_bound ();
     569         1147 :     REAL_VALUE_TYPE ub = lhs.upper_bound ();
     570         1786 :     if (!lhs.maybe_isnan () && real_less (&dconst0, &lb))
     571              :       {
     572          146 :         for (unsigned i = 0; i < ulps; ++i)
     573            0 :           frange_nextafter (TYPE_MODE (type), lb, dconstninf);
     574          146 :         if (real_less (&dconst0, &lb))
     575              :           {
     576          146 :             frange wlhs (type, lb, dconstinf);
     577          146 :             wlhs.clear_nan ();
     578          146 :             wlhs.widen (type);
     579          146 :             REAL_VALUE_TYPE op = wlhs.lower_bound ();
     580          146 :             frange_arithmetic (MULT_EXPR, type, lb, op, op, dconstninf);
     581          146 :           }
     582              :         else
     583            0 :           lb = dconstninf;
     584              :       }
     585              :     else
     586         1001 :       lb = dconstninf;
     587         1147 :     if (real_isfinite (&ub) && real_less (&dconst0, &ub))
     588              :       {
     589          282 :         for (unsigned i = 0; i < ulps; ++i)
     590            0 :           frange_nextafter (TYPE_MODE (type), ub, dconstinf);
     591          282 :         if (real_isfinite (&ub))
     592              :           {
     593          282 :             frange wlhs (type, dconstninf, ub);
     594          282 :             wlhs.clear_nan ();
     595          282 :             wlhs.widen (type);
     596          282 :             REAL_VALUE_TYPE op = wlhs.upper_bound ();
     597          282 :             frange_arithmetic (MULT_EXPR, type, ub, op, op, dconstinf);
     598          282 :           }
     599              :         else
     600            0 :           ub = dconstinf;
     601              :       }
     602              :     else
     603          865 :       ub = dconstinf;
     604         2294 :     frange r2;
     605         1147 :     r2.set (type, lb, ub);
     606         1147 :     r.intersect (r2);
     607         1147 :     return true;
     608              :   }
     609              : } op_cfn_sqrt;
     610              : 
     611              : class cfn_sincos : public range_operator
     612              : {
     613              : public:
     614              :   using range_operator::fold_range;
     615              :   using range_operator::op1_range;
     616              :   cfn_sincos (combined_fn cfn) { m_cfn = cfn; }
     617        11921 :   virtual bool fold_range (frange &r, tree type,
     618              :                            const frange &lh, const frange &,
     619              :                            relation_trio) const final override
     620              :   {
     621        11921 :     if (lh.undefined_p ())
     622              :       return false;
     623        11905 :     if (lh.known_isnan () || lh.known_isinf ())
     624              :       {
     625            0 :         r.set_nan (type);
     626            0 :         return true;
     627              :       }
     628        11905 :     unsigned bulps = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type),
     629              :                                                       true);
     630        11905 :     if (bulps == ~0U)
     631            0 :       r.set_varying (type);
     632        11905 :     else if (bulps == 0)
     633        11853 :       r.set (type, dconstm1, dconst1);
     634              :     else
     635              :       {
     636           52 :         REAL_VALUE_TYPE boundmin, boundmax;
     637           52 :         boundmax = dconst1;
     638          104 :         while (bulps--)
     639           52 :           frange_nextafter (TYPE_MODE (type), boundmax, dconstinf);
     640           52 :         real_arithmetic (&boundmin, NEGATE_EXPR, &boundmax, NULL);
     641           52 :         r.set (type, boundmin, boundmax);
     642              :       }
     643        15097 :     if (!lh.maybe_isnan () && !lh.maybe_isinf ())
     644         1172 :       r.clear_nan ();
     645              : 
     646        11905 :     unsigned ulps
     647        11905 :       = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type), false);
     648        11905 :     if (ulps == ~0U)
     649              :       return true;
     650        11905 :     REAL_VALUE_TYPE lb = lh.lower_bound ();
     651        11905 :     REAL_VALUE_TYPE ub = lh.upper_bound ();
     652        11905 :     REAL_VALUE_TYPE diff;
     653        11905 :     real_arithmetic (&diff, MINUS_EXPR, &ub, &lb);
     654        11905 :     if (!real_isfinite (&diff))
     655              :       return true;
     656         1788 :     REAL_VALUE_TYPE pi = dconst_pi ();
     657         1788 :     REAL_VALUE_TYPE pix2;
     658         1788 :     real_arithmetic (&pix2, PLUS_EXPR, &pi, &pi);
     659              :     // We can only try to narrow the range further if ub-lb < 2*pi.
     660         1788 :     if (!real_less (&diff, &pix2))
     661              :       return true;
     662          257 :     REAL_VALUE_TYPE lb_lo, lb_hi, ub_lo, ub_hi;
     663          257 :     REAL_VALUE_TYPE lb_deriv_lo, lb_deriv_hi, ub_deriv_lo, ub_deriv_hi;
     664          257 :     if (!frange_mpfr_arg1 (&lb_lo, &lb_hi,
     665          257 :                            m_cfn == CFN_SIN ? mpfr_sin : mpfr_cos, lb,
     666              :                            type, ulps)
     667          257 :         || !frange_mpfr_arg1 (&ub_lo, &ub_hi,
     668          257 :                               m_cfn == CFN_SIN ? mpfr_sin : mpfr_cos, ub,
     669              :                               type, ulps)
     670          257 :         || !frange_mpfr_arg1 (&lb_deriv_lo, &lb_deriv_hi,
     671          257 :                               m_cfn == CFN_SIN ? mpfr_cos : mpfr_sin, lb,
     672              :                               type, 0)
     673          514 :         || !frange_mpfr_arg1 (&ub_deriv_lo, &ub_deriv_hi,
     674          257 :                               m_cfn == CFN_SIN ? mpfr_cos : mpfr_sin, ub,
     675              :                               type, 0))
     676              :       return true;
     677          257 :     if (m_cfn == CFN_COS)
     678              :       {
     679              :         // Derivative of cos is -sin, so negate.
     680           73 :         lb_deriv_lo.sign ^= 1;
     681           73 :         lb_deriv_hi.sign ^= 1;
     682           73 :         ub_deriv_lo.sign ^= 1;
     683           73 :         ub_deriv_hi.sign ^= 1;
     684              :       }
     685              : 
     686          257 :     if (real_less (&lb_lo, &ub_lo))
     687          124 :       lb = lb_lo;
     688              :     else
     689          133 :       lb = ub_lo;
     690          257 :     if (real_less (&lb_hi, &ub_hi))
     691          124 :       ub = ub_hi;
     692              :     else
     693          133 :       ub = lb_hi;
     694              : 
     695              :     // The range between the function result on the boundaries may need
     696              :     // to be extended to +1 (+Inf) or -1 (-Inf) or both depending on the
     697              :     // derivative or length of the argument range (diff).
     698              : 
     699              :     // First handle special case, where the derivative has different signs,
     700              :     // so the bound must be roughly -1 or +1.
     701          257 :     if (real_isneg (&lb_deriv_lo) != real_isneg (&lb_deriv_hi))
     702              :       {
     703            0 :         if (real_isneg (&lb_lo))
     704            0 :           lb = dconstninf;
     705              :         else
     706            0 :           ub = dconstinf;
     707              :       }
     708          257 :     if (real_isneg (&ub_deriv_lo) != real_isneg (&ub_deriv_hi))
     709              :       {
     710            0 :         if (real_isneg (&ub_lo))
     711            0 :           lb = dconstninf;
     712              :         else
     713            0 :           ub = dconstinf;
     714              :       }
     715              : 
     716              :     // If derivative at lower_bound and upper_bound have the same sign,
     717              :     // the function grows or declines on the whole range if diff < pi, so
     718              :     // [lb, ub] is correct, and if diff >= pi the result range must include
     719              :     // both the minimum and maximum.
     720          257 :     if (real_isneg (&lb_deriv_lo) == real_isneg (&ub_deriv_lo))
     721              :       {
     722          157 :         if (!real_less (&diff, &pi))
     723              :           return true;
     724              :       }
     725              :     // If function declines at lower_bound and grows at upper_bound,
     726              :     // the result range must include the minimum, so set lb to -Inf.
     727          100 :     else if (real_isneg (&lb_deriv_lo))
     728           19 :       lb = dconstninf;
     729              :     // If function grows at lower_bound and declines at upper_bound,
     730              :     // the result range must include the maximum, so set ub to +Inf.
     731              :     else
     732           81 :       ub = dconstinf;
     733          237 :     frange r2;
     734          237 :     r2.set (type, lb, ub);
     735          237 :     r2.flush_denormals_to_zero ();
     736          237 :     r.intersect (r2);
     737          237 :     return true;
     738          237 :   }
     739         2743 :   virtual bool op1_range (frange &r, tree type,
     740              :                           const frange &lhs, const frange &,
     741              :                           relation_trio) const final override
     742              :   {
     743         2743 :     if (lhs.undefined_p ())
     744              :       return false;
     745              : 
     746              :     // A known NAN means the input is [-INF,-INF][+INF,+INF] U +-NAN,
     747              :     // which we can't currently represent.
     748         2743 :     if (lhs.known_isnan ())
     749              :       {
     750            0 :         r.set_varying (type);
     751            0 :         return true;
     752              :       }
     753              : 
     754              :     // Results outside of [-1.0, +1.0] are impossible.
     755         2743 :     unsigned bulps
     756         2743 :       = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type), true);
     757         2743 :     if (bulps != ~0U)
     758              :       {
     759         2743 :         const REAL_VALUE_TYPE &lb = lhs.lower_bound ();
     760         2743 :         const REAL_VALUE_TYPE &ub = lhs.upper_bound ();
     761         2743 :         REAL_VALUE_TYPE m1 = dconstm1;
     762         2743 :         REAL_VALUE_TYPE p1 = dconst1;
     763         2743 :         while (bulps--)
     764              :           {
     765            0 :             frange_nextafter (TYPE_MODE (type), m1, dconstninf);
     766            0 :             frange_nextafter (TYPE_MODE (type), p1, dconstinf);
     767              :           }
     768         2743 :         if (real_less (&ub, &m1) || real_less (&p1, &lb))
     769              :           {
     770            0 :             if (!lhs.maybe_isnan ())
     771            0 :               r.set_undefined ();
     772              :             else
     773              :               /* If lhs could be NAN and finite result is impossible,
     774              :                  the range is like lhs.known_isnan () above,
     775              :                  [-INF,-INF][+INF,+INF] U +-NAN.  */
     776            0 :               r.set_varying (type);
     777            0 :             return true;
     778              :           }
     779              :       }
     780              : 
     781         3856 :     if (!lhs.maybe_isnan ())
     782              :       {
     783              :         // If NAN is not valid result, the input cannot include either
     784              :         // a NAN nor a +-INF.
     785         1113 :         REAL_VALUE_TYPE lb = real_min_representable (type);
     786         1113 :         REAL_VALUE_TYPE ub = real_max_representable (type);
     787         1113 :         r.set (type, lb, ub, nan_state (false, false));
     788              :       }
     789              :     else
     790         1630 :       r.set_varying (type);
     791              :     return true;
     792              :   }
     793              : private:
     794              :   combined_fn m_cfn;
     795              : } op_cfn_sin (CFN_SIN), op_cfn_cos (CFN_COS);
     796              : 
     797              : 
     798              : // FP functions which are nonnegative independent of the arguments.
     799              : class cfn_fp_nonnegative : public range_operator
     800              : {
     801              : public:
     802              :   using range_operator::fold_range;
     803        21572 :   virtual bool fold_range (frange &r, tree type,
     804              :                            const frange &, const frange &,
     805              :                            relation_trio) const final override
     806              :   {
     807        21572 :     r.set_nonnegative (type);
     808        21572 :     return true;
     809              :   }
     810              : } op_cfn_fp_nonegative;
     811              : 
     812              : // FP functions which are nonnegative if arg0 is nonnegative.
     813              : // Also handles pass through of if non-nan
     814              : class cfn_fp_nonnegative_arg0 : public range_operator
     815              : {
     816              : public:
     817              :   using range_operator::fold_range;
     818              :   cfn_fp_nonnegative_arg0(bool nan) : arg_nan (nan) {}
     819        40066 :   virtual bool fold_range (frange &r, tree type,
     820              :                            const frange &op1, const frange &,
     821              :                            relation_trio) const final override
     822              :   {
     823        40066 :     if (op1.undefined_p ())
     824              :       return false;
     825        40024 :     bool changed = false;
     826        40024 :     bool sign = false;
     827        40024 :     if (op1.signbit_p (sign) && !sign)
     828              :       {
     829         8683 :         r.set_nonnegative (type);
     830         8683 :         changed = true;
     831              :       }
     832        48630 :     if (arg_nan && !op1.maybe_isnan ())
     833              :       {
     834         8606 :         if (r.undefined_p ())
     835         5856 :           r.set_varying (type);
     836         8606 :         r.clear_nan ();
     837         8606 :         changed = true;
     838              :       }
     839              :     return changed;
     840              :   }
     841              : private:
     842              :   bool arg_nan;
     843              : } op_cfn_fp_nonegative_arg0(false), op_cfn_fp_nonegative_nan_arg0(true);
     844              : 
     845              : // Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER.
     846              : class cfn_toupper_tolower : public range_operator
     847              : {
     848              : public:
     849              :   using range_operator::fold_range;
     850              :   cfn_toupper_tolower (bool toupper)  { m_toupper = toupper; }
     851              :   virtual bool fold_range (irange &r, tree type, const irange &lh,
     852              :                            const irange &, relation_trio) const;
     853              : private:
     854              :   bool get_letter_range (tree type, irange &lowers, irange &uppers) const;
     855              :   bool m_toupper;
     856              : } op_cfn_toupper (true), op_cfn_tolower (false);
     857              : 
     858              : // Return TRUE if we recognize the target character set and return the
     859              : // range for lower case and upper case letters.
     860              : 
     861              : bool
     862          217 : cfn_toupper_tolower::get_letter_range (tree type, irange &lowers,
     863              :                                        irange &uppers) const
     864              : {
     865              :   // ASCII
     866          217 :   int a = lang_hooks.to_target_charset ('a');
     867          217 :   int z = lang_hooks.to_target_charset ('z');
     868          217 :   int A = lang_hooks.to_target_charset ('A');
     869          217 :   int Z = lang_hooks.to_target_charset ('Z');
     870              : 
     871          217 :   if ((z - a == 25) && (Z - A == 25))
     872              :     {
     873          217 :       lowers = int_range<2> (type,
     874          434 :                              wi::shwi (a, TYPE_PRECISION (type)),
     875          434 :                              wi::shwi (z, TYPE_PRECISION (type)));
     876          217 :       uppers = int_range<2> (type,
     877          434 :                              wi::shwi (A, TYPE_PRECISION (type)),
     878          434 :                              wi::shwi (Z, TYPE_PRECISION (type)));
     879          217 :       return true;
     880              :     }
     881              :   // Unknown character set.
     882              :   return false;
     883              : }
     884              : 
     885              : bool
     886          217 : cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh,
     887              :                                  const irange &, relation_trio) const
     888              : {
     889          217 :   int_range<3> lowers;
     890          217 :   int_range<3> uppers;
     891          217 :   if (!get_letter_range (type, lowers, uppers))
     892              :     return false;
     893              : 
     894          217 :   r = lh;
     895          217 :   if (m_toupper)
     896              :     {
     897              :       // Return the range passed in without any lower case characters,
     898              :       // but including all the upper case ones.
     899          117 :       bool res = lowers.invert ();
     900          117 :       gcc_checking_assert (res);
     901          117 :       r.intersect (lowers);
     902          117 :       r.union_ (uppers);
     903              :     }
     904              :   else
     905              :     {
     906              :       // Return the range passed in without any lower case characters,
     907              :       // but including all the upper case ones.
     908          100 :       bool res = uppers.invert ();
     909          100 :       gcc_checking_assert (res);
     910          100 :       r.intersect (uppers);
     911          100 :       r.union_ (lowers);
     912              :     }
     913              :   return true;
     914          217 : }
     915              : 
     916              : // Implement range operator for CFN_BUILT_IN_FFS.
     917              : class cfn_ffs : public range_operator
     918              : {
     919              : public:
     920              :   using range_operator::fold_range;
     921         6673 :   virtual bool fold_range (irange &r, tree type, const irange &lh,
     922              :                            const irange &, relation_trio) const
     923              :   {
     924         6673 :     if (lh.undefined_p ())
     925              :       return false;
     926              :     // __builtin_ffs* and __builtin_popcount* return [0, prec].
     927         6673 :     int prec = TYPE_PRECISION (lh.type ());
     928              :     // If arg is non-zero, then ffs or popcount are non-zero.
     929         6673 :     int mini = range_includes_zero_p (lh) ? 0 : 1;
     930         6673 :     int maxi = prec;
     931              : 
     932              :     // If some high bits are known to be zero, decrease the maximum.
     933         6673 :     int_range_max tmp = lh;
     934         6673 :     if (TYPE_SIGN (tmp.type ()) == SIGNED)
     935         1865 :       range_cast (tmp, unsigned_type_for (tmp.type ()));
     936         6673 :     wide_int max = tmp.upper_bound ();
     937         6673 :     maxi = wi::floor_log2 (max) + 1;
     938         6673 :     r.set (type,
     939        13346 :            wi::shwi (mini, TYPE_PRECISION (type)),
     940         6673 :            wi::shwi (maxi, TYPE_PRECISION (type)));
     941         6673 :     return true;
     942         6673 :   }
     943              : } op_cfn_ffs;
     944              : 
     945              : // Implement range operator for CFN_BUILT_IN_POPCOUNT.
     946              : class cfn_popcount : public cfn_ffs
     947              : {
     948              : public:
     949              :   using range_operator::fold_range;
     950         4753 :   virtual bool fold_range (irange &r, tree type, const irange &lh,
     951              :                            const irange &rh, relation_trio rel) const
     952              :   {
     953         4753 :     if (lh.undefined_p ())
     954              :       return false;
     955         4745 :     unsigned prec = TYPE_PRECISION (type);
     956         4745 :     irange_bitmask bm = lh.get_bitmask ();
     957         4745 :     wide_int nz = bm.get_nonzero_bits ();
     958         4745 :     wide_int high = wi::shwi (wi::popcount (nz), prec);
     959              :     // Calculating the popcount of a singleton is trivial.
     960         4745 :     if (lh.singleton_p ())
     961              :       {
     962            6 :         r.set (type, high, high);
     963            6 :         return true;
     964              :       }
     965         4739 :     if (cfn_ffs::fold_range (r, type, lh, rh, rel))
     966              :       {
     967         4739 :         wide_int known_ones = ~bm.mask () & bm.value ();
     968         4739 :         wide_int low = wi::shwi (wi::popcount (known_ones), prec);
     969         4739 :         int_range<2> tmp (type, low, high);
     970         4739 :         r.intersect (tmp);
     971         4739 :         return true;
     972         4739 :       }
     973              :     return false;
     974         4745 :   }
     975              : } op_cfn_popcount;
     976              : 
     977              : // Implement range operator for CFN_BUILT_IN_CLZ
     978              : class cfn_clz : public range_operator
     979              : {
     980              : public:
     981              :   cfn_clz (bool internal) { m_gimple_call_internal_p = internal; }
     982              :   using range_operator::fold_range;
     983              :   virtual bool fold_range (irange &r, tree type, const irange &lh,
     984              :                            const irange &rh, relation_trio) const;
     985              : private:
     986              :   bool m_gimple_call_internal_p;
     987              : } op_cfn_clz (false), op_cfn_clz_internal (true);
     988              : 
     989              : bool
     990       137666 : cfn_clz::fold_range (irange &r, tree type, const irange &lh,
     991              :                      const irange &rh, relation_trio) const
     992              : {
     993              :   // __builtin_c[lt]z* return [0, prec-1], except when the
     994              :   // argument is 0, but that is undefined behavior.
     995              :   //
     996              :   // For __builtin_c[lt]z* consider argument of 0 always undefined
     997              :   // behavior, for internal fns likewise, unless it has 2 arguments,
     998              :   // then the second argument is the value at zero.
     999       137666 :   if (lh.undefined_p ())
    1000              :     return false;
    1001       137580 :   int prec = TYPE_PRECISION (lh.type ());
    1002       137580 :   int mini = 0;
    1003       137580 :   int maxi = prec - 1;
    1004       137580 :   if (m_gimple_call_internal_p)
    1005              :     {
    1006              :       // Handle only the two common values.
    1007           75 :       if (rh.lower_bound () == -1)
    1008              :         mini = -1;
    1009           69 :       else if (rh.lower_bound () == prec)
    1010           69 :         maxi = prec;
    1011              :       else
    1012              :         // Magic value to give up, unless we can prove arg is non-zero.
    1013              :         mini = -2;
    1014              :     }
    1015              : 
    1016              :   // From clz of minimum we can compute result maximum.
    1017       137580 :   if (wi::gt_p (lh.lower_bound (), 0, TYPE_SIGN (lh.type ())))
    1018              :     {
    1019       120719 :       maxi = prec - 1 - wi::floor_log2 (lh.lower_bound ());
    1020       120719 :       if (mini < 0)
    1021              :         mini = 0;
    1022              :     }
    1023        16861 :   else if (!range_includes_zero_p (lh))
    1024              :     {
    1025              :       mini = 0;
    1026              :       maxi = prec - 1;
    1027              :     }
    1028        16860 :   if (mini == -2)
    1029              :     return false;
    1030              :   // From clz of maximum we can compute result minimum.
    1031       137580 :   wide_int max = lh.upper_bound ();
    1032       137580 :   int newmini = prec - 1 - wi::floor_log2 (max);
    1033       137580 :   if (max == 0)
    1034              :     {
    1035              :       // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec,
    1036              :       // return [prec, prec] or [-1, -1], otherwise ignore the range.
    1037           11 :       if (maxi == prec)
    1038              :         mini = prec;
    1039           11 :       else if (mini == -1)
    1040              :         maxi = -1;
    1041              :     }
    1042       137569 :   else if (mini >= 0)
    1043       137564 :     mini = newmini;
    1044              : 
    1045       137579 :   if (mini == -2)
    1046              :     return false;
    1047       137580 :   r.set (type,
    1048       275160 :          wi::shwi (mini, TYPE_PRECISION (type)),
    1049       137580 :          wi::shwi (maxi, TYPE_PRECISION (type)));
    1050       137580 :   return true;
    1051       137580 : }
    1052              : 
    1053              : // Implement range operator for CFN_BUILT_IN_CTZ
    1054              : class cfn_ctz : public range_operator
    1055              : {
    1056              : public:
    1057              :   cfn_ctz (bool internal) { m_gimple_call_internal_p = internal; }
    1058              :   using range_operator::fold_range;
    1059              :   virtual bool fold_range (irange &r, tree type, const irange &lh,
    1060              :                            const irange &rh, relation_trio) const;
    1061              : private:
    1062              :   bool m_gimple_call_internal_p;
    1063              : } op_cfn_ctz (false), op_cfn_ctz_internal (true);
    1064              : 
    1065              : bool
    1066        16630 : cfn_ctz::fold_range (irange &r, tree type, const irange &lh,
    1067              :                      const irange &rh, relation_trio) const
    1068              : {
    1069        16630 :   if (lh.undefined_p ())
    1070              :     return false;
    1071        16603 :   int prec = TYPE_PRECISION (lh.type ());
    1072        16603 :   int mini = 0;
    1073        16603 :   int maxi = prec - 1;
    1074              : 
    1075        16603 :   if (m_gimple_call_internal_p)
    1076              :     {
    1077              :       // Handle only the two common values.
    1078           91 :       if (rh.lower_bound () == -1)
    1079              :         mini = -1;
    1080           91 :       else if (rh.lower_bound () == prec)
    1081           91 :         maxi = prec;
    1082              :       else
    1083              :         // Magic value to give up, unless we can prove arg is non-zero.
    1084              :         mini = -2;
    1085              :     }
    1086              :   // If arg is non-zero, then use [0, prec - 1].
    1087        16603 :   if (!range_includes_zero_p (lh))
    1088              :     {
    1089        12131 :       mini = 0;
    1090        12131 :       maxi = prec - 1;
    1091              :     }
    1092              :   // If some high bits are known to be zero, we can decrease
    1093              :   // the maximum.
    1094        16603 :   wide_int max = lh.upper_bound ();
    1095        16603 :   if (max == 0)
    1096              :     {
    1097              :       // Argument is [0, 0].  If CTZ_DEFINED_VALUE_AT_ZERO
    1098              :       // is 2 with value -1 or prec, return [-1, -1] or [prec, prec].
    1099              :       // Otherwise ignore the range.
    1100            8 :       if (mini == -1)
    1101              :         maxi = -1;
    1102            8 :       else if (maxi == prec)
    1103        16603 :         mini = prec;
    1104              :     }
    1105              :   // If value at zero is prec and 0 is in the range, we can't lower
    1106              :   // the upper bound.  We could create two separate ranges though,
    1107              :   // [0,floor_log2(max)][prec,prec] though.
    1108        16595 :   else if (maxi != prec)
    1109        16504 :     maxi = wi::floor_log2 (max);
    1110              : 
    1111        16603 :   if (mini == -2)
    1112              :     return false;
    1113        16603 :   r.set (type,
    1114        33206 :          wi::shwi (mini, TYPE_PRECISION (type)),
    1115        16603 :          wi::shwi (maxi, TYPE_PRECISION (type)));
    1116        16603 :   return true;
    1117        16603 : }
    1118              : 
    1119              : 
    1120              : // Implement range operator for CFN_BUILT_IN_
    1121              : class cfn_clrsb : public range_operator
    1122              : {
    1123              : public:
    1124              :   using range_operator::fold_range;
    1125          804 :   virtual bool fold_range (irange &r, tree type, const irange &lh,
    1126              :                            const irange &, relation_trio) const
    1127              :   {
    1128          804 :     if (lh.undefined_p ())
    1129              :       return false;
    1130          804 :     int prec = TYPE_PRECISION (lh.type ());
    1131          804 :     r.set (type,
    1132         1608 :            wi::zero (TYPE_PRECISION (type)),
    1133          804 :            wi::shwi (prec - 1, TYPE_PRECISION (type)));
    1134          804 :     return true;
    1135              :   }
    1136              : } op_cfn_clrsb;
    1137              : 
    1138              : 
    1139              : // Implement range operator for CFN_BUILT_IN_
    1140              : class cfn_ubsan : public range_operator
    1141              : {
    1142              : public:
    1143              :   cfn_ubsan (enum tree_code code) { m_code = code; }
    1144              :   using range_operator::fold_range;
    1145        15425 :   virtual bool fold_range (irange &r, tree type, const irange &lh,
    1146              :                            const irange &rh, relation_trio rel) const
    1147              :   {
    1148        15425 :     bool saved_flag_wrapv = flag_wrapv;
    1149              :     // Pretend the arithmetic is wrapping.  If there is any overflow,
    1150              :     // we'll complain, but will actually do wrapping operation.
    1151        15425 :     flag_wrapv = 1;
    1152        15425 :     bool result = range_op_handler (m_code).fold_range (r, type, lh, rh, rel);
    1153        15425 :     flag_wrapv = saved_flag_wrapv;
    1154              : 
    1155              :     // If for both arguments vrp_valueize returned non-NULL, this should
    1156              :     // have been already folded and if not, it wasn't folded because of
    1157              :     // overflow.  Avoid removing the UBSAN_CHECK_* calls in that case.
    1158        15425 :     if (result && r.singleton_p ())
    1159          478 :       r.set_varying (type);
    1160        15425 :     return result;
    1161              :   }
    1162              : private:
    1163              :   enum tree_code m_code;
    1164              : };
    1165              : 
    1166              : cfn_ubsan op_cfn_ubsan_add (PLUS_EXPR);
    1167              : cfn_ubsan op_cfn_ubsan_sub (MINUS_EXPR);
    1168              : cfn_ubsan op_cfn_ubsan_mul (MULT_EXPR);
    1169              : 
    1170              : 
    1171              : // Implement range operator for CFN_BUILT_IN_STRLEN
    1172              : class cfn_strlen : public range_operator
    1173              : {
    1174              : public:
    1175              :   using range_operator::fold_range;
    1176       289995 :   virtual bool fold_range (irange &r, tree type, const prange &,
    1177              :                            const irange &, relation_trio) const
    1178              :   {
    1179       289995 :     wide_int max = irange_val_max (ptrdiff_type_node);
    1180              :     // To account for the terminating NULL, the maximum length
    1181              :     // is one less than the maximum array size, which in turn
    1182              :     // is one less than PTRDIFF_MAX (or SIZE_MAX where it's
    1183              :     // smaller than the former type).
    1184              :     // FIXME: Use max_object_size() - 1 here.
    1185       289995 :     r.set (type, wi::zero (TYPE_PRECISION (type)), max - 2);
    1186       289995 :     return true;
    1187       289995 :   }
    1188              : } op_cfn_strlen;
    1189              : 
    1190              : 
    1191              : // Implement range operator for CFN_BUILT_IN_GOACC_DIM
    1192              : class cfn_goacc_dim : public range_operator
    1193              : {
    1194              : public:
    1195              :   cfn_goacc_dim (bool is_pos) { m_is_pos = is_pos; }
    1196              :   using range_operator::fold_range;
    1197        12348 :   virtual bool fold_range (irange &r, tree type, const irange &lh,
    1198              :                            const irange &, relation_trio) const
    1199              :   {
    1200        12348 :     tree axis_tree;
    1201        12348 :     if (!lh.singleton_p (&axis_tree))
    1202              :       return false;
    1203        12348 :     HOST_WIDE_INT axis = TREE_INT_CST_LOW (axis_tree);
    1204        12348 :     int size = oacc_get_fn_dim_size (current_function_decl, axis);
    1205        12348 :     if (!size)
    1206              :       // If it's dynamic, the backend might know a hardware limitation.
    1207            0 :       size = targetm.goacc.dim_limit (axis);
    1208              : 
    1209        12348 :     r.set (type,
    1210        31826 :            wi::shwi (m_is_pos ? 0 : 1, TYPE_PRECISION (type)),
    1211              :            size
    1212        12348 :            ? wi::shwi (size - m_is_pos, TYPE_PRECISION (type))
    1213              :            : irange_val_max (type));
    1214        12348 :     return true;
    1215              :   }
    1216              : private:
    1217              :   bool m_is_pos;
    1218              : } op_cfn_goacc_dim_size (false), op_cfn_goacc_dim_pos (true);
    1219              : 
    1220              : // Implement range operator for CFN_BUILT_IN_ISINF
    1221              : class cfn_isinf : public range_operator
    1222              : {
    1223              : public:
    1224              :   using range_operator::fold_range;
    1225              :   using range_operator::op1_range;
    1226            0 :   virtual bool fold_range (irange &r, tree type, const frange &op1,
    1227              :                            const irange &, relation_trio) const override
    1228              :   {
    1229            0 :     if (op1.undefined_p ())
    1230              :       return false;
    1231              : 
    1232            0 :     if (op1.known_isinf ())
    1233              :       {
    1234            0 :         wide_int one = wi::one (TYPE_PRECISION (type));
    1235            0 :         r.set (type, one, one);
    1236            0 :         return true;
    1237            0 :       }
    1238              : 
    1239            0 :     if (op1.known_isnan ()
    1240            0 :         || (!real_isinf (&op1.lower_bound ())
    1241            0 :             && !real_isinf (&op1.upper_bound ())))
    1242              :       {
    1243            0 :         r.set_zero (type);
    1244            0 :         return true;
    1245              :       }
    1246              : 
    1247            0 :     r.set_varying (type);
    1248            0 :     return true;
    1249              :   }
    1250            0 :   virtual bool op1_range (frange &r, tree type, const irange &lhs,
    1251              :                           const frange &, relation_trio) const override
    1252              :   {
    1253            0 :     if (lhs.undefined_p ())
    1254              :       return false;
    1255              : 
    1256            0 :     if (lhs.zero_p ())
    1257              :       {
    1258            0 :         nan_state nan (true);
    1259            0 :         r.set (type, real_min_representable (type),
    1260            0 :                real_max_representable (type), nan);
    1261            0 :         return true;
    1262              :       }
    1263              : 
    1264            0 :     if (!range_includes_zero_p (lhs))
    1265              :       {
    1266              :         // The range is [-INF,-INF][+INF,+INF], but it can't be represented.
    1267              :         // Set range to [-INF,+INF]
    1268            0 :         r.set_varying (type);
    1269            0 :         r.clear_nan ();
    1270            0 :         return true;
    1271              :       }
    1272              : 
    1273            0 :     r.set_varying (type);
    1274            0 :     return true;
    1275              :   }
    1276              : } op_cfn_isinf;
    1277              : 
    1278              : //Implement range operator for CFN_BUILT_IN_ISFINITE
    1279              : class cfn_isfinite : public range_operator
    1280              : {
    1281              : public:
    1282              :   using range_operator::fold_range;
    1283              :   using range_operator::op1_range;
    1284            0 :   virtual bool fold_range (irange &r, tree type, const frange &op1,
    1285              :                            const irange &, relation_trio) const override
    1286              :   {
    1287            0 :     if (op1.undefined_p ())
    1288              :       return false;
    1289              : 
    1290            0 :     if (op1.known_isfinite ())
    1291              :       {
    1292            0 :         wide_int one = wi::one (TYPE_PRECISION (type));
    1293            0 :         r.set (type, one, one);
    1294            0 :         return true;
    1295            0 :       }
    1296              : 
    1297            0 :     if (op1.known_isnan ()
    1298            0 :         || op1.known_isinf ())
    1299              :       {
    1300            0 :         r.set_zero (type);
    1301            0 :         return true;
    1302              :       }
    1303              : 
    1304            0 :     r.set_varying (type);
    1305            0 :     return true;
    1306              :   }
    1307            0 :   virtual bool op1_range (frange &r, tree type, const irange &lhs,
    1308              :                           const frange &, relation_trio) const override
    1309              :   {
    1310            0 :     if (lhs.undefined_p ())
    1311              :       return false;
    1312              : 
    1313            0 :     if (lhs.zero_p ())
    1314              :       {
    1315              :         // The range is [-INF,-INF][+INF,+INF] NAN, but it can't be represented.
    1316              :         // Set range to varying
    1317            0 :         r.set_varying (type);
    1318            0 :         return true;
    1319              :       }
    1320              : 
    1321            0 :     if (!range_includes_zero_p (lhs))
    1322              :       {
    1323            0 :         nan_state nan (false);
    1324            0 :         r.set (type, real_min_representable (type),
    1325            0 :                real_max_representable (type), nan);
    1326            0 :         return true;
    1327              :       }
    1328              : 
    1329            0 :     r.set_varying (type);
    1330            0 :     return true;
    1331              :   }
    1332              : } op_cfn_isfinite;
    1333              : 
    1334              : //Implement range operator for CFN_BUILT_IN_ISNORMAL
    1335              : class cfn_isnormal :  public range_operator
    1336              : {
    1337              : public:
    1338              :   using range_operator::fold_range;
    1339              :   using range_operator::op1_range;
    1340            0 :   virtual bool fold_range (irange &r, tree type, const frange &op1,
    1341              :                            const irange &, relation_trio) const override
    1342              :   {
    1343            0 :     if (op1.undefined_p ())
    1344              :       return false;
    1345              : 
    1346            0 :     if (op1.known_isnormal ())
    1347              :       {
    1348            0 :         wide_int one = wi::one (TYPE_PRECISION (type));
    1349            0 :         r.set (type, one, one);
    1350            0 :         return true;
    1351            0 :       }
    1352              : 
    1353            0 :     if (op1.known_isnan ()
    1354            0 :         || op1.known_isinf ()
    1355            0 :         || op1.known_isdenormal_or_zero ())
    1356              :       {
    1357            0 :         r.set_zero (type);
    1358            0 :         return true;
    1359              :       }
    1360              : 
    1361            0 :     r.set_varying (type);
    1362            0 :     return true;
    1363              :   }
    1364            0 :   virtual bool op1_range (frange &r, tree type, const irange &lhs,
    1365              :                           const frange &, relation_trio) const override
    1366              :   {
    1367            0 :     if (lhs.undefined_p ())
    1368              :       return false;
    1369              : 
    1370            0 :     if (lhs.zero_p ())
    1371              :       {
    1372            0 :         r.set_varying (type);
    1373            0 :         return true;
    1374              :       }
    1375              : 
    1376            0 :     if (!range_includes_zero_p (lhs))
    1377              :       {
    1378            0 :         nan_state nan (false);
    1379            0 :         r.set (type, real_min_representable (type),
    1380            0 :                real_max_representable (type), nan);
    1381            0 :         return true;
    1382              :       }
    1383              : 
    1384            0 :     r.set_varying (type);
    1385            0 :     return true;
    1386              :   }
    1387              : } op_cfn_isnormal;
    1388              : 
    1389              : // Implement range operator for CFN_BUILT_IN_
    1390              : class cfn_parity : public range_operator
    1391              : {
    1392              : public:
    1393              :   using range_operator::fold_range;
    1394         1169 :   virtual bool fold_range (irange &r, tree type, const irange &,
    1395              :                            const irange &, relation_trio) const
    1396              :   {
    1397         1169 :     r = range_true_and_false (type);
    1398         1169 :     return true;
    1399              :   }
    1400              : } op_cfn_parity;
    1401              : 
    1402              : // Set up a gimple_range_op_handler for any nonstandard function which can be
    1403              : // supported via range-ops.
    1404              : 
    1405              : void
    1406    785040803 : gimple_range_op_handler::maybe_non_standard ()
    1407              : {
    1408    785040803 :   range_op_handler signed_op (OP_WIDEN_MULT_SIGNED);
    1409    785040803 :   gcc_checking_assert (signed_op);
    1410    785040803 :   range_op_handler unsigned_op (OP_WIDEN_MULT_UNSIGNED);
    1411    785040803 :   gcc_checking_assert (unsigned_op);
    1412    785040803 :   range_op_handler signed_unsigned_op (OP_WIDEN_MULT_SIGNED_UNSIGNED);
    1413    785040803 :   gcc_checking_assert (signed_unsigned_op);
    1414    785040803 :   bool signed1, signed2;
    1415              : 
    1416    785040803 :   if (gimple_code (m_stmt) == GIMPLE_ASSIGN)
    1417    254084339 :     switch (gimple_assign_rhs_code (m_stmt))
    1418              :       {
    1419        22474 :         case WIDEN_MULT_EXPR:
    1420        22474 :           m_op1 = gimple_assign_rhs1 (m_stmt);
    1421        22474 :           m_op2 = gimple_assign_rhs2 (m_stmt);
    1422        22474 :           signed1 = TYPE_SIGN (TREE_TYPE (m_op1)) == SIGNED;
    1423        22474 :           signed2 = TYPE_SIGN (TREE_TYPE (m_op2)) == SIGNED;
    1424              : 
    1425        22474 :           if (signed1 != signed2)
    1426              :             {
    1427            0 :               if (signed2 && !signed1)
    1428            0 :                 std::swap (m_op1, m_op2);
    1429            0 :               m_operator = signed_unsigned_op.range_op ();
    1430              :             }
    1431        22474 :           else if (signed1)
    1432         2059 :             m_operator = signed_op.range_op ();
    1433              :           else
    1434        20415 :             m_operator = unsigned_op.range_op ();
    1435              :           break;
    1436              : 
    1437              :         default:
    1438              :           break;
    1439              :       }
    1440    785040803 : }
    1441              : 
    1442              : // Set up a gimple_range_op_handler for any built in function which can be
    1443              : // supported via range-ops.
    1444              : 
    1445              : void
    1446     75645517 : gimple_range_op_handler::maybe_builtin_call ()
    1447              : {
    1448     75645517 :   gcc_checking_assert (is_a <gcall *> (m_stmt));
    1449              : 
    1450     75645517 :   gcall *call = as_a <gcall *> (m_stmt);
    1451     75645517 :   combined_fn func = gimple_call_combined_fn (call);
    1452     75645517 :   if (func == CFN_LAST)
    1453              :     return;
    1454     33831149 :   tree type = gimple_range_type (call);
    1455     33831149 :   if (!type)
    1456              :     return;
    1457     33831149 :   if (!value_range::supports_type_p (type))
    1458              :     return;
    1459              : 
    1460     33831149 :   switch (func)
    1461              :     {
    1462       890648 :     case CFN_BUILT_IN_CONSTANT_P:
    1463       890648 :       if (gimple_call_num_args (call) != 1)
    1464              :         return;
    1465       890618 :       m_op1 = gimple_call_arg (call, 0);
    1466       890618 :       if (irange::supports_p (TREE_TYPE (m_op1)))
    1467       734235 :         m_operator = &op_cfn_constant_p;
    1468       156383 :       else if (frange::supports_p (TREE_TYPE (m_op1)))
    1469         1134 :         m_operator = &op_cfn_constant_float_p;
    1470              :       // builtin_constant_p should not be recomputed.  See PR 123205.
    1471       890618 :       m_recomputable = false;
    1472       890618 :       break;
    1473              : 
    1474       194496 :     CASE_FLT_FN (CFN_BUILT_IN_SIGNBIT):
    1475       194496 :       if (gimple_call_num_args (call) != 1)
    1476              :         return;
    1477       194496 :       m_op1 = gimple_call_arg (call, 0);
    1478       194496 :       m_operator = &op_cfn_signbit;
    1479       194496 :       break;
    1480              : 
    1481            0 :     CASE_FLT_FN (CFN_BUILT_IN_ISINF):
    1482            0 :       if (gimple_call_num_args (call) != 1)
    1483              :         return;
    1484            0 :       m_op1 = gimple_call_arg (call, 0);
    1485            0 :       m_operator = &op_cfn_isinf;
    1486            0 :       break;
    1487              : 
    1488            0 :     case CFN_BUILT_IN_ISFINITE:
    1489            0 :       if (gimple_call_num_args (call) != 1)
    1490              :         return;
    1491            0 :       m_op1 = gimple_call_arg (call, 0);
    1492            0 :       m_operator = &op_cfn_isfinite;
    1493            0 :       break;
    1494              : 
    1495            0 :     case CFN_BUILT_IN_ISNORMAL:
    1496            0 :       if (gimple_call_num_args (call) != 1)
    1497              :         return;
    1498            0 :       m_op1 = gimple_call_arg (call, 0);
    1499            0 :       m_operator = &op_cfn_isnormal;
    1500            0 :       break;
    1501              : 
    1502      1154309 :     CASE_CFN_COPYSIGN_ALL:
    1503      1154309 :       m_op1 = gimple_call_arg (call, 0);
    1504      1154309 :       m_op2 = gimple_call_arg (call, 1);
    1505      1154309 :       m_operator = &op_cfn_copysign;
    1506      1154309 :       break;
    1507              : 
    1508       172163 :     CASE_CFN_SQRT:
    1509       172163 :     CASE_CFN_SQRT_FN:
    1510       172163 :       m_op1 = gimple_call_arg (call, 0);
    1511       172163 :       m_operator = &op_cfn_sqrt;
    1512       172163 :       break;
    1513              : 
    1514        42091 :     CASE_CFN_SIN:
    1515        42091 :     CASE_CFN_SIN_FN:
    1516        42091 :       m_op1 = gimple_call_arg (call, 0);
    1517        42091 :       m_operator = &op_cfn_sin;
    1518        42091 :       break;
    1519              : 
    1520        23074 :     CASE_CFN_COS:
    1521        23074 :     CASE_CFN_COS_FN:
    1522        23074 :       m_op1 = gimple_call_arg (call, 0);
    1523        23074 :       m_operator = &op_cfn_cos;
    1524        23074 :       break;
    1525              : 
    1526          861 :     case CFN_BUILT_IN_TOUPPER:
    1527          861 :     case CFN_BUILT_IN_TOLOWER:
    1528              :       // Only proceed If the argument is compatible with the LHS.
    1529          861 :       m_op1 = gimple_call_arg (call, 0);
    1530          861 :       if (range_compatible_p (type, TREE_TYPE (m_op1)))
    1531         1402 :         m_operator = (func == CFN_BUILT_IN_TOLOWER) ? &op_cfn_tolower
    1532              :                                                     : &op_cfn_toupper;
    1533              :       break;
    1534              : 
    1535         9959 :     CASE_CFN_FFS:
    1536         9959 :       m_op1 = gimple_call_arg (call, 0);
    1537         9959 :       m_operator = &op_cfn_ffs;
    1538         9959 :       break;
    1539              : 
    1540        25625 :     CASE_CFN_POPCOUNT:
    1541        25625 :       m_op1 = gimple_call_arg (call, 0);
    1542        25625 :       m_operator = &op_cfn_popcount;
    1543        25625 :       break;
    1544              : 
    1545      1025190 :     CASE_CFN_CLZ:
    1546      1025190 :       m_op1 = gimple_call_arg (call, 0);
    1547      1025190 :       if (gimple_call_internal_p (call)
    1548      1025190 :           && gimple_call_num_args (call) == 2)
    1549              :         {
    1550          380 :           m_op2 = gimple_call_arg (call, 1);
    1551          380 :           m_operator = &op_cfn_clz_internal;
    1552              :         }
    1553              :       else
    1554      1024810 :         m_operator = &op_cfn_clz;
    1555              :       break;
    1556              : 
    1557        97899 :     CASE_CFN_CTZ:
    1558        97899 :       m_op1 = gimple_call_arg (call, 0);
    1559        97899 :       if (gimple_call_internal_p (call)
    1560        97899 :           && gimple_call_num_args (call) == 2)
    1561              :         {
    1562          527 :           m_op2 = gimple_call_arg (call, 1);
    1563          527 :           m_operator = &op_cfn_ctz_internal;
    1564              :         }
    1565              :       else
    1566        97372 :         m_operator = &op_cfn_ctz;
    1567              :       break;
    1568              : 
    1569         5388 :     CASE_CFN_CLRSB:
    1570         5388 :       m_op1 = gimple_call_arg (call, 0);
    1571         5388 :       m_operator = &op_cfn_clrsb;
    1572         5388 :       break;
    1573              : 
    1574        28379 :     case CFN_UBSAN_CHECK_ADD:
    1575        28379 :       m_op1 = gimple_call_arg (call, 0);
    1576        28379 :       m_op2 = gimple_call_arg (call, 1);
    1577        28379 :       m_operator = &op_cfn_ubsan_add;
    1578        28379 :       break;
    1579              : 
    1580        25618 :     case CFN_UBSAN_CHECK_SUB:
    1581        25618 :       m_op1 = gimple_call_arg (call, 0);
    1582        25618 :       m_op2 = gimple_call_arg (call, 1);
    1583        25618 :       m_operator = &op_cfn_ubsan_sub;
    1584        25618 :       break;
    1585              : 
    1586        22220 :     case CFN_UBSAN_CHECK_MUL:
    1587        22220 :       m_op1 = gimple_call_arg (call, 0);
    1588        22220 :       m_op2 = gimple_call_arg (call, 1);
    1589        22220 :       m_operator = &op_cfn_ubsan_mul;
    1590        22220 :       break;
    1591              : 
    1592      1849668 :     case CFN_BUILT_IN_STRLEN:
    1593      1849668 :       {
    1594      1849668 :         tree lhs = gimple_call_lhs (call);
    1595      1849668 :         if (lhs && ptrdiff_type_node && (TYPE_PRECISION (ptrdiff_type_node)
    1596      1849668 :                                          == TYPE_PRECISION (TREE_TYPE (lhs))))
    1597              :           {
    1598      1849668 :             m_op1 = gimple_call_arg (call, 0);
    1599      1849668 :             m_operator = &op_cfn_strlen;
    1600              :           }
    1601              :         break;
    1602              :       }
    1603              : 
    1604              :     // Optimizing these two internal functions helps the loop
    1605              :     // optimizer eliminate outer comparisons.  Size is [1,N]
    1606              :     // and pos is [0,N-1].
    1607        29662 :     case CFN_GOACC_DIM_SIZE:
    1608              :       // This call will ensure all the asserts are triggered.
    1609        29662 :       oacc_get_ifn_dim_arg (call);
    1610        29662 :       m_op1 = gimple_call_arg (call, 0);
    1611        29662 :       m_operator = &op_cfn_goacc_dim_size;
    1612        29662 :       break;
    1613              : 
    1614        43718 :     case CFN_GOACC_DIM_POS:
    1615              :       // This call will ensure all the asserts are triggered.
    1616        43718 :       oacc_get_ifn_dim_arg (call);
    1617        43718 :       m_op1 = gimple_call_arg (call, 0);
    1618        43718 :       m_operator = &op_cfn_goacc_dim_pos;
    1619        43718 :       break;
    1620              : 
    1621         6697 :     CASE_CFN_PARITY:
    1622         6697 :       m_operator = &op_cfn_parity;
    1623         6697 :       break;
    1624              : 
    1625       126807 :     CASE_CFN_ACOS:
    1626       126807 :     CASE_CFN_ACOS_FN:
    1627       126807 :     CASE_CFN_ACOSH:
    1628       126807 :     CASE_CFN_ACOSH_FN:
    1629       126807 :     CASE_CFN_ACOSPI:
    1630       126807 :     CASE_CFN_ACOSPI_FN:
    1631       126807 :     CASE_CFN_CABS:
    1632       126807 :     CASE_CFN_CABS_FN:
    1633       126807 :     CASE_CFN_COSH:
    1634       126807 :     CASE_CFN_COSH_FN:
    1635       126807 :     CASE_CFN_ERFC:
    1636       126807 :     CASE_CFN_ERFC_FN:
    1637       126807 :     CASE_CFN_EXP:
    1638       126807 :     CASE_CFN_EXP_FN:
    1639       126807 :     CASE_CFN_EXP10:
    1640       126807 :     CASE_CFN_EXP2:
    1641       126807 :     CASE_CFN_EXP2_FN:
    1642       126807 :     CASE_CFN_FABS:
    1643       126807 :     CASE_CFN_FABS_FN:
    1644       126807 :     CASE_CFN_FDIM:
    1645       126807 :     CASE_CFN_FDIM_FN:
    1646       126807 :     CASE_CFN_HYPOT:
    1647       126807 :     CASE_CFN_HYPOT_FN:
    1648       126807 :     CASE_CFN_POW10:
    1649       126807 :       m_operator = &op_cfn_fp_nonegative;
    1650       126807 :       break;
    1651              : 
    1652              :     // FIXME: some of these can do better than just nonnegative.
    1653        88373 :     CASE_CFN_ASINH:
    1654        88373 :     CASE_CFN_ASINH_FN:
    1655        88373 :     CASE_CFN_ASINPI:
    1656        88373 :     CASE_CFN_ASINPI_FN:
    1657        88373 :     CASE_CFN_ATAN:
    1658        88373 :     CASE_CFN_ATAN_FN:
    1659        88373 :     CASE_CFN_ATANH:
    1660        88373 :     CASE_CFN_ATANH_FN:
    1661        88373 :     CASE_CFN_ATANPI:
    1662        88373 :     CASE_CFN_ATANPI_FN:
    1663        88373 :     CASE_CFN_CBRT:
    1664        88373 :     CASE_CFN_CBRT_FN:
    1665        88373 :     CASE_CFN_ERF:
    1666        88373 :     CASE_CFN_ERF_FN:
    1667        88373 :     CASE_CFN_EXPM1:
    1668        88373 :     CASE_CFN_EXPM1_FN:
    1669        88373 :     CASE_CFN_FMOD:
    1670        88373 :     CASE_CFN_FMOD_FN:
    1671        88373 :     CASE_CFN_FREXP:
    1672        88373 :     CASE_CFN_FREXP_FN:
    1673        88373 :     CASE_CFN_MODF:
    1674        88373 :     CASE_CFN_MODF_FN:
    1675        88373 :     CASE_CFN_SCALB:
    1676        88373 :     CASE_CFN_SCALBLN:
    1677        88373 :     CASE_CFN_SCALBLN_FN:
    1678        88373 :     CASE_CFN_SCALBN:
    1679        88373 :     CASE_CFN_SCALBN_FN:
    1680        88373 :     CASE_CFN_SIGNIFICAND:
    1681        88373 :     CASE_CFN_SINH:
    1682        88373 :     CASE_CFN_SINH_FN:
    1683        88373 :     CASE_CFN_TANH:
    1684        88373 :     CASE_CFN_TANH_FN:
    1685        88373 :     CASE_CFN_LDEXP:
    1686        88373 :       m_operator = &op_cfn_fp_nonegative_arg0;
    1687        88373 :       m_op1 = gimple_call_arg (call, 0);
    1688        88373 :       break;
    1689              : 
    1690              : 
    1691              :     // FIXME: these can be improved for the rounding builtins.
    1692              :     // Currently just sets non-negative and update nan.
    1693       105939 :     CASE_CFN_FLOOR:
    1694       105939 :     CASE_CFN_FLOOR_FN:
    1695       105939 :     CASE_CFN_CEIL:
    1696       105939 :     CASE_CFN_CEIL_FN:
    1697       105939 :     CASE_CFN_NEARBYINT:
    1698       105939 :     CASE_CFN_NEARBYINT_FN:
    1699       105939 :     CASE_CFN_RINT:
    1700       105939 :     CASE_CFN_RINT_FN:
    1701       105939 :     CASE_CFN_ROUND:
    1702       105939 :     CASE_CFN_ROUND_FN:
    1703       105939 :     CASE_CFN_ROUNDEVEN:
    1704       105939 :     CASE_CFN_ROUNDEVEN_FN:
    1705       105939 :     CASE_CFN_TRUNC:
    1706       105939 :     CASE_CFN_TRUNC_FN:
    1707       105939 :       m_operator = &op_cfn_fp_nonegative_nan_arg0;
    1708       105939 :       m_op1 = gimple_call_arg (call, 0);
    1709       105939 :       break;
    1710              : 
    1711     27862365 :     default:
    1712     27862365 :       {
    1713     27862365 :         unsigned arg;
    1714     27862365 :         if (gimple_call_fnspec (call).returns_arg (&arg)
    1715      1661300 :             && arg == 0
    1716      1661300 :             && gimple_call_num_args (call) > 0)
    1717              :           {
    1718      1661300 :             m_op1 = gimple_call_arg (call, 0);
    1719      1661300 :             m_operator = &op_cfn_pass_through_arg1;
    1720              :           }
    1721              :         break;
    1722              :       }
    1723              :     }
    1724              : }
        

Generated by: LCOV version 2.5.0-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.