LCOV - code coverage report
Current view: top level - gcc - gimple-range-path.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.3 % 353 308
Test Date: 2026-09-19 16:22:48 Functions: 93.8 % 32 30
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Basic block path solver.
       2              :    Copyright (C) 2021-2026 Free Software Foundation, Inc.
       3              :    Contributed by Aldy Hernandez <aldyh@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              :  for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "tree.h"
      26              : #include "gimple.h"
      27              : #include "cfganal.h"
      28              : #include "value-range.h"
      29              : #include "gimple-range.h"
      30              : #include "tree-pretty-print.h"
      31              : #include "gimple-range-path.h"
      32              : #include "ssa.h"
      33              : #include "tree-cfg.h"
      34              : #include "gimple-iterator.h"
      35              : 
      36              : // Internal construct to help facilitate debugging of solver.
      37              : #define DEBUG_SOLVER (dump_file && (param_threader_debug == THREADER_DEBUG_ALL))
      38              : 
      39       808983 : path_range_query::path_range_query (gimple_ranger &ranger,
      40              :                                     const vec<basic_block> &path,
      41              :                                     const bitmap_head *dependencies,
      42              :                                     bool resolve)
      43       808983 :   : m_cache (),
      44       808983 :     m_ranger (ranger),
      45       808983 :     m_resolve (resolve)
      46              : {
      47       808983 :   share_query (ranger);
      48              :   // Override the relation oracle with a local path relation oracle.
      49       808983 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      50              : 
      51       808983 :   reset_path (path, dependencies);
      52       808983 : }
      53              : 
      54      8602305 : path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
      55      8602305 :   : m_cache (),
      56      8602305 :     m_ranger (ranger),
      57      8602305 :     m_resolve (resolve)
      58              : {
      59      8602305 :   share_query (ranger);
      60              :   // Override the relation oracle with a local path relation oracle.
      61      8602305 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      62      8602305 : }
      63              : 
      64     16697499 : path_range_query::~path_range_query ()
      65              : {
      66      9411288 :   delete m_relation;
      67      9411288 :   m_relation = NULL;
      68     16697499 : }
      69              : 
      70              : // Return TRUE if NAME is an exit dependency for the path.
      71              : 
      72              : bool
      73    144655634 : path_range_query::exit_dependency_p (tree name)
      74              : {
      75    144655634 :   return (TREE_CODE (name) == SSA_NAME
      76    144655634 :           && bitmap_bit_p (m_exit_dependencies, SSA_NAME_VERSION (name)));
      77              : }
      78              : 
      79              : // If NAME has a cache entry, return it in R, and return TRUE.
      80              : 
      81              : inline bool
      82    322866062 : path_range_query::get_cache (vrange &r, tree name)
      83              : {
      84    322866062 :   if (!gimple_range_ssa_p (name))
      85     64225920 :     return get_global_range_query ()->range_of_expr (r, name);
      86              : 
      87    258640142 :   return m_cache.get_range (r, name);
      88              : }
      89              : 
      90              : void
      91            0 : path_range_query::dump (FILE *dump_file)
      92              : {
      93            0 :   push_dump_file save (dump_file, dump_flags & ~TDF_DETAILS);
      94              : 
      95            0 :   if (m_path.is_empty ())
      96            0 :     return;
      97              : 
      98            0 :   unsigned i;
      99            0 :   bitmap_iterator bi;
     100              : 
     101            0 :   dump_ranger (dump_file, m_path);
     102              : 
     103            0 :   fprintf (dump_file, "Exit dependencies:\n");
     104            0 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     105              :     {
     106            0 :       tree name = ssa_name (i);
     107            0 :       print_generic_expr (dump_file, name, TDF_SLIM);
     108            0 :       fprintf (dump_file, "\n");
     109              :     }
     110              : 
     111            0 :   m_cache.dump (dump_file);
     112            0 : }
     113              : 
     114              : void
     115            0 : path_range_query::debug ()
     116              : {
     117            0 :   dump (stderr);
     118            0 : }
     119              : 
     120              : // Return TRUE if NAME is defined outside the current path.
     121              : 
     122              : bool
     123     57493063 : path_range_query::defined_outside_path (tree name)
     124              : {
     125     57493063 :   gimple *def = SSA_NAME_DEF_STMT (name);
     126     57493063 :   basic_block bb = gimple_bb (def);
     127              : 
     128     57493063 :   return !bb || !m_path.contains (bb);
     129              : }
     130              : 
     131              : // Return the range of NAME on entry to the path.
     132              : 
     133              : void
     134     21468844 : path_range_query::range_on_path_entry (vrange &r, tree name)
     135              : {
     136     21468844 :   gcc_checking_assert (defined_outside_path (name));
     137     21468844 :   basic_block entry = entry_bb ();
     138     21468844 :   m_ranger.range_on_entry (r, entry, name);
     139     21468844 : }
     140              : 
     141              : // Return the range of NAME at the end of the path being analyzed.
     142              : 
     143              : bool
     144    201132411 : path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
     145              : {
     146    201132411 :   if (!r.supports_type_p (TREE_TYPE (name)))
     147              :     return false;
     148              : 
     149    201132411 :   if (get_cache (r, name))
     150              :     return true;
     151              : 
     152     58336040 :   if (m_resolve && defined_outside_path (name))
     153              :     {
     154     19715357 :       range_on_path_entry (r, name);
     155     19715357 :       m_cache.set_range (name, r);
     156     19715357 :       return true;
     157              :     }
     158              : 
     159              :   // We can be called from match.pd or elsewhere, with a context statement
     160              :   // that can be anywhere on the path.  Since we can only compute ranges
     161              :   // mid flight at the current path position, check that's the case,
     162              :   // otherwise fall through to the global range.
     163     38620683 :   if (stmt
     164     38502431 :       && gimple_bb (stmt) == curr_bb ()
     165     77123114 :       && range_defined_in_block (r, name, gimple_bb (stmt)))
     166              :     {
     167     19332241 :       if (TREE_CODE (name) == SSA_NAME)
     168              :         {
     169     19332241 :           value_range glob (TREE_TYPE (name));
     170     19332241 :           gimple_range_global (glob, name);
     171     19332241 :           r.intersect (glob);
     172     19332241 :         }
     173              : 
     174     19332241 :       m_cache.set_range (name, r);
     175     19332241 :       return true;
     176              :     }
     177              : 
     178     19288442 :   gimple_range_global (r, name);
     179     19288442 :   return true;
     180              : }
     181              : 
     182              : bool
     183    201132411 : path_range_query::range_of_expr (vrange &r, tree name, gimple *stmt)
     184              : {
     185    201132411 :   if (internal_range_of_expr (r, name, stmt))
     186              :     {
     187    201132411 :       if (r.undefined_p ())
     188       183156 :         m_undefined_path = true;
     189              : 
     190              :       return true;
     191              :     }
     192              :   return false;
     193              : }
     194              : 
     195              : bool
     196     28491515 : path_range_query::unreachable_path_p ()
     197              : {
     198     28491515 :   return m_undefined_path;
     199              : }
     200              : 
     201              : // Reset the current path to PATH.
     202              : 
     203              : void
     204     38173948 : path_range_query::reset_path (const vec<basic_block> &path,
     205              :                               const bitmap_head *dependencies)
     206              : {
     207     38173948 :   gcc_checking_assert (path.length () > 1);
     208              : 
     209              :   // Use truncate/safe_splice instead of copy() to avoid repeated mallocs here.
     210     38173948 :   m_path.truncate (0);
     211     38173948 :   m_path.safe_splice (path);
     212              : 
     213     38173948 :   m_pos = m_path.length () - 1;
     214     38173948 :   m_undefined_path = false;
     215     38173948 :   m_cache.clear ();
     216              : 
     217     38173948 :   compute_ranges (dependencies);
     218     38173948 : }
     219              : 
     220              : bool
     221    278061781 : path_range_query::ssa_defined_in_bb (tree name, basic_block bb)
     222              : {
     223    278061781 :   return (TREE_CODE (name) == SSA_NAME
     224    273542561 :           && SSA_NAME_DEF_STMT (name)
     225    551604342 :           && gimple_bb (SSA_NAME_DEF_STMT (name)) == bb);
     226              : }
     227              : 
     228              : // Return the range of the result of PHI in R.
     229              : //
     230              : // Since PHIs are calculated in parallel at the beginning of the
     231              : // block, we must be careful to never save anything to the cache here.
     232              : // It is the caller's responsibility to adjust the cache.  Also,
     233              : // calculating the PHI's range must not trigger additional lookups.
     234              : 
     235              : void
     236     22138970 : path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
     237              : {
     238     22138970 :   tree name = gimple_phi_result (phi);
     239              : 
     240     44277940 :   if (at_entry ())
     241              :     {
     242      3611447 :       if (m_resolve && m_ranger.range_of_expr (r, name, phi))
     243              :         return;
     244              : 
     245              :       // Try to fold the phi exclusively with global values.
     246              :       // This will get things like PHI <5(99), 6(88)>.  We do this by
     247              :       // calling range_of_expr with no context.
     248      1781475 :       unsigned nargs = gimple_phi_num_args (phi);
     249      1781475 :       value_range arg_range (TREE_TYPE (name));
     250      1781475 :       r.set_undefined ();
     251      7736502 :       for (size_t i = 0; i < nargs; ++i)
     252              :         {
     253      4173552 :           tree arg = gimple_phi_arg_def (phi, i);
     254      4173552 :           if (m_ranger.range_of_expr (arg_range, arg, /*stmt=*/NULL))
     255      4173552 :             r.union_ (arg_range);
     256              :           else
     257              :             {
     258            0 :               r.set_varying (TREE_TYPE (name));
     259            0 :               return;
     260              :             }
     261              :         }
     262              :       return;
     263      1781475 :     }
     264              : 
     265     18527523 :   basic_block bb = gimple_bb (phi);
     266     18527523 :   basic_block prev = prev_bb ();
     267     18527523 :   edge e_in = find_edge (prev, bb);
     268              :   // The incoming edge the path supplies is never abnormal, so the
     269              :   // argument on it is a valid value for the PHI result even when the
     270              :   // result occurs in an abnormal PHI.
     271     18527523 :   gcc_checking_assert (!(e_in->flags & EDGE_ABNORMAL));
     272     18527523 :   tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e_in);
     273              :   // Avoid using the cache for ARGs defined in this block, as
     274              :   // that could create an ordering problem.
     275     18527523 :   if (ssa_defined_in_bb (arg, bb) || !get_cache (r, arg))
     276              :     {
     277      4901764 :       if (m_resolve)
     278              :         {
     279      2793351 :           value_range tmp (TREE_TYPE (name));
     280              :           // Using both the range on entry to the path, and the
     281              :           // range on this edge yields significantly better
     282              :           // results.
     283      2793351 :           if (TREE_CODE (arg) == SSA_NAME
     284      2793351 :               && defined_outside_path (arg))
     285      1753487 :             range_on_path_entry (r, arg);
     286              :           else
     287      1039864 :             r.set_varying (TREE_TYPE (name));
     288      2793351 :           m_ranger.range_on_edge (tmp, e_in, arg);
     289      2793351 :           r.intersect (tmp);
     290      2793351 :           return;
     291      2793351 :         }
     292      2108413 :       r.set_varying (TREE_TYPE (name));
     293              :     }
     294              : }
     295              : 
     296              : // If NAME is defined in BB, set R to the range of NAME, and return
     297              : // TRUE.  Otherwise, return FALSE.
     298              : 
     299              : bool
     300    230167301 : path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb)
     301              : {
     302              :   // Ranges can only be calculated at the current path position, both
     303              :   // while pre-computing the cache and when answering questions at the
     304              :   // path exit afterwards.
     305    230167301 :   gcc_assert (bb == curr_bb ());
     306              : 
     307    230167301 :   gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     308    230167301 :   basic_block def_bb = gimple_bb (def_stmt);
     309              : 
     310    230167301 :   if (def_bb != bb)
     311              :     return false;
     312              : 
     313     79548097 :   if (get_cache (r, name))
     314              :     return true;
     315              : 
     316     77710042 :   if (gimple_code (def_stmt) == GIMPLE_PHI)
     317     22138970 :     ssa_range_in_phi (r, as_a<gphi *> (def_stmt));
     318              :   else
     319              :     {
     320     55571072 :       if (name)
     321     55571072 :         get_path_oracle ()->killing_def (name);
     322              : 
     323     55571072 :       if (!range_of_stmt (r, def_stmt, name))
     324        15158 :         r.set_varying (TREE_TYPE (name));
     325              :     }
     326              : 
     327     77710042 :   if (bb && POINTER_TYPE_P (TREE_TYPE (name)))
     328     12643124 :     infer_oracle ().maybe_adjust_range (r, name, bb);
     329              : 
     330     77710042 :   if (DEBUG_SOLVER && (bb || !r.varying_p ()))
     331              :     {
     332            0 :       fprintf (dump_file, "range_defined_in_block (BB%d) for ", bb ? bb->index : -1);
     333            0 :       print_generic_expr (dump_file, name, TDF_SLIM);
     334            0 :       fprintf (dump_file, " is ");
     335            0 :       r.dump (dump_file);
     336            0 :       fprintf (dump_file, "\n");
     337              :     }
     338              : 
     339              :   return true;
     340              : }
     341              : 
     342              : // Compute ranges defined in the PHIs in this block.
     343              : 
     344              : void
     345    104269492 : path_range_query::compute_ranges_in_phis (basic_block bb)
     346              : {
     347              :   // PHIs must be resolved simultaneously on entry to the block
     348              :   // because any dependencies must be satisfied with values on entry.
     349              :   // Thus, we calculate all PHIs first, and then update the cache at
     350              :   // the end.
     351              : 
     352    203149723 :   for (auto iter = gsi_start_phis (bb); !gsi_end_p (iter); gsi_next (&iter))
     353              :     {
     354     98880231 :       gphi *phi = iter.phi ();
     355     98880231 :       tree name = gimple_phi_result (phi);
     356              : 
     357     98880231 :       if (!exit_dependency_p (name))
     358     78232411 :         continue;
     359              : 
     360     20647820 :       value_range r (TREE_TYPE (name));
     361     20647820 :       if (range_defined_in_block (r, name, bb))
     362     20647820 :         m_cache.set_range (name, r);
     363     20647820 :     }
     364    104269492 : }
     365              : 
     366              : // Return TRUE if relations may be invalidated after crossing edge E.
     367              : 
     368              : bool
     369     45491617 : path_range_query::relations_may_be_invalidated (edge e)
     370              : {
     371              :   // As soon as the path crosses a back edge, we can encounter
     372              :   // definitions of SSA_NAMEs that may have had a use in the path
     373              :   // already, so this will then be a new definition.  The relation
     374              :   // code is all designed around seeing things in dominator order, and
     375              :   // crossing a back edge in the path violates this assumption.
     376     45491617 :   return (e->flags & EDGE_DFS_BACK);
     377              : }
     378              : 
     379              : // Compute ranges defined in the current block, or exported to the
     380              : // next block.
     381              : 
     382              : void
     383    104269492 : path_range_query::compute_ranges_in_block (basic_block bb)
     384              : {
     385    104269492 :   bitmap_iterator bi;
     386    104269492 :   unsigned i;
     387              : 
     388    164908346 :   if (m_resolve && !at_entry ())
     389     38250493 :     compute_phi_relations (bb, prev_bb ());
     390              : 
     391              :   // Force recalculation of any names in the cache that are defined in
     392              :   // this block.  This can happen on interdependent SSA/phis in loops.
     393    358501368 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     394              :     {
     395    254231876 :       tree name = ssa_name (i);
     396    254231876 :       if (ssa_defined_in_bb (name, bb))
     397     60215856 :         m_cache.clear_range (name);
     398              :     }
     399              : 
     400              :   // Solve dependencies defined in this block, starting with the PHIs...
     401    104269492 :   compute_ranges_in_phis (bb);
     402              :   // ...and then the rest of the dependencies.
     403    358501368 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     404              :     {
     405    254231876 :       tree name = ssa_name (i);
     406    254231876 :       value_range r (TREE_TYPE (name));
     407              : 
     408    254231876 :       if (gimple_code (SSA_NAME_DEF_STMT (name)) != GIMPLE_PHI
     409    254231876 :           && range_defined_in_block (r, name, bb))
     410     39568036 :         m_cache.set_range (name, r);
     411    254231876 :     }
     412              : 
     413    104269492 :   if (at_exit ())
     414     38173948 :     return;
     415              : 
     416              :   // Solve dependencies that are exported to the next block.
     417     66095544 :   basic_block next = next_bb ();
     418     66095544 :   edge e = find_edge (bb, next);
     419              : 
     420     66095544 :   if (m_resolve && relations_may_be_invalidated (e))
     421              :     {
     422      2169517 :       if (DEBUG_SOLVER)
     423            0 :         fprintf (dump_file,
     424              :                  "Resetting relations as they may be invalidated in %d->%d.\n",
     425            0 :                  e->src->index, e->dest->index);
     426              : 
     427      2169517 :       path_oracle *p = get_path_oracle ();
     428              :       // ?? Instead of nuking the root oracle altogether, we could
     429              :       // reset the path oracle to search for relations from the top of
     430              :       // the loop with the root oracle.  Something for future development.
     431      2169517 :       p->reset_path ();
     432              :     }
     433              : 
     434     66095544 :   bitmap exports = gori_ssa ()->exports (bb);
     435     82859521 :   EXECUTE_IF_AND_IN_BITMAP (m_exit_dependencies, exports, 0, i, bi)
     436              :     {
     437     16763977 :       tree name = ssa_name (i);
     438     16763977 :       value_range r (TREE_TYPE (name));
     439     16763977 :       if (gori ().edge_range_p (r, e, name, *this))
     440              :         {
     441     14947118 :           value_range cached_range (TREE_TYPE (name));
     442     14947118 :           if (get_cache (cached_range, name))
     443     11845512 :             r.intersect (cached_range);
     444              : 
     445     14947118 :           m_cache.set_range (name, r);
     446     14947118 :           if (DEBUG_SOLVER)
     447              :             {
     448            0 :               fprintf (dump_file, "edge_range_p for ");
     449            0 :               print_generic_expr (dump_file, name, TDF_SLIM);
     450            0 :               fprintf (dump_file, " on edge %d->%d ",
     451            0 :                        e->src->index, e->dest->index);
     452            0 :               fprintf (dump_file, "is ");
     453            0 :               r.dump (dump_file);
     454            0 :               fprintf (dump_file, "\n");
     455              :             }
     456     14947118 :         }
     457     16763977 :     }
     458              : 
     459     66095544 :   if (m_resolve)
     460     38250493 :     compute_outgoing_relations (bb, next);
     461              : }
     462              : 
     463              : // Adjust all pointer exit dependencies in BB with non-null information.
     464              : 
     465              : void
     466    104269492 : path_range_query::adjust_for_non_null_uses (basic_block bb)
     467              : {
     468              :   // If there are no pointer exit dependencies with an inferred range, there's
     469              :   // nothing to do.
     470    104269492 :   if (m_pointer_exit_dependencies.is_empty ()
     471     23587315 :       || !infer_oracle ().has_range_p (bb))
     472    100557308 :     return;
     473              : 
     474      3712184 :   prange r;
     475              : 
     476     20511269 :   for (tree name : m_pointer_exit_dependencies)
     477              :     {
     478      9374717 :       if (get_cache (r, name))
     479              :         {
     480      4086323 :           if (!r.contains_zero_p ())
     481      2322335 :             continue;
     482              :         }
     483              :       else
     484      5288394 :         r.set_varying (TREE_TYPE (name));
     485              : 
     486      7052382 :       if (infer_oracle ().maybe_adjust_range (r, name, bb))
     487       880083 :         m_cache.set_range (name, r);
     488              :     }
     489      3712184 : }
     490              : 
     491              : // If NAME is a supported SSA_NAME, add it to the bitmap in dependencies.
     492              : 
     493              : bool
     494       164008 : path_range_query::add_to_exit_dependencies (tree name, bitmap dependencies)
     495              : {
     496       164008 :   if (TREE_CODE (name) == SSA_NAME
     497       164008 :       && value_range::supports_type_p (TREE_TYPE (name)))
     498       164008 :     return bitmap_set_bit (dependencies, SSA_NAME_VERSION (name));
     499              :   return false;
     500              : }
     501              : 
     502              : // Compute the exit dependencies to PATH.  These are essentially the
     503              : // SSA names used to calculate the final conditional along the path.
     504              : 
     505              : void
     506       808983 : path_range_query::compute_exit_dependencies (bitmap dependencies)
     507              : {
     508              :   // Start with the imports from the exit block...
     509       808983 :   basic_block exit = m_path[0];
     510       808983 :   bitmap_copy (dependencies, gori_ssa ()->imports (exit));
     511              : 
     512       808983 :   auto_vec<tree> worklist (bitmap_count_bits (dependencies));
     513       808983 :   bitmap_iterator bi;
     514       808983 :   unsigned i;
     515      2079949 :   EXECUTE_IF_SET_IN_BITMAP (dependencies, 0, i, bi)
     516              :     {
     517      1270966 :       tree name = ssa_name (i);
     518      1270966 :       worklist.quick_push (name);
     519              :     }
     520              : 
     521              :   // ...and add any operands used to define these imports.
     522      4641960 :   while (!worklist.is_empty ())
     523              :     {
     524      1511997 :       tree name = worklist.pop ();
     525      1511997 :       gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     526      1840072 :       if (SSA_NAME_IS_DEFAULT_DEF (name)
     527      1511997 :           || !m_path.contains (gimple_bb (def_stmt)))
     528       328075 :         continue;
     529              : 
     530      1183922 :       if (gphi *phi = dyn_cast <gphi *> (def_stmt))
     531              :         {
     532      1907589 :           for (size_t i = 0; i < gimple_phi_num_args (phi); ++i)
     533              :             {
     534      1274434 :               edge e = gimple_phi_arg_edge (phi, i);
     535      1274434 :               tree arg = gimple_phi_arg (phi, i)->def;
     536              : 
     537      1274434 :               if (TREE_CODE (arg) == SSA_NAME
     538       806997 :                   && m_path.contains (e->src)
     539      1433908 :                   && bitmap_set_bit (dependencies, SSA_NAME_VERSION (arg)))
     540       148822 :                 worklist.safe_push (arg);
     541              :             }
     542              :         }
     543      2871747 :       else if (gassign *ass = dyn_cast <gassign *> (def_stmt))
     544              :         {
     545       512538 :           tree ssa[3];
     546       512538 :           unsigned count = gimple_range_ssa_names (ssa, 3, ass);
     547      1189084 :           for (unsigned j = 0; j < count; ++j)
     548       164008 :             if (add_to_exit_dependencies (ssa[j], dependencies))
     549        92209 :               worklist.safe_push (ssa[j]);
     550              :         }
     551              :     }
     552              :   // Exported booleans along the path, may help conditionals.
     553       808983 :   if (m_resolve)
     554      2657686 :     for (i = 0; i < m_path.length (); ++i)
     555              :       {
     556      1848703 :         basic_block bb = m_path[i];
     557      1848703 :         tree name;
     558      3765219 :         FOR_EACH_GORI_EXPORT_NAME (gori_ssa (), bb, name)
     559      1916516 :           if (TREE_CODE (TREE_TYPE (name)) == BOOLEAN_TYPE)
     560        58844 :             bitmap_set_bit (dependencies, SSA_NAME_VERSION (name));
     561              :       }
     562       808983 : }
     563              : 
     564              : // Compute the ranges for DEPENDENCIES along PATH.
     565              : //
     566              : // DEPENDENCIES are path exit dependencies.  They are the set of SSA
     567              : // names, any of which could potentially change the value of the final
     568              : // conditional in PATH.  If none is given, the exit dependencies are
     569              : // calculated from the final conditional in the path.
     570              : 
     571              : void
     572     38173948 : path_range_query::compute_ranges (const bitmap_head *dependencies)
     573              : {
     574     38173948 :   if (DEBUG_SOLVER)
     575            0 :     fprintf (dump_file, "\n==============================================\n");
     576              : 
     577     38173948 :   if (dependencies)
     578     37364965 :     bitmap_copy (m_exit_dependencies, dependencies);
     579              :   else
     580       808983 :     compute_exit_dependencies (m_exit_dependencies);
     581              : 
     582              :   // The oracle carries state from any previously solved path, so it has
     583              :   // to be reset even in non-resolving mode.
     584     38173948 :   path_oracle *p = get_path_oracle ();
     585     38173948 :   p->reset_path (&(m_ranger.relation ()));
     586              : 
     587              :   // Collect the pointer exit dependencies once per path.
     588     38173948 :   m_pointer_exit_dependencies.truncate (0);
     589     38173948 :   {
     590     38173948 :     bitmap_iterator bi;
     591     38173948 :     unsigned i;
     592    128222143 :     EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     593              :       {
     594     90048195 :         tree name = ssa_name (i);
     595     90048195 :         if (POINTER_TYPE_P (TREE_TYPE (name)))
     596              :           {
     597              :             // Querying the infer oracle here is what populates its
     598              :             // per-block summaries, so that adjust_for_non_null_uses can
     599              :             // skip a block with no inferred range in it at all.
     600     18018864 :             infer_oracle ().has_range_p (entry_bb (), name);
     601     18018864 :             m_pointer_exit_dependencies.safe_push (name);
     602              :           }
     603              :       }
     604              :   }
     605              : 
     606     38173948 :   if (DEBUG_SOLVER)
     607              :     {
     608            0 :       fprintf (dump_file, "path_range_query: compute_ranges for path: ");
     609            0 :       for (unsigned i = m_path.length (); i > 0; --i)
     610              :         {
     611            0 :           basic_block bb = m_path[i - 1];
     612            0 :           fprintf (dump_file, "%d", bb->index);
     613            0 :           if (i > 1)
     614            0 :             fprintf (dump_file, "->");
     615              :         }
     616            0 :       fprintf (dump_file, "\n");
     617              :     }
     618              : 
     619    170365036 :   while (1)
     620              :     {
     621    104269492 :       basic_block bb = curr_bb ();
     622              : 
     623    104269492 :       compute_ranges_in_block (bb);
     624    104269492 :       adjust_for_non_null_uses (bb);
     625              : 
     626    104269492 :       if (at_exit ())
     627              :         break;
     628              : 
     629     66095544 :       move_next ();
     630     66095544 :     }
     631              : 
     632     38173948 :   if (DEBUG_SOLVER)
     633              :     {
     634            0 :       get_path_oracle ()->dump (dump_file);
     635            0 :       dump (dump_file);
     636              :     }
     637     38173948 : }
     638              : 
     639              : // A folding aid used to register and query relations along a path.
     640              : // When queried, it returns relations as they would appear on exit to
     641              : // the path.
     642              : //
     643              : // Relations are registered on entry so the path_oracle knows which
     644              : // block to query the root oracle at when a relation lies outside the
     645              : // path.  However, when queried we return the relation on exit to the
     646              : // path, since the root_oracle ignores the registered.
     647              : 
     648              : class jt_fur_source : public fur_depend
     649              : {
     650              : public:
     651              :   jt_fur_source (gimple *s, path_range_query *, const vec<basic_block> &);
     652              :   relation_kind query_relation (tree op1, tree op2) override;
     653              :   bool register_relation (gimple *, relation_kind, tree op1, tree op2) override;
     654              :   bool register_relation (edge, relation_kind, tree op1, tree op2) override;
     655              : private:
     656              :   basic_block m_entry;
     657              : };
     658              : 
     659     80780488 : jt_fur_source::jt_fur_source (gimple *s,
     660              :                               path_range_query *query,
     661              :                               const vec<basic_block> &path)
     662     80780488 :   : fur_depend (s, query)
     663              : {
     664     80780488 :   gcc_checking_assert (!path.is_empty ());
     665              : 
     666     80780488 :   m_entry = path[path.length () - 1];
     667     80780488 : }
     668              : 
     669              : // Ignore statement and register relation on entry to path.  Return false if
     670              : // no new relation is registered.
     671              : 
     672              : bool
     673     10740710 : jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2)
     674              : {
     675     10740710 :   return m_query->relation ().record (m_entry, k, op1, op2);
     676              : }
     677              : 
     678              : // Ignore edge and register relation on entry to path.  Return false if no
     679              : // new relation is registered.
     680              : 
     681              : bool
     682     14800608 : jt_fur_source::register_relation (edge, relation_kind k, tree op1, tree op2)
     683              : {
     684     14800608 :   return m_query->relation ().record (m_entry, k, op1, op2);
     685              : }
     686              : 
     687              : relation_kind
     688     38997319 : jt_fur_source::query_relation (tree op1, tree op2)
     689              : {
     690     38997319 :   if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
     691              :     return VREL_VARYING;
     692              : 
     693     13691615 :   return m_query->relation ().query (m_entry, op1, op2);
     694              : }
     695              : 
     696              : // Return the range of STMT at the end of the path being analyzed.
     697              : 
     698              : bool
     699     94944052 : path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
     700              : {
     701     94944052 :   tree type = gimple_range_type (stmt);
     702              : 
     703     94944052 :   if (!type || !r.supports_type_p (type))
     704              :     return false;
     705              : 
     706              :   // If resolving unknowns, fold the statement making use of any
     707              :   // relations along the path.
     708     94928894 :   if (m_resolve)
     709              :     {
     710     56533497 :       fold_using_range f;
     711     56533497 :       jt_fur_source src (stmt, this, m_path);
     712     56533497 :       if (!f.fold_stmt (r, stmt, src))
     713         4956 :         r.set_varying (type);
     714              :     }
     715              :   // Otherwise, fold without relations.
     716     38395397 :   else if (!fold_range (r, stmt, this))
     717            0 :     r.set_varying (type);
     718              : 
     719              :   return true;
     720              : }
     721              : 
     722              : // If possible, register the relation on the incoming edge E into PHI.
     723              : 
     724              : void
     725      9567438 : path_range_query::maybe_register_phi_relation (gphi *phi, edge e)
     726              : {
     727      9567438 :   tree arg = gimple_phi_arg_def (phi, e->dest_idx);
     728              : 
     729      9567438 :   if (!gimple_range_ssa_p (arg))
     730              :     return;
     731              : 
     732      7241124 :   if (relations_may_be_invalidated (e))
     733              :     return;
     734              : 
     735      5302382 :   basic_block bb = gimple_bb (phi);
     736      5302382 :   tree result = gimple_phi_result (phi);
     737              : 
     738              :   // Avoid recording the equivalence if the arg is defined in this
     739              :   // block, as that could create an ordering problem.
     740      5302382 :   if (ssa_defined_in_bb (arg, bb))
     741              :     return;
     742              : 
     743      5302382 :   if (dump_file && (dump_flags & TDF_DETAILS))
     744           66 :     fprintf (dump_file, "maybe_register_phi_relation in bb%d:", bb->index);
     745              : 
     746      5302382 :   get_path_oracle ()->killing_def (result);
     747      5302382 :   m_relation->record (entry_bb (), VREL_EQ, arg, result);
     748              : }
     749              : 
     750              : // Compute relations for each PHI in BB.  For example:
     751              : //
     752              : //   x_5 = PHI<y_9(5),...>
     753              : //
     754              : // If the path flows through BB5, we can register that x_5 == y_9.
     755              : 
     756              : void
     757     38250493 : path_range_query::compute_phi_relations (basic_block bb, basic_block prev)
     758              : {
     759     38250493 :   if (prev == NULL)
     760              :     return;
     761              : 
     762     38250493 :   edge e_in = find_edge (prev, bb);
     763              : 
     764     84025896 :   for (gphi_iterator iter = gsi_start_phis (bb); !gsi_end_p (iter);
     765     45775403 :        gsi_next (&iter))
     766              :     {
     767     45775403 :       gphi *phi = iter.phi ();
     768     45775403 :       tree result = gimple_phi_result (phi);
     769     45775403 :       unsigned nargs = gimple_phi_num_args (phi);
     770              : 
     771     45775403 :       if (!exit_dependency_p (result))
     772     36207965 :         continue;
     773              : 
     774     17792756 :       for (size_t i = 0; i < nargs; ++i)
     775     17792756 :         if (e_in == gimple_phi_arg_edge (phi, i))
     776              :           {
     777      9567438 :             maybe_register_phi_relation (phi, e_in);
     778      9567438 :             break;
     779              :           }
     780              :     }
     781              : }
     782              : 
     783              : // Compute outgoing relations from BB to NEXT.
     784              : 
     785              : void
     786     38250493 : path_range_query::compute_outgoing_relations (basic_block bb, basic_block next)
     787              : {
     788     76500986 :   if (gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (bb)))
     789              :     {
     790     24246991 :       int_range<2> r;
     791     24246991 :       edge e0 = EDGE_SUCC (bb, 0);
     792     24246991 :       edge e1 = EDGE_SUCC (bb, 1);
     793              : 
     794     24246991 :       if (e0->dest == next)
     795     10356960 :         gcond_edge_range (r, e0);
     796     13890031 :       else if (e1->dest == next)
     797     13890031 :         gcond_edge_range (r, e1);
     798              :       else
     799            0 :         gcc_unreachable ();
     800              : 
     801     24246991 :       jt_fur_source src (NULL, this, m_path);
     802     24246991 :       src.register_outgoing_edges (cond, r, e0, e1);
     803     24246991 :     }
     804     38250493 : }
        

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.