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

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.