LCOV - code coverage report
Current view: top level - gcc - value-query.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.1 % 267 230
Test Date: 2026-09-19 16:22:48 Functions: 80.0 % 30 24
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Support routines for value queries.
       2              :    Copyright (C) 2020-2026 Free Software Foundation, Inc.
       3              :    Contributed by Aldy Hernandez <aldyh@redhat.com> and
       4              :    Andrew MacLeod <amacleod@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 "tree.h"
      27              : #include "gimple.h"
      28              : #include "ssa.h"
      29              : #include "tree-ssanames.h"
      30              : #include "fold-const.h"
      31              : #include "value-query.h"
      32              : #include "alloc-pool.h"
      33              : #include "gimple-range.h"
      34              : #include "value-range-storage.h"
      35              : #include "target.h"
      36              : 
      37              : // Attempt to make Q the current range query for FUN.  If it is already the
      38              : // current range query, return NULL.
      39              : // If the specified query is not compatible with being the current query,
      40              : // instead push the global query for safety.  This is most common when
      41              : // the requested query is a path ranger, and it can be unstable to make
      42              : // arbitrary queries which may be in the middle or after a path.
      43              : 
      44              : range_query *
      45    430679043 : set_range_query (struct function *fun, range_query *q)
      46              : {
      47              :   // Set the global query if it hasn't been set.
      48    430679043 :   if (!fun->x_range_query)
      49      3169115 :     fun->x_range_query = get_global_range_query ();
      50              : 
      51              :   // If this is not a compatible range query, revert to the global query.
      52    430679043 :   if (!q->active_query_compatible_p ())
      53     94898661 :     q = get_global_range_query ();
      54              : 
      55    430679043 :   if (q == fun->x_range_query)
      56              :     return NULL;
      57              : 
      58    200190556 :   range_query *orig = fun->x_range_query;
      59    200190556 :   fun->x_range_query = q;
      60    200190556 :   return orig;
      61              : }
      62              : 
      63              : // range_query default methods.
      64              : 
      65              : bool
      66     16579742 : range_query::range_on_edge (vrange &r, edge, tree expr)
      67              : {
      68     16579742 :   return range_of_expr (r, expr);
      69              : }
      70              : 
      71              : bool
      72            0 : range_query::range_on_entry (vrange &r, basic_block, tree expr)
      73              : {
      74            0 :   return range_of_expr (r, expr);
      75              : }
      76              : 
      77              : bool
      78            0 : range_query::range_on_exit (vrange &r, basic_block, tree expr)
      79              : {
      80            0 :   return range_of_expr (r, expr);
      81              : }
      82              : 
      83              : bool
      84      1510761 : range_query::range_of_stmt (vrange &r, gimple *stmt, tree name)
      85              : {
      86      1510761 :   if (!name)
      87      1510761 :     name = gimple_get_lhs (stmt);
      88              : 
      89      1510761 :   gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
      90              : 
      91      1510761 :   if (name)
      92      1510761 :     return range_of_expr (r, name);
      93              :   return false;
      94              : }
      95              : 
      96              : // Default for updating range info is to do nothing.
      97              : void
      98    124441484 : range_query::update_range_info (tree)
      99              : {
     100    124441484 : }
     101              : 
     102              : // Default for updating range info is to do nothing.
     103              : void
     104      4323814 : range_query::update_range_info (tree, const vrange &)
     105              : {
     106      4323814 : }
     107              : 
     108              : // Default for resetting range info for NAME is to clear the oracles.
     109              : 
     110              : void
     111      8076662 : range_query::reset_range_info (tree name)
     112              : {
     113      8076662 :   relation ().clear (name);
     114      8076662 :   if (gori_ssa ())
     115          440 :     gori_ssa ()->clear (name);
     116      8076662 :   infer_oracle ().clear (name);
     117      8076662 : }
     118              : 
     119              : // If the range of expr EXPR at STMT is a single value, return it.
     120              : // Otherwise return NULL_TREE.
     121              : 
     122              : tree
     123     92083975 : range_query::value_of_expr (tree expr, gimple *stmt)
     124              : {
     125     92083975 :   tree t;
     126              : 
     127     92083975 :   if (!value_range::supports_type_p (TREE_TYPE (expr)))
     128              :     return NULL_TREE;
     129              : 
     130     92080880 :   value_range r (TREE_TYPE (expr));
     131              : 
     132     92080880 :   if (range_of_expr (r, expr, stmt))
     133              :     {
     134              :       // A constant used in an unreachable block often returns as UNDEFINED.
     135              :       // If the result is undefined, check the global value for a constant.
     136     92080880 :       if (r.undefined_p ())
     137        25790 :         range_of_expr (r, expr);
     138     92080880 :       if (r.singleton_p (&t))
     139      4082756 :         return t;
     140              :     }
     141              :   return NULL_TREE;
     142     92080880 : }
     143              : 
     144              : // If the range on edge E for EXPR is a single value, return it.
     145              : // Otherwise return NULL_TREE.
     146              : 
     147              : tree
     148           27 : range_query::value_on_edge (edge e, tree expr)
     149              : {
     150           27 :   tree t;
     151              : 
     152           27 :   if (!value_range::supports_type_p (TREE_TYPE (expr)))
     153              :     return NULL_TREE;
     154           27 :   value_range r (TREE_TYPE (expr));
     155           27 :   if (range_on_edge (r, e, expr))
     156              :     {
     157              :       // A constant used in an unreachable block often returns as UNDEFINED.
     158              :       // If the result is undefined, check the global value for a constant.
     159           27 :       if (r.undefined_p ())
     160            0 :         range_of_expr (r, expr);
     161           27 :       if (r.singleton_p (&t))
     162            3 :         return t;
     163              :     }
     164              :   return NULL_TREE;
     165           27 : }
     166              : 
     167              : // If the range of STMT for NAME is a single value, return it.
     168              : // Otherwise return NULL_TREE.
     169              : 
     170              : tree
     171     49016031 : range_query::value_of_stmt (gimple *stmt, tree name)
     172              : {
     173     49016031 :   tree t;
     174              : 
     175     49016031 :   if (!name)
     176            0 :     name = gimple_get_lhs (stmt);
     177              : 
     178     49016031 :   gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
     179              : 
     180     49016031 :   if (!name || !value_range::supports_type_p (TREE_TYPE (name)))
     181              :     return NULL_TREE;
     182     47180606 :   value_range r (TREE_TYPE (name));
     183     94361212 :   if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
     184       303556 :     return t;
     185              :   return NULL_TREE;
     186     47180606 : }
     187              : 
     188              : // If the range on entry to BB for EXPR is a single value, return it.
     189              : // Otherwise return NULL_TREE.
     190              : 
     191              : tree
     192            0 : range_query::value_on_entry (basic_block bb, tree expr)
     193              : {
     194            0 :   tree t;
     195              : 
     196            0 :   gcc_checking_assert (bb);
     197            0 :   if (!value_range::supports_type_p (TREE_TYPE (expr)))
     198              :     return NULL_TREE;
     199              : 
     200            0 :   value_range r (TREE_TYPE (expr));
     201              : 
     202            0 :   if (range_on_entry (r, bb, expr) && r.singleton_p (&t))
     203            0 :     return t;
     204              :   return NULL_TREE;
     205            0 : }
     206              : 
     207              : // If the range on exit to BB for EXPR is a single value, return it.
     208              : // Otherwise return NULL_TREE.
     209              : 
     210              : tree
     211            0 : range_query::value_on_exit (basic_block bb, tree expr)
     212              : {
     213            0 :   tree t;
     214              : 
     215            0 :   gcc_checking_assert (bb);
     216            0 :   if (!value_range::supports_type_p (TREE_TYPE (expr)))
     217              :     return NULL_TREE;
     218              : 
     219            0 :   value_range r (TREE_TYPE (expr));
     220              : 
     221            0 :   if (range_on_exit (r, bb, expr) && r.singleton_p (&t))
     222            0 :     return t;
     223              :   return NULL_TREE;
     224            0 : }
     225              : 
     226              : void
     227            0 : range_query::dump (FILE *)
     228              : {
     229            0 : }
     230              : 
     231              : // Default oracle for all range queries.  This contains no storage and thus
     232              : // can be used anywhere.
     233              : relation_oracle default_relation_oracle;
     234              : infer_range_oracle default_infer_oracle;
     235              : gimple_outgoing_range default_gori;
     236              : 
     237              : void
     238     29449302 : range_query::create_gori (int not_executable_flag, int sw_max_edges)
     239              : {
     240     29449302 :   gcc_checking_assert (m_gori == &default_gori);
     241     29449302 :   gcc_checking_assert (m_map == NULL);
     242     29449302 :   m_map = new gori_map ();
     243     29449302 :   gcc_checking_assert (m_map);
     244     29449302 :   m_gori = new gori_compute (*m_map, not_executable_flag, sw_max_edges);
     245     29449302 :   gcc_checking_assert (m_gori);
     246     29449302 : }
     247              : 
     248              : void
     249     81109419 : range_query::destroy_gori ()
     250              : {
     251     81109419 :   if (m_gori && m_gori != &default_gori)
     252     29449302 :     delete m_gori;
     253     81109419 :   if (m_map)
     254     29449302 :     delete m_map;
     255     81109419 :   m_map = NULL;
     256     81109419 :   m_gori= &default_gori;
     257     81109419 : }
     258              : 
     259              : // Create an infer oracle using Q as the default range query if needed.
     260              : // if DO_SEARCH is true, use immediate uses to scan alluses of a NAME the first
     261              : // time it is queried.  This is primarily for passes which operate in the
     262              : // on-demand model where earlier uses may not have been seen.
     263              : // VRP and DOM walk passes set this to FALSE as they will walk all statements
     264              : // in order.
     265              : void
     266     29449302 : range_query::create_infer_oracle (range_query *q, bool do_search)
     267              : {
     268     29449302 :   gcc_checking_assert (m_infer == &default_infer_oracle);
     269     29449302 :   m_infer = new infer_range_manager (do_search, q);
     270     29449302 :   gcc_checking_assert (m_infer);
     271     29449302 : }
     272              : 
     273              : void
     274    110558721 : range_query::destroy_infer_oracle ()
     275              : {
     276    110558721 :   if (m_infer && m_infer != &default_infer_oracle)
     277     29449302 :     delete m_infer;
     278    110558721 :   m_infer = &default_infer_oracle;
     279    110558721 : }
     280              : 
     281              : // Create dominance based range oracle for the current query if dom info is
     282              : // available.  DO_TRANS_P indicates whether transitive relations should
     283              : // be created.  This can cost more in compile time.
     284              : 
     285              : void
     286     29449311 : range_query::create_relation_oracle (bool do_trans_p)
     287              : {
     288     29449311 :   gcc_checking_assert (this != &global_ranges);
     289     29449311 :   gcc_checking_assert (m_relation == &default_relation_oracle);
     290              : 
     291     29449311 :   if (!dom_info_available_p (CDI_DOMINATORS))
     292              :     return;
     293     27398343 :   m_relation = new dom_oracle (do_trans_p);
     294     27398343 :   gcc_checking_assert (m_relation);
     295              : }
     296              : 
     297              : // Destroy any relation oracle that was created.
     298              : 
     299              : void
     300    110558721 : range_query::destroy_relation_oracle ()
     301              : {
     302              :   // m_relation can be NULL if a derived range_query class took care of
     303              :   // disposing its own oracle.
     304    110558721 :   if (m_relation && m_relation != &default_relation_oracle)
     305              :     {
     306     27398343 :       delete m_relation;
     307     27398343 :       m_relation = &default_relation_oracle;
     308              :     }
     309    110558721 : }
     310              : 
     311              : void
     312     38860590 : range_query::share_query (range_query &q)
     313              : {
     314     38860590 :   m_relation = q.m_relation;
     315     38860590 :   m_infer = q.m_infer;
     316     38860590 :   m_gori = q.m_gori;
     317     38860590 :   m_map = q.m_map;
     318     38860590 :   m_shared_copy_p = true;
     319     38860590 : }
     320              : 
     321    119970021 : range_query::range_query ()
     322              : {
     323    119970021 :   m_relation = &default_relation_oracle;
     324    119970021 :   m_infer = &default_infer_oracle;
     325    119970021 :   m_gori = &default_gori;
     326    119970021 :   m_map = NULL;
     327    119970021 :   m_shared_copy_p = false;
     328    119970021 : }
     329              : 
     330    119970009 : range_query::~range_query ()
     331              : {
     332              :   // Do not destroy anything if this is a shared copy.
     333    119970009 :   if (m_shared_copy_p)
     334              :     return;
     335     81109419 :   destroy_gori ();
     336     81109419 :   destroy_infer_oracle ();
     337     81109419 :   destroy_relation_oracle ();
     338            0 : }
     339              : 
     340              : // This routine will invoke the equivalent of range_of_expr on
     341              : // either a gimple statement STMT, on entry to block BBENTRY, or on
     342              : // exit from block BBEXIT.   Only one of these 3 fields may be set.
     343              : // It is valid for none of them to be set, in wqhich case there is no context.
     344              : 
     345              : bool
     346     30593835 : range_query::invoke_range_of_expr (vrange &r, tree expr, gimple *stmt,
     347              :                                    basic_block bbentry, basic_block bbexit,
     348              :                                    edge e)
     349              : {
     350     30593835 :   if (bbentry)
     351              :     {
     352            0 :       gcc_checking_assert (!stmt && !bbexit && !e);
     353            0 :       return range_on_entry (r, bbentry, expr);
     354              :     }
     355     30593835 :   if (bbexit)
     356              :     {
     357            0 :       gcc_checking_assert (!stmt && !e);
     358            0 :       return range_on_exit (r, bbexit, expr);
     359              :     }
     360     30593835 :   if (e)
     361              :     {
     362      2666427 :       gcc_checking_assert (!stmt);
     363      2666427 :       return range_on_edge (r, e, expr);
     364              :     }
     365              : 
     366     27927408 :   return range_of_expr (r, expr, stmt);
     367              : }
     368              : 
     369              : // Return a range in R for the tree EXPR.  The context can be either a STMT,
     370              : // or on entry to block BBENTRY or exit from block BBEXIT.
     371              : // Return true if a range is representable, and UNDEFINED/false if not.
     372              : 
     373              : bool
     374    316427059 : range_query::get_tree_range (vrange &r, tree expr, gimple *stmt,
     375              :                              basic_block bbentry, basic_block bbexit, edge e)
     376              : {
     377    316427059 :   tree type;
     378    316427059 :   if (TYPE_P (expr))
     379              :     type = expr;
     380              :   else
     381    316427059 :     type = TREE_TYPE (expr);
     382              : 
     383    316427059 :   if (!r.supports_type_p (type))
     384              :     {
     385     20973019 :       r.set_undefined ();
     386     20973019 :       return false;
     387              :     }
     388    295454040 :   if (expr == type)
     389              :     {
     390            0 :       r.set_varying (type);
     391            0 :       return true;
     392              :     }
     393    295454040 :   switch (TREE_CODE (expr))
     394              :     {
     395    240776883 :     case INTEGER_CST:
     396    240776883 :       {
     397    240776883 :         if (TREE_OVERFLOW_P (expr))
     398           55 :           expr = drop_tree_overflow (expr);
     399    240776883 :         r.set (expr, expr);
     400    240776883 :         return true;
     401              :       }
     402              : 
     403      4874129 :     case REAL_CST:
     404      4874129 :       {
     405      4874129 :         frange &f = as_a <frange> (r);
     406      4874129 :         REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (expr);
     407      4874129 :         if (real_isnan (rv))
     408              :           {
     409        15991 :             bool sign = real_isneg (rv);
     410        15991 :             f.set_nan (TREE_TYPE (expr), sign);
     411              :           }
     412              :         else
     413              :           {
     414      4858138 :             nan_state nan (false);
     415      4858138 :             f.set (TREE_TYPE (expr), *rv, *rv, nan);
     416              :           }
     417              :         return true;
     418              :       }
     419              : 
     420        20059 :     case SSA_NAME:
     421              :       // If this is not an abnormal or virtual ssa, invoke range_of_expr.
     422        20059 :       if (gimple_range_ssa_p (expr))
     423        20059 :         return invoke_range_of_expr (r, expr, stmt, bbentry, bbexit, e);
     424            0 :       gimple_range_global (r, expr);
     425            0 :       return true;
     426              : 
     427     10924697 :     case ADDR_EXPR:
     428     10924697 :       {
     429              :         // Handle &expr, and set points to.
     430     10924697 :         if (tree_single_nonzero_p (expr))
     431     10865676 :          r.set_nonzero (type);
     432              :         else
     433        59021 :           r.set_varying (type);
     434              :         // Set points to field.
     435     10924697 :         gcc_checking_assert (is_a <prange> (r));
     436     10924697 :         prange &ptr = as_a <prange> (r);
     437     10924697 :         ptr.set_pt (expr, true);
     438     10924697 :         return true;
     439              :       }
     440              : 
     441     38858272 :     default:
     442     38858272 :       if (POLY_INT_CST_P (expr))
     443              :         {
     444              :           unsigned int precision = TYPE_PRECISION (type);
     445              :           signop sign = TYPE_SIGN (type);
     446              :           bool have_poly_bound = targetm.poly_int_indeterminate_bound;
     447              :           poly_uint64 indeterminate_bound;
     448              : 
     449              :           if (have_poly_bound)
     450              :             indeterminate_bound = targetm.poly_int_indeterminate_bound ();
     451              : 
     452              :           auto val = wi::to_poly_wide (expr);
     453              :           auto type_min = wi::to_wide (TYPE_MIN_VALUE (type));
     454              :           auto type_max = wi::to_wide (TYPE_MAX_VALUE (type));
     455              : 
     456              :           /* Start with the invariant part of the poly-int, then account
     457              :              for each coefficient below.
     458              : 
     459              :              The target hook gives a per-coefficient upper bound for the
     460              :              indeterminate.  Since those indeterminates are unsigned and
     461              :              nonnegative, a positive coefficient can only increase the upper
     462              :              bound and a negative coefficient can only decrease the lower
     463              :              bound.  The opposite bound is unaffected by that coefficient:
     464              : 
     465              :                 [A, +C] with C >= 0  => max += C * bound
     466              :                 [A, -C] with C >= 0  => min -= C * bound.  */
     467              :           wide_int bounds[2] = { val.coeffs[0], val.coeffs[0] };
     468              :           bool ovf[2] = { false, false };
     469              : 
     470              :           for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
     471              :             {
     472              :               const auto &coeff = val.coeffs[i];
     473              :               if (wi::eq_p (coeff, 0))
     474              :                 continue;
     475              : 
     476              :               /* Select the only bound affected by this coefficient.  A
     477              :                  negative coefficient contributes to the minimum and a positive
     478              :                  coefficient contributes to the maximum.  */
     479              :               bool coeff_neg = wi::neg_p (coeff, sign);
     480              :               wide_int &bound = bounds[coeff_neg ? 0 : 1];
     481              :               bool &bound_ovf = ovf[coeff_neg ? 0 : 1];
     482              : 
     483              :               if (bound_ovf)
     484              :                 continue;
     485              : 
     486              :               /* A missing hook, or a -1 bound for this coefficient, means the
     487              :                  indeterminate has no finite target-specific limit.  Treat that
     488              :                  like an overflow of the affected bound.  */
     489              :               if (!have_poly_bound
     490              :                   || indeterminate_bound.coeffs[i] == HOST_WIDE_INT_M1U)
     491              :                 bound_ovf = true;
     492              :               else
     493              :                 {
     494              :                   auto indeterminate
     495              :                     = wi::uhwi (indeterminate_bound.coeffs[i], precision);
     496              :                   wi::overflow_type mul_ovf = wi::OVF_NONE;
     497              :                   auto term = wi::mul (coeff, indeterminate, sign, &mul_ovf);
     498              :                   wi::overflow_type add_ovf = wi::OVF_NONE;
     499              :                   bound = wi::add (bound, term, sign, &add_ovf);
     500              :                   bound_ovf = (mul_ovf != wi::OVF_NONE
     501              :                                || add_ovf != wi::OVF_NONE);
     502              :                 }
     503              : 
     504              :               if (TYPE_OVERFLOW_WRAPS (type) && bound_ovf)
     505              :                 {
     506              :                   r.set_varying (type);
     507              :                   r.update_bitmask (irange_bitmask (wi::zero (precision),
     508              :                                                     get_nonzero_bits (expr)));
     509              :                   return true;
     510              :                 }
     511              : 
     512              :               if (bound_ovf)
     513              :                 {
     514              :                   if (coeff_neg)
     515              :                     bounds[0] = type_min;
     516              :                   else
     517              :                     bounds[1] = type_max;
     518              :                 }
     519              :             }
     520              : 
     521              :           /* Check that the target filled in sensible bounds information.  */
     522              :           gcc_assert (wi::le_p (bounds[0], bounds[1], sign));
     523              : 
     524              :           irange &ir = as_a <irange> (r);
     525              :           ir.set (type, bounds[0], bounds[1]);
     526              : 
     527              :           /* Preserve alignment/step information that is not visible in the
     528              :              intervals.  For example, a poly-int like [8, 8] can
     529              :              only produce multiples of 8, but the interval range might be
     530              :              [8, 136], which also contains values with low bits set.  */
     531              :           ir.update_bitmask (irange_bitmask (wi::zero (precision),
     532              :                                              get_nonzero_bits (expr)));
     533              :           return true;
     534              :         }
     535     38858272 :       break;
     536              :     }
     537     38858272 :   if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr))
     538              :     {
     539     11609657 :       tree op0 = TREE_OPERAND (expr, 0);
     540     11609657 :       tree op1 = TREE_OPERAND (expr, 1);
     541     11609657 :       if (COMPARISON_CLASS_P (expr)
     542     11609657 :           && !value_range::supports_type_p (TREE_TYPE (op0)))
     543              :         return false;
     544     11609657 :       range_op_handler op (TREE_CODE (expr));
     545     11609657 :       if (op)
     546              :         {
     547     11609657 :           value_range r0 (TREE_TYPE (op0));
     548     11609657 :           value_range r1 (TREE_TYPE (op1));
     549     11609657 :           invoke_range_of_expr (r0, op0, stmt, bbentry, bbexit, e);
     550     11609657 :           invoke_range_of_expr (r1, op1, stmt, bbentry, bbexit, e);
     551     11609657 :           if (!op.fold_range (r, type, r0, r1))
     552          341 :             r.set_varying (type);
     553     11609657 :         }
     554              :       else
     555            0 :         r.set_varying (type);
     556              :       return true;
     557              :     }
     558     27248615 :   if (UNARY_CLASS_P (expr))
     559              :     {
     560      7364502 :       range_op_handler op (TREE_CODE (expr));
     561      7364502 :       tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
     562      7364502 :       if (op && value_range::supports_type_p (op0_type))
     563              :         {
     564      7354462 :           value_range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
     565      7354462 :           value_range r1 (type);
     566      7354462 :           r1.set_varying (type);
     567      7354462 :           invoke_range_of_expr (r0, TREE_OPERAND (expr, 0), stmt, bbentry,
     568              :                                 bbexit, e);
     569      7354462 :           if (!op.fold_range (r, type, r0, r1))
     570            0 :             r.set_varying (type);
     571      7354462 :         }
     572              :       else
     573        10040 :         r.set_varying (type);
     574      7364502 :       return true;
     575              :     }
     576     19884113 :   r.set_varying (type);
     577     19884113 :   return true;
     578              : }
     579              : 
     580              : // Return the range for NAME from SSA_NAME_RANGE_INFO.
     581              : 
     582              : static inline void
     583    191207223 : get_ssa_name_range_info (vrange &r, const_tree name)
     584              : {
     585    191207223 :   tree type = TREE_TYPE (name);
     586    191207223 :   gcc_checking_assert (!POINTER_TYPE_P (type));
     587    191207223 :   gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
     588              : 
     589    191207223 :   vrange_storage *ri = SSA_NAME_RANGE_INFO (name);
     590              : 
     591    191207223 :   if (ri)
     592    174337603 :     ri->get_vrange (r, TREE_TYPE (name));
     593              :   else
     594     16869620 :     r.set_varying (type);
     595    191207223 : }
     596              : 
     597              : // Return nonnull attribute of pointer NAME from SSA_NAME_PTR_INFO.
     598              : 
     599              : static inline bool
     600    107858306 : get_ssa_name_ptr_info_nonnull (const_tree name)
     601              : {
     602    107858306 :   gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
     603    107858306 :   struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
     604    107858306 :   if (pi == NULL)
     605              :     return false;
     606              :   /* TODO Now pt->null is conservatively set to true in PTA
     607              :      analysis. vrp is the only pass (including ipa-vrp)
     608              :      that clears pt.null via set_ptr_nonnull when it knows
     609              :      for sure. PTA will preserves the pt.null value set by VRP.
     610              : 
     611              :      When PTA analysis is improved, pt.anything, pt.nonlocal
     612              :      and pt.escaped may also has to be considered before
     613              :      deciding that pointer cannot point to NULL.  */
     614    106661739 :   return !pi->pt.null;
     615              : }
     616              : 
     617              : // Update the global range for NAME into the SSA_RANGE_NAME_INFO and
     618              : // Return the legacy global range for NAME if it has one, otherwise
     619              : // return VARYING.
     620              : // See discussion here regarding why there use to be a wrapper function:
     621              : // https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571709.html
     622              : // Legacy EVRP has been removed, leaving just this function.
     623              : 
     624              : void
     625    662527104 : gimple_range_global (vrange &r, tree name, struct function *fun)
     626              : {
     627    662527104 :   tree type = TREE_TYPE (name);
     628    662527104 :   gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
     629              : 
     630    662527104 :   if (SSA_NAME_IS_DEFAULT_DEF (name))
     631              :     {
     632     42942583 :       tree sym = SSA_NAME_VAR (name);
     633              :       // Adapted from vr_values::get_lattice_entry().
     634              :       // Use a range from an SSA_NAME's available range.
     635     42942583 :       if (TREE_CODE (sym) == PARM_DECL)
     636              :         {
     637              :           // Try to use the "nonnull" attribute to create ~[0, 0]
     638              :           // anti-ranges for pointers.  Note that this is only valid with
     639              :           // default definitions of PARM_DECLs.
     640     39925911 :           if (POINTER_TYPE_P (type)
     641     39925911 :               && ((cfun && fun == cfun && nonnull_arg_p (sym))
     642     11614534 :                   || get_ssa_name_ptr_info_nonnull (name)))
     643     11290830 :             r.set_nonzero (type);
     644     28635081 :           else if (!POINTER_TYPE_P (type))
     645              :             {
     646     17222974 :               get_ssa_name_range_info (r, name);
     647     17222974 :               if (r.undefined_p ())
     648            0 :                 r.set_varying (type);
     649              :             }
     650              :           else
     651     11412107 :             r.set_varying (type);
     652              :         }
     653              :       // If this is a local automatic with no definition, use undefined.
     654      3016672 :       else if (TREE_CODE (sym) != RESULT_DECL)
     655      2687152 :         r.set_undefined ();
     656              :       else
     657       329520 :         r.set_varying (type);
     658              :    }
     659    619584521 :   else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
     660              :     {
     661    173984249 :       get_ssa_name_range_info (r, name);
     662    173984249 :       if (r.undefined_p ())
     663            0 :         r.set_varying (type);
     664              :     }
     665    445600272 :   else if (POINTER_TYPE_P (type) && SSA_NAME_PTR_INFO (name))
     666              :     {
     667     96243772 :       if (get_ssa_name_ptr_info_nonnull (name))
     668     13731209 :         r.set_nonzero (type);
     669              :       else
     670     82512563 :         r.set_varying (type);
     671              :     }
     672              :   else
     673    349356500 :     r.set_varying (type);
     674    662527104 : }
     675              : 
     676              : // ----------------------------------------------
     677              : // global_range_query implementation.
     678              : 
     679              : global_range_query global_ranges;
     680              : 
     681              : bool
     682    464652779 : global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
     683              : {
     684    464652779 :   if (!gimple_range_ssa_p (expr))
     685    128041253 :     return get_tree_range (r, expr, stmt);
     686              : 
     687    336611526 :   gimple_range_global (r, expr);
     688              : 
     689    336611526 :   return true;
     690              : }
        

Generated by: LCOV version 2.4-beta

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