LCOV - code coverage report
Current view: top level - gcc - value-query.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.5 % 267 231
Test Date: 2026-10-17 16:30:31 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    432428492 : set_range_query (struct function *fun, range_query *q)
      46              : {
      47              :   // Set the global query if it hasn't been set.
      48    432428492 :   if (!fun->x_range_query)
      49      3193818 :     fun->x_range_query = get_global_range_query ();
      50              : 
      51              :   // If this is not a compatible range query, revert to the global query.
      52    432428492 :   if (!q->active_query_compatible_p ())
      53     97635484 :     q = get_global_range_query ();
      54              : 
      55    432428492 :   if (q == fun->x_range_query)
      56              :     return NULL;
      57              : 
      58    191437580 :   range_query *orig = fun->x_range_query;
      59    191437580 :   fun->x_range_query = q;
      60    191437580 :   return orig;
      61              : }
      62              : 
      63              : // range_query default methods.
      64              : 
      65              : bool
      66     12148004 : range_query::range_on_edge (vrange &r, edge, tree expr)
      67              : {
      68     12148004 :   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      1457701 : range_query::range_of_stmt (vrange &r, gimple *stmt, tree name)
      85              : {
      86      1457701 :   if (!name)
      87      1457701 :     name = gimple_get_lhs (stmt);
      88              : 
      89      1457701 :   gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
      90              : 
      91      1457701 :   if (name)
      92      1457701 :     return range_of_expr (r, name);
      93              :   return false;
      94              : }
      95              : 
      96              : // Default for updating range info is to do nothing.
      97              : void
      98    124327570 : range_query::update_range_info (tree)
      99              : {
     100    124327570 : }
     101              : 
     102              : // Default for updating range info is to do nothing.
     103              : void
     104      4353232 : range_query::update_range_info (tree, const vrange &)
     105              : {
     106      4353232 : }
     107              : 
     108              : // Default for resetting range info for NAME is to clear the oracles.
     109              : 
     110              : void
     111      7937668 : range_query::reset_range_info (tree name)
     112              : {
     113      7937668 :   relation ().clear (name);
     114      7937668 :   if (gori_ssa ())
     115       277349 :     gori_ssa ()->clear (name);
     116      7937668 :   infer_oracle ().clear (name);
     117      7937668 : }
     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     90162594 : range_query::value_of_expr (tree expr, gimple *stmt)
     124              : {
     125     90162594 :   tree t;
     126              : 
     127     90162594 :   if (!value_range::supports_type_p (TREE_TYPE (expr)))
     128              :     return NULL_TREE;
     129              : 
     130     90159559 :   value_range r (TREE_TYPE (expr));
     131              : 
     132     90159559 :   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     90159559 :       if (r.undefined_p ())
     137        25673 :         range_of_expr (r, expr);
     138     90159559 :       if (r.singleton_p (&t))
     139      4155944 :         return t;
     140              :     }
     141              :   return NULL_TREE;
     142     90159559 : }
     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    114360258 : range_query::value_of_stmt (gimple *stmt, tree name)
     172              : {
     173    114360258 :   tree t;
     174              : 
     175    114360258 :   if (!name)
     176     65023174 :     name = gimple_get_lhs (stmt);
     177              : 
     178    114360258 :   gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
     179              : 
     180    105051642 :   if (!name || !value_range::supports_type_p (TREE_TYPE (name)))
     181              :     return NULL_TREE;
     182     96020207 :   value_range r (TREE_TYPE (name));
     183    192040414 :   if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
     184      1031807 :     return t;
     185              :   return NULL_TREE;
     186     96020207 : }
     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     29893232 : range_query::create_gori (int not_executable_flag, int sw_max_edges)
     239              : {
     240     29893232 :   gcc_checking_assert (m_gori == &default_gori);
     241     29893232 :   gcc_checking_assert (m_map == NULL);
     242     29893232 :   m_map = new gori_map ();
     243     29893232 :   gcc_checking_assert (m_map);
     244     29893232 :   m_gori = new gori_compute (*m_map, not_executable_flag, sw_max_edges);
     245     29893232 :   gcc_checking_assert (m_gori);
     246     29893232 : }
     247              : 
     248              : void
     249     82152878 : range_query::destroy_gori ()
     250              : {
     251     82152878 :   if (m_gori && m_gori != &default_gori)
     252     29893232 :     delete m_gori;
     253     82152878 :   if (m_map)
     254     29893232 :     delete m_map;
     255     82152878 :   m_map = NULL;
     256     82152878 :   m_gori= &default_gori;
     257     82152878 : }
     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     29893232 : range_query::create_infer_oracle (range_query *q, bool do_search)
     267              : {
     268     29893232 :   gcc_checking_assert (m_infer == &default_infer_oracle);
     269     29893232 :   m_infer = new infer_range_manager (do_search, q);
     270     29893232 :   gcc_checking_assert (m_infer);
     271     29893232 : }
     272              : 
     273              : void
     274    112046110 : range_query::destroy_infer_oracle ()
     275              : {
     276    112046110 :   if (m_infer && m_infer != &default_infer_oracle)
     277     29893232 :     delete m_infer;
     278    112046110 :   m_infer = &default_infer_oracle;
     279    112046110 : }
     280              : 
     281              : // Create dominance based range oracle for the current query if dom info is
     282              : // available.
     283              : 
     284              : void
     285     29893241 : range_query::create_relation_oracle ()
     286              : {
     287     29893241 :   gcc_checking_assert (this != &global_ranges);
     288     29893241 :   gcc_checking_assert (m_relation == &default_relation_oracle);
     289              : 
     290     29893241 :   if (!dom_info_available_p (CDI_DOMINATORS))
     291              :     return;
     292     27831547 :   m_relation = new dom_oracle ();
     293     27831547 :   gcc_checking_assert (m_relation);
     294              : }
     295              : 
     296              : // Destroy any relation oracle that was created.
     297              : 
     298              : void
     299    112046110 : range_query::destroy_relation_oracle ()
     300              : {
     301              :   // m_relation can be NULL if a derived range_query class took care of
     302              :   // disposing its own oracle.
     303    112046110 :   if (m_relation && m_relation != &default_relation_oracle)
     304              :     {
     305     27831547 :       delete m_relation;
     306     27831547 :       m_relation = &default_relation_oracle;
     307              :     }
     308    112046110 : }
     309              : 
     310              : void
     311     39369864 : range_query::share_query (range_query &q)
     312              : {
     313     39369864 :   m_relation = q.m_relation;
     314     39369864 :   m_infer = q.m_infer;
     315     39369864 :   m_gori = q.m_gori;
     316     39369864 :   m_map = q.m_map;
     317     39369864 :   m_shared_copy_p = true;
     318     39369864 : }
     319              : 
     320    121522754 : range_query::range_query ()
     321              : {
     322    121522754 :   m_relation = &default_relation_oracle;
     323    121522754 :   m_infer = &default_infer_oracle;
     324    121522754 :   m_gori = &default_gori;
     325    121522754 :   m_map = NULL;
     326    121522754 :   m_shared_copy_p = false;
     327    121522754 : }
     328              : 
     329    121522742 : range_query::~range_query ()
     330              : {
     331              :   // Do not destroy anything if this is a shared copy.
     332    121522742 :   if (m_shared_copy_p)
     333              :     return;
     334     82152878 :   destroy_gori ();
     335     82152878 :   destroy_infer_oracle ();
     336     82152878 :   destroy_relation_oracle ();
     337            0 : }
     338              : 
     339              : // This routine will invoke the equivalent of range_of_expr on
     340              : // either a gimple statement STMT, on entry to block BBENTRY, or on
     341              : // exit from block BBEXIT.   Only one of these 3 fields may be set.
     342              : // It is valid for none of them to be set, in wqhich case there is no context.
     343              : 
     344              : bool
     345     30808387 : range_query::invoke_range_of_expr (vrange &r, tree expr, gimple *stmt,
     346              :                                    basic_block bbentry, basic_block bbexit,
     347              :                                    edge e)
     348              : {
     349     30808387 :   if (bbentry)
     350              :     {
     351            0 :       gcc_checking_assert (!stmt && !bbexit && !e);
     352            0 :       return range_on_entry (r, bbentry, expr);
     353              :     }
     354     30808387 :   if (bbexit)
     355              :     {
     356            0 :       gcc_checking_assert (!stmt && !e);
     357            0 :       return range_on_exit (r, bbexit, expr);
     358              :     }
     359     30808387 :   if (e)
     360              :     {
     361      3156199 :       gcc_checking_assert (!stmt);
     362      3156199 :       return range_on_edge (r, e, expr);
     363              :     }
     364              : 
     365     27652188 :   return range_of_expr (r, expr, stmt);
     366              : }
     367              : 
     368              : // Return a range in R for the tree EXPR.  The context can be either a STMT,
     369              : // or on entry to block BBENTRY or exit from block BBEXIT.
     370              : // Return true if a range is representable, and UNDEFINED/false if not.
     371              : 
     372              : bool
     373    342902953 : range_query::get_tree_range (vrange &r, tree expr, gimple *stmt,
     374              :                              basic_block bbentry, basic_block bbexit, edge e)
     375              : {
     376    342902953 :   tree type;
     377    342902953 :   if (TYPE_P (expr))
     378              :     type = expr;
     379              :   else
     380    342902953 :     type = TREE_TYPE (expr);
     381              : 
     382    342902953 :   if (!r.supports_type_p (type))
     383              :     {
     384     21114838 :       r.set_undefined ();
     385     21114838 :       return false;
     386              :     }
     387    321788115 :   if (expr == type)
     388              :     {
     389            0 :       r.set_varying (type);
     390            0 :       return true;
     391              :     }
     392    321788115 :   switch (TREE_CODE (expr))
     393              :     {
     394    255684204 :     case INTEGER_CST:
     395    255684204 :       {
     396    255684204 :         if (TREE_OVERFLOW_P (expr))
     397          109 :           expr = drop_tree_overflow (expr);
     398    255684204 :         r.set (expr, expr);
     399    255684204 :         return true;
     400              :       }
     401              : 
     402      4898628 :     case REAL_CST:
     403      4898628 :       {
     404      4898628 :         frange &f = as_a <frange> (r);
     405      4898628 :         REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (expr);
     406      4898628 :         if (real_isnan (rv))
     407              :           {
     408        16647 :             bool sign = real_isneg (rv);
     409        16647 :             f.set_nan (TREE_TYPE (expr), sign);
     410              :           }
     411              :         else
     412              :           {
     413      4881981 :             nan_state nan (false);
     414      4881981 :             f.set (TREE_TYPE (expr), *rv, *rv, nan);
     415              :           }
     416              :         return true;
     417              :       }
     418              : 
     419        20544 :     case SSA_NAME:
     420              :       // If this is not an abnormal or virtual ssa, invoke range_of_expr.
     421        20544 :       if (gimple_range_ssa_p (expr))
     422        20544 :         return invoke_range_of_expr (r, expr, stmt, bbentry, bbexit, e);
     423            0 :       gimple_range_global (r, expr);
     424            0 :       return true;
     425              : 
     426     11013718 :     case ADDR_EXPR:
     427     11013718 :       {
     428              :         // Handle &expr, and set points to.
     429     11013718 :         if (tree_single_nonzero_p (expr))
     430     10952960 :          r.set_nonzero (type);
     431              :         else
     432        60758 :           r.set_varying (type);
     433              :         // Set points to field.
     434     11013718 :         gcc_checking_assert (is_a <prange> (r));
     435     11013718 :         prange &ptr = as_a <prange> (r);
     436     11013718 :         ptr.set_pt (expr, true);
     437     11013718 :         return true;
     438              :       }
     439              : 
     440     50171021 :     default:
     441     50171021 :       if (POLY_INT_CST_P (expr))
     442              :         {
     443              :           unsigned int precision = TYPE_PRECISION (type);
     444              :           signop sign = TYPE_SIGN (type);
     445              :           bool have_poly_bound = targetm.poly_int_indeterminate_bound;
     446              :           poly_uint64 indeterminate_bound;
     447              : 
     448              :           if (have_poly_bound)
     449              :             indeterminate_bound = targetm.poly_int_indeterminate_bound ();
     450              : 
     451              :           auto val = wi::to_poly_wide (expr);
     452              :           auto type_min = wi::to_wide (TYPE_MIN_VALUE (type));
     453              :           auto type_max = wi::to_wide (TYPE_MAX_VALUE (type));
     454              : 
     455              :           /* Start with the invariant part of the poly-int, then account
     456              :              for each coefficient below.
     457              : 
     458              :              The target hook gives a per-coefficient upper bound for the
     459              :              indeterminate.  Since those indeterminates are unsigned and
     460              :              nonnegative, a positive coefficient can only increase the upper
     461              :              bound and a negative coefficient can only decrease the lower
     462              :              bound.  The opposite bound is unaffected by that coefficient:
     463              : 
     464              :                 [A, +C] with C >= 0  => max += C * bound
     465              :                 [A, -C] with C >= 0  => min -= C * bound.  */
     466              :           wide_int bounds[2] = { val.coeffs[0], val.coeffs[0] };
     467              :           bool ovf[2] = { false, false };
     468              : 
     469              :           for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
     470              :             {
     471              :               const auto &coeff = val.coeffs[i];
     472              :               if (wi::eq_p (coeff, 0))
     473              :                 continue;
     474              : 
     475              :               /* Select the only bound affected by this coefficient.  A
     476              :                  negative coefficient contributes to the minimum and a positive
     477              :                  coefficient contributes to the maximum.  */
     478              :               bool coeff_neg = wi::neg_p (coeff, sign);
     479              :               wide_int &bound = bounds[coeff_neg ? 0 : 1];
     480              :               bool &bound_ovf = ovf[coeff_neg ? 0 : 1];
     481              : 
     482              :               if (bound_ovf)
     483              :                 continue;
     484              : 
     485              :               /* A missing hook, or a -1 bound for this coefficient, means the
     486              :                  indeterminate has no finite target-specific limit.  Treat that
     487              :                  like an overflow of the affected bound.  */
     488              :               if (!have_poly_bound
     489              :                   || indeterminate_bound.coeffs[i] == HOST_WIDE_INT_M1U)
     490              :                 bound_ovf = true;
     491              :               else
     492              :                 {
     493              :                   auto indeterminate
     494              :                     = wi::uhwi (indeterminate_bound.coeffs[i], precision);
     495              :                   wi::overflow_type mul_ovf = wi::OVF_NONE;
     496              :                   auto term = wi::mul (coeff, indeterminate, sign, &mul_ovf);
     497              :                   wi::overflow_type add_ovf = wi::OVF_NONE;
     498              :                   bound = wi::add (bound, term, sign, &add_ovf);
     499              :                   bound_ovf = (mul_ovf != wi::OVF_NONE
     500              :                                || add_ovf != wi::OVF_NONE);
     501              :                 }
     502              : 
     503              :               if (TYPE_OVERFLOW_WRAPS (type) && bound_ovf)
     504              :                 {
     505              :                   r.set_varying (type);
     506              :                   r.update_bitmask (irange_bitmask (wi::zero (precision),
     507              :                                                     get_nonzero_bits (expr)));
     508              :                   return true;
     509              :                 }
     510              : 
     511              :               if (bound_ovf)
     512              :                 {
     513              :                   if (coeff_neg)
     514              :                     bounds[0] = type_min;
     515              :                   else
     516              :                     bounds[1] = type_max;
     517              :                 }
     518              :             }
     519              : 
     520              :           /* Check that the target filled in sensible bounds information.  */
     521              :           gcc_assert (wi::le_p (bounds[0], bounds[1], sign));
     522              : 
     523              :           irange &ir = as_a <irange> (r);
     524              :           ir.set (type, bounds[0], bounds[1]);
     525              : 
     526              :           /* Preserve alignment/step information that is not visible in the
     527              :              intervals.  For example, a poly-int like [8, 8] can
     528              :              only produce multiples of 8, but the interval range might be
     529              :              [8, 136], which also contains values with low bits set.  */
     530              :           ir.update_bitmask (irange_bitmask (wi::zero (precision),
     531              :                                              get_nonzero_bits (expr)));
     532              :           return true;
     533              :         }
     534     50171021 :       break;
     535              :     }
     536     50171021 :   if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr))
     537              :     {
     538     11679336 :       tree op0 = TREE_OPERAND (expr, 0);
     539     11679336 :       tree op1 = TREE_OPERAND (expr, 1);
     540     11679336 :       if (COMPARISON_CLASS_P (expr)
     541     11679336 :           && !value_range::supports_type_p (TREE_TYPE (op0)))
     542              :         return false;
     543     11679336 :       range_op_handler op (TREE_CODE (expr));
     544     11679336 :       if (op)
     545              :         {
     546     11679336 :           value_range r0 (TREE_TYPE (op0));
     547     11679336 :           value_range r1 (TREE_TYPE (op1));
     548     11679336 :           invoke_range_of_expr (r0, op0, stmt, bbentry, bbexit, e);
     549     11679336 :           invoke_range_of_expr (r1, op1, stmt, bbentry, bbexit, e);
     550     11679336 :           if (!op.fold_range (r, type, r0, r1))
     551          340 :             r.set_varying (type);
     552     11679336 :         }
     553              :       else
     554            0 :         r.set_varying (type);
     555              :       return true;
     556              :     }
     557     38491685 :   if (UNARY_CLASS_P (expr))
     558              :     {
     559      7439241 :       range_op_handler op (TREE_CODE (expr));
     560      7439241 :       tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
     561      7439241 :       if (op && value_range::supports_type_p (op0_type))
     562              :         {
     563      7429171 :           value_range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
     564      7429171 :           value_range r1 (type);
     565      7429171 :           r1.set_varying (type);
     566      7429171 :           invoke_range_of_expr (r0, TREE_OPERAND (expr, 0), stmt, bbentry,
     567              :                                 bbexit, e);
     568      7429171 :           if (!op.fold_range (r, type, r0, r1))
     569            0 :             r.set_varying (type);
     570      7429171 :         }
     571              :       else
     572        10070 :         r.set_varying (type);
     573      7439241 :       return true;
     574              :     }
     575     31052444 :   r.set_varying (type);
     576     31052444 :   return true;
     577              : }
     578              : 
     579              : // Return the range for NAME from SSA_NAME_RANGE_INFO.
     580              : 
     581              : static inline void
     582    184795109 : get_ssa_name_range_info (vrange &r, const_tree name)
     583              : {
     584    184795109 :   tree type = TREE_TYPE (name);
     585    184795109 :   gcc_checking_assert (!POINTER_TYPE_P (type));
     586    184795109 :   gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
     587              : 
     588    184795109 :   vrange_storage *ri = SSA_NAME_RANGE_INFO (name);
     589              : 
     590    184795109 :   if (ri)
     591    168011881 :     ri->get_vrange (r, TREE_TYPE (name));
     592              :   else
     593     16783228 :     r.set_varying (type);
     594    184795109 : }
     595              : 
     596              : // Return nonnull attribute of pointer NAME from SSA_NAME_PTR_INFO.
     597              : 
     598              : static inline bool
     599     98688061 : get_ssa_name_ptr_info_nonnull (const_tree name)
     600              : {
     601     98688061 :   gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
     602     98688061 :   struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
     603     98688061 :   if (pi == NULL)
     604              :     return false;
     605              :   /* TODO Now pt->null is conservatively set to true in PTA
     606              :      analysis. vrp is the only pass (including ipa-vrp)
     607              :      that clears pt.null via set_ptr_nonnull when it knows
     608              :      for sure. PTA will preserves the pt.null value set by VRP.
     609              : 
     610              :      When PTA analysis is improved, pt.anything, pt.nonlocal
     611              :      and pt.escaped may also has to be considered before
     612              :      deciding that pointer cannot point to NULL.  */
     613     97484259 :   return !pi->pt.null;
     614              : }
     615              : 
     616              : // Update the global range for NAME into the SSA_RANGE_NAME_INFO and
     617              : // Return the legacy global range for NAME if it has one, otherwise
     618              : // return VARYING.
     619              : // See discussion here regarding why there use to be a wrapper function:
     620              : // https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571709.html
     621              : // Legacy EVRP has been removed, leaving just this function.
     622              : 
     623              : void
     624    631691890 : gimple_range_global (vrange &r, tree name, struct function *fun)
     625              : {
     626    631691890 :   tree type = TREE_TYPE (name);
     627    631691890 :   gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
     628              : 
     629    631691890 :   if (SSA_NAME_IS_DEFAULT_DEF (name))
     630              :     {
     631     42768445 :       tree sym = SSA_NAME_VAR (name);
     632              :       // Adapted from vr_values::get_lattice_entry().
     633              :       // Use a range from an SSA_NAME's available range.
     634     42768445 :       if (TREE_CODE (sym) == PARM_DECL)
     635              :         {
     636              :           // Try to use the "nonnull" attribute to create ~[0, 0]
     637              :           // anti-ranges for pointers.  Note that this is only valid with
     638              :           // default definitions of PARM_DECLs.
     639     39774037 :           if (POINTER_TYPE_P (type)
     640     39774037 :               && ((cfun && fun == cfun && nonnull_arg_p (sym))
     641     11556747 :                   || get_ssa_name_ptr_info_nonnull (name)))
     642     11277766 :             r.set_nonzero (type);
     643     28496271 :           else if (!POINTER_TYPE_P (type))
     644              :             {
     645     17136196 :               get_ssa_name_range_info (r, name);
     646     17136196 :               if (r.undefined_p ())
     647            0 :                 r.set_varying (type);
     648              :             }
     649              :           else
     650     11360075 :             r.set_varying (type);
     651              :         }
     652              :       // If this is a local automatic with no definition, use undefined.
     653      2994408 :       else if (TREE_CODE (sym) != RESULT_DECL)
     654      2665813 :         r.set_undefined ();
     655              :       else
     656       328595 :         r.set_varying (type);
     657              :    }
     658    588923445 :   else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
     659              :     {
     660    167658913 :       get_ssa_name_range_info (r, name);
     661    167658913 :       if (r.undefined_p ())
     662            0 :         r.set_varying (type);
     663              :     }
     664    421264532 :   else if (POINTER_TYPE_P (type) && SSA_NAME_PTR_INFO (name))
     665              :     {
     666     87131314 :       if (get_ssa_name_ptr_info_nonnull (name))
     667     11447043 :         r.set_nonzero (type);
     668              :       else
     669     75684271 :         r.set_varying (type);
     670              :     }
     671              :   else
     672    334133218 :     r.set_varying (type);
     673    631691890 : }
     674              : 
     675              : // ----------------------------------------------
     676              : // global_range_query implementation.
     677              : 
     678              : global_range_query global_ranges;
     679              : 
     680              : bool
     681    438164326 : global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
     682              : {
     683    438164326 :   if (!gimple_range_ssa_p (expr))
     684    113317382 :     return get_tree_range (r, expr, stmt);
     685              : 
     686    324846944 :   gimple_range_global (r, expr);
     687              : 
     688    324846944 :   return true;
     689              : }
        

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.