LCOV - code coverage report
Current view: top level - gcc - gimple-range-path.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.0 % 346 301
Test Date: 2026-03-28 14:25:54 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     26916003 : path_range_query::path_range_query (gimple_ranger &ranger,
      40              :                                     const vec<basic_block> &path,
      41              :                                     const bitmap_head *dependencies,
      42     26916003 :                                     bool resolve)
      43     26916003 :   : m_cache (),
      44     26916003 :     m_ranger (ranger),
      45     26916003 :     m_resolve (resolve)
      46              : {
      47     26916003 :   share_query (ranger);
      48              :   // Override the relation oracle with a local path relation oracle.
      49     26916003 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      50              : 
      51     26916003 :   reset_path (path, dependencies);
      52     26916003 : }
      53              : 
      54      2076319 : path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
      55      2076319 :   : m_cache (),
      56      2076319 :     m_ranger (ranger),
      57      2076319 :     m_resolve (resolve)
      58              : {
      59      2076319 :   share_query (ranger);
      60              :   // Override the relation oracle with a local path relation oracle.
      61      2076319 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      62      2076319 : }
      63              : 
      64     29779757 : path_range_query::~path_range_query ()
      65              : {
      66     28992322 :   delete m_relation;
      67     28992322 :   m_relation = NULL;
      68     29779757 : }
      69              : 
      70              : // Return TRUE if NAME is an exit dependency for the path.
      71              : 
      72              : bool
      73    129808141 : path_range_query::exit_dependency_p (tree name)
      74              : {
      75    129808141 :   return (TREE_CODE (name) == SSA_NAME
      76    129808141 :           && 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    345749542 : path_range_query::get_cache (vrange &r, tree name)
      83              : {
      84    345749542 :   if (!gimple_range_ssa_p (name))
      85     61278439 :     return get_global_range_query ()->range_of_expr (r, name);
      86              : 
      87    284471103 :   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     55337995 : path_range_query::defined_outside_path (tree name)
     124              : {
     125     55337995 :   gimple *def = SSA_NAME_DEF_STMT (name);
     126     55337995 :   basic_block bb = gimple_bb (def);
     127              : 
     128     55337995 :   return !bb || !m_path.contains (bb);
     129              : }
     130              : 
     131              : // Return the range of NAME on entry to the path.
     132              : 
     133              : void
     134     20641354 : path_range_query::range_on_path_entry (vrange &r, tree name)
     135              : {
     136     20641354 :   gcc_checking_assert (defined_outside_path (name));
     137     20641354 :   basic_block entry = entry_bb ();
     138     20641354 :   m_ranger.range_on_entry (r, entry, name);
     139     20641354 : }
     140              : 
     141              : // Return the range of NAME at the end of the path being analyzed.
     142              : 
     143              : bool
     144    196590933 : path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
     145              : {
     146    196590933 :   if (!r.supports_type_p (TREE_TYPE (name)))
     147              :     return false;
     148              : 
     149    196590933 :   if (get_cache (r, name))
     150              :     return true;
     151              : 
     152     56268474 :   if (m_resolve && defined_outside_path (name))
     153              :     {
     154     19211461 :       range_on_path_entry (r, name);
     155     19211461 :       m_cache.set_range (name, r);
     156     19211461 :       return true;
     157              :     }
     158              : 
     159     37057013 :   if (stmt
     160     37057013 :       && range_defined_in_block (r, name, gimple_bb (stmt)))
     161              :     {
     162     17588224 :       if (TREE_CODE (name) == SSA_NAME)
     163              :         {
     164     17588224 :           value_range glob (TREE_TYPE (name));
     165     17588224 :           gimple_range_global (glob, name);
     166     17588224 :           r.intersect (glob);
     167     17588224 :         }
     168              : 
     169     17588224 :       m_cache.set_range (name, r);
     170     17588224 :       return true;
     171              :     }
     172              : 
     173     19468789 :   gimple_range_global (r, name);
     174     19468789 :   return true;
     175              : }
     176              : 
     177              : bool
     178    196590933 : path_range_query::range_of_expr (vrange &r, tree name, gimple *stmt)
     179              : {
     180    196590933 :   if (internal_range_of_expr (r, name, stmt))
     181              :     {
     182    196590933 :       if (r.undefined_p ())
     183       149165 :         m_undefined_path = true;
     184              : 
     185    196590933 :       return true;
     186              :     }
     187              :   return false;
     188              : }
     189              : 
     190              : bool
     191     26004889 : path_range_query::unreachable_path_p ()
     192              : {
     193     26004889 :   return m_undefined_path;
     194              : }
     195              : 
     196              : // Reset the current path to PATH.
     197              : 
     198              : void
     199     35558533 : path_range_query::reset_path (const vec<basic_block> &path,
     200              :                               const bitmap_head *dependencies)
     201              : {
     202     35558533 :   gcc_checking_assert (path.length () > 1);
     203     35558533 :   m_path = path.copy ();
     204     35558533 :   m_pos = m_path.length () - 1;
     205     35558533 :   m_undefined_path = false;
     206     35558533 :   m_cache.clear ();
     207              : 
     208     35558533 :   compute_ranges (dependencies);
     209     35558533 : }
     210              : 
     211              : bool
     212    252746925 : path_range_query::ssa_defined_in_bb (tree name, basic_block bb)
     213              : {
     214    252746925 :   return (TREE_CODE (name) == SSA_NAME
     215    250417980 :           && SSA_NAME_DEF_STMT (name)
     216    503164905 :           && gimple_bb (SSA_NAME_DEF_STMT (name)) == bb);
     217              : }
     218              : 
     219              : // Return the range of the result of PHI in R.
     220              : //
     221              : // Since PHIs are calculated in parallel at the beginning of the
     222              : // block, we must be careful to never save anything to the cache here.
     223              : // It is the caller's responsibility to adjust the cache.  Also,
     224              : // calculating the PHI's range must not trigger additional lookups.
     225              : 
     226              : void
     227     18952008 : path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
     228              : {
     229     18952008 :   tree name = gimple_phi_result (phi);
     230              : 
     231     37904016 :   if (at_entry ())
     232              :     {
     233      3881157 :       if (m_resolve && m_ranger.range_of_expr (r, name, phi))
     234              :         return;
     235              : 
     236              :       // Try to fold the phi exclusively with global values.
     237              :       // This will get things like PHI <5(99), 6(88)>.  We do this by
     238              :       // calling range_of_expr with no context.
     239      1916644 :       unsigned nargs = gimple_phi_num_args (phi);
     240      1916644 :       value_range arg_range (TREE_TYPE (name));
     241      1916644 :       r.set_undefined ();
     242      6254510 :       for (size_t i = 0; i < nargs; ++i)
     243              :         {
     244      4337866 :           tree arg = gimple_phi_arg_def (phi, i);
     245      4337866 :           if (m_ranger.range_of_expr (arg_range, arg, /*stmt=*/NULL))
     246      4337866 :             r.union_ (arg_range);
     247              :           else
     248              :             {
     249            0 :               r.set_varying (TREE_TYPE (name));
     250            0 :               return;
     251              :             }
     252              :         }
     253              :       return;
     254      1916644 :     }
     255              : 
     256     15070851 :   basic_block bb = gimple_bb (phi);
     257     15070851 :   basic_block prev = prev_bb ();
     258     15070851 :   edge e_in = find_edge (prev, bb);
     259     15070851 :   tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e_in);
     260              :   // Avoid using the cache for ARGs defined in this block, as
     261              :   // that could create an ordering problem.
     262     15070851 :   if (ssa_defined_in_bb (arg, bb) || !get_cache (r, arg))
     263              :     {
     264      4623897 :       if (m_resolve)
     265              :         {
     266      2622473 :           value_range tmp (TREE_TYPE (name));
     267              :           // Using both the range on entry to the path, and the
     268              :           // range on this edge yields significantly better
     269              :           // results.
     270      2622473 :           if (TREE_CODE (arg) == SSA_NAME
     271      2622473 :               && defined_outside_path (arg))
     272      1429893 :             range_on_path_entry (r, arg);
     273              :           else
     274      1192580 :             r.set_varying (TREE_TYPE (name));
     275      2622473 :           m_ranger.range_on_edge (tmp, e_in, arg);
     276      2622473 :           r.intersect (tmp);
     277      2622473 :           return;
     278      2622473 :         }
     279      2001424 :       r.set_varying (TREE_TYPE (name));
     280              :     }
     281              : }
     282              : 
     283              : // If NAME is defined in BB, set R to the range of NAME, and return
     284              : // TRUE.  Otherwise, return FALSE.
     285              : 
     286              : bool
     287    215963225 : path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb)
     288              : {
     289    215963225 :   gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     290    215963225 :   basic_block def_bb = gimple_bb (def_stmt);
     291              : 
     292    215963225 :   if (def_bb != bb)
     293              :     return false;
     294              : 
     295     72962637 :   if (get_cache (r, name))
     296              :     return true;
     297              : 
     298     71235550 :   if (gimple_code (def_stmt) == GIMPLE_PHI)
     299     18952008 :     ssa_range_in_phi (r, as_a<gphi *> (def_stmt));
     300              :   else
     301              :     {
     302     52283542 :       if (name)
     303     52283542 :         get_path_oracle ()->killing_def (name);
     304              : 
     305     52283542 :       if (!range_of_stmt (r, def_stmt, name))
     306        14607 :         r.set_varying (TREE_TYPE (name));
     307              :     }
     308              : 
     309     71235550 :   if (bb && POINTER_TYPE_P (TREE_TYPE (name)))
     310     11004507 :     infer_oracle ().maybe_adjust_range (r, name, bb);
     311              : 
     312     71235550 :   if (DEBUG_SOLVER && (bb || !r.varying_p ()))
     313              :     {
     314            0 :       fprintf (dump_file, "range_defined_in_block (BB%d) for ", bb ? bb->index : -1);
     315            0 :       print_generic_expr (dump_file, name, TDF_SLIM);
     316            0 :       fprintf (dump_file, " is ");
     317            0 :       r.dump (dump_file);
     318            0 :       fprintf (dump_file, "\n");
     319              :     }
     320              : 
     321              :   return true;
     322              : }
     323              : 
     324              : // Compute ranges defined in the PHIs in this block.
     325              : 
     326              : void
     327     97901022 : path_range_query::compute_ranges_in_phis (basic_block bb)
     328              : {
     329              :   // PHIs must be resolved simultaneously on entry to the block
     330              :   // because any dependencies must be satisfied with values on entry.
     331              :   // Thus, we calculate all PHIs first, and then update the cache at
     332              :   // the end.
     333              : 
     334    186415110 :   for (auto iter = gsi_start_phis (bb); !gsi_end_p (iter); gsi_next (&iter))
     335              :     {
     336     88514088 :       gphi *phi = iter.phi ();
     337     88514088 :       tree name = gimple_phi_result (phi);
     338              : 
     339     88514088 :       if (!exit_dependency_p (name))
     340     70855265 :         continue;
     341              : 
     342     17658823 :       value_range r (TREE_TYPE (name));
     343     17658823 :       if (range_defined_in_block (r, name, bb))
     344     17658823 :         m_cache.set_range (name, r);
     345     17658823 :     }
     346     97901022 : }
     347              : 
     348              : // Return TRUE if relations may be invalidated after crossing edge E.
     349              : 
     350              : bool
     351     43037181 : path_range_query::relations_may_be_invalidated (edge e)
     352              : {
     353              :   // As soon as the path crosses a back edge, we can encounter
     354              :   // definitions of SSA_NAMEs that may have had a use in the path
     355              :   // already, so this will then be a new definition.  The relation
     356              :   // code is all designed around seeing things in dominator order, and
     357              :   // crossing a back edge in the path violates this assumption.
     358     43037181 :   return (e->flags & EDGE_DFS_BACK);
     359              : }
     360              : 
     361              : // Compute ranges defined in the current block, or exported to the
     362              : // next block.
     363              : 
     364              : void
     365     97901022 : path_range_query::compute_ranges_in_block (basic_block bb)
     366              : {
     367     97901022 :   bitmap_iterator bi;
     368     97901022 :   unsigned i;
     369              : 
     370    155422617 :   if (m_resolve && !at_entry ())
     371     36356354 :     compute_phi_relations (bb, prev_bb ());
     372              : 
     373              :   // Force recalculation of any names in the cache that are defined in
     374              :   // this block.  This can happen on interdependent SSA/phis in loops.
     375    331157840 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     376              :     {
     377    233256818 :       tree name = ssa_name (i);
     378    233256818 :       if (ssa_defined_in_bb (name, bb))
     379     55374413 :         m_cache.clear_range (name);
     380              :     }
     381              : 
     382              :   // Solve dependencies defined in this block, starting with the PHIs...
     383     97901022 :   compute_ranges_in_phis (bb);
     384              :   // ...and then the rest of the dependencies.
     385    331157840 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     386              :     {
     387    233256818 :       tree name = ssa_name (i);
     388    233256818 :       value_range r (TREE_TYPE (name));
     389              : 
     390    233256818 :       if (gimple_code (SSA_NAME_DEF_STMT (name)) != GIMPLE_PHI
     391    233256818 :           && range_defined_in_block (r, name, bb))
     392     37715590 :         m_cache.set_range (name, r);
     393    233256818 :     }
     394              : 
     395     97901022 :   if (at_exit ())
     396     35558533 :     return;
     397              : 
     398              :   // Solve dependencies that are exported to the next block.
     399     62342489 :   basic_block next = next_bb ();
     400     62342489 :   edge e = find_edge (bb, next);
     401              : 
     402     62342489 :   if (m_resolve && relations_may_be_invalidated (e))
     403              :     {
     404      2510167 :       if (DEBUG_SOLVER)
     405            0 :         fprintf (dump_file,
     406              :                  "Resetting relations as they may be invalidated in %d->%d.\n",
     407            0 :                  e->src->index, e->dest->index);
     408              : 
     409      2510167 :       path_oracle *p = get_path_oracle ();
     410              :       // ?? Instead of nuking the root oracle altogether, we could
     411              :       // reset the path oracle to search for relations from the top of
     412              :       // the loop with the root oracle.  Something for future development.
     413      2510167 :       p->reset_path ();
     414              :     }
     415              : 
     416     62342489 :   bitmap exports = gori_ssa ()->exports (bb);
     417     80813537 :   EXECUTE_IF_AND_IN_BITMAP (m_exit_dependencies, exports, 0, i, bi)
     418              :     {
     419     18471048 :       tree name = ssa_name (i);
     420     18471048 :       value_range r (TREE_TYPE (name));
     421     18471048 :       if (gori ().edge_range_p (r, e, name, *this))
     422              :         {
     423     16629170 :           value_range cached_range (TREE_TYPE (name));
     424     16629170 :           if (get_cache (cached_range, name))
     425     13176145 :             r.intersect (cached_range);
     426              : 
     427     16629170 :           m_cache.set_range (name, r);
     428     16629170 :           if (DEBUG_SOLVER)
     429              :             {
     430            0 :               fprintf (dump_file, "edge_range_p for ");
     431            0 :               print_generic_expr (dump_file, name, TDF_SLIM);
     432            0 :               fprintf (dump_file, " on edge %d->%d ",
     433            0 :                        e->src->index, e->dest->index);
     434            0 :               fprintf (dump_file, "is ");
     435            0 :               r.dump (dump_file);
     436            0 :               fprintf (dump_file, "\n");
     437              :             }
     438     16629170 :         }
     439     18471048 :     }
     440              : 
     441     62342489 :   if (m_resolve)
     442     36356354 :     compute_outgoing_relations (bb, next);
     443              : }
     444              : 
     445              : // Adjust all pointer exit dependencies in BB with non-null information.
     446              : 
     447              : void
     448     97901022 : path_range_query::adjust_for_non_null_uses (basic_block bb)
     449              : {
     450     97901022 :   prange r;
     451     97901022 :   bitmap_iterator bi;
     452     97901022 :   unsigned i;
     453              : 
     454    331157840 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     455              :     {
     456    233256818 :       tree name = ssa_name (i);
     457              : 
     458    233256818 :       if (!POINTER_TYPE_P (TREE_TYPE (name)))
     459    187560349 :         continue;
     460              : 
     461     45696469 :       if (get_cache (r, name))
     462              :         {
     463     19206437 :           if (r.nonzero_p ())
     464      7781211 :             continue;
     465              :         }
     466              :       else
     467     26490032 :         r.set_varying (TREE_TYPE (name));
     468              : 
     469     37915258 :       if (infer_oracle ().maybe_adjust_range (r, name, bb))
     470       805929 :         m_cache.set_range (name, r);
     471              :     }
     472     97901022 : }
     473              : 
     474              : // If NAME is a supported SSA_NAME, add it to the bitmap in dependencies.
     475              : 
     476              : bool
     477       161682 : path_range_query::add_to_exit_dependencies (tree name, bitmap dependencies)
     478              : {
     479       161682 :   if (TREE_CODE (name) == SSA_NAME
     480       161682 :       && value_range::supports_type_p (TREE_TYPE (name)))
     481       161682 :     return bitmap_set_bit (dependencies, SSA_NAME_VERSION (name));
     482              :   return false;
     483              : }
     484              : 
     485              : // Compute the exit dependencies to PATH.  These are essentially the
     486              : // SSA names used to calculate the final conditional along the path.
     487              : 
     488              : void
     489       787435 : path_range_query::compute_exit_dependencies (bitmap dependencies)
     490              : {
     491              :   // Start with the imports from the exit block...
     492       787435 :   basic_block exit = m_path[0];
     493       787435 :   bitmap_copy (dependencies, gori_ssa ()->imports (exit));
     494              : 
     495       787435 :   auto_vec<tree> worklist (bitmap_count_bits (dependencies));
     496       787435 :   bitmap_iterator bi;
     497       787435 :   unsigned i;
     498      2020719 :   EXECUTE_IF_SET_IN_BITMAP (dependencies, 0, i, bi)
     499              :     {
     500      1233284 :       tree name = ssa_name (i);
     501      1233284 :       worklist.quick_push (name);
     502              :     }
     503              : 
     504              :   // ...and add any operands used to define these imports.
     505      4525826 :   while (!worklist.is_empty ())
     506              :     {
     507      1475478 :       tree name = worklist.pop ();
     508      1475478 :       gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     509      1799766 :       if (SSA_NAME_IS_DEFAULT_DEF (name)
     510      1475478 :           || !m_path.contains (gimple_bb (def_stmt)))
     511       324288 :         continue;
     512              : 
     513      1151190 :       if (gphi *phi = dyn_cast <gphi *> (def_stmt))
     514              :         {
     515      1888906 :           for (size_t i = 0; i < gimple_phi_num_args (phi); ++i)
     516              :             {
     517      1261935 :               edge e = gimple_phi_arg_edge (phi, i);
     518      1261935 :               tree arg = gimple_phi_arg (phi, i)->def;
     519              : 
     520      1261935 :               if (TREE_CODE (arg) == SSA_NAME
     521       800530 :                   && m_path.contains (e->src)
     522      1422865 :                   && bitmap_set_bit (dependencies, SSA_NAME_VERSION (arg)))
     523       150459 :                 worklist.safe_push (arg);
     524              :             }
     525              :         }
     526      2787132 :       else if (gassign *ass = dyn_cast <gassign *> (def_stmt))
     527              :         {
     528       479248 :           tree ssa[3];
     529       479248 :           unsigned count = gimple_range_ssa_names (ssa, 3, ass);
     530       640930 :           for (unsigned j = 0; j < count; ++j)
     531       161682 :             if (add_to_exit_dependencies (ssa[j], dependencies))
     532        91735 :               worklist.safe_push (ssa[j]);
     533              :         }
     534              :     }
     535              :   // Exported booleans along the path, may help conditionals.
     536       787435 :   if (m_resolve)
     537      2574253 :     for (i = 0; i < m_path.length (); ++i)
     538              :       {
     539      1786818 :         basic_block bb = m_path[i];
     540      1786818 :         tree name;
     541      3637407 :         FOR_EACH_GORI_EXPORT_NAME (gori_ssa (), bb, name)
     542      1850589 :           if (TREE_CODE (TREE_TYPE (name)) == BOOLEAN_TYPE)
     543        57563 :             bitmap_set_bit (dependencies, SSA_NAME_VERSION (name));
     544              :       }
     545       787435 : }
     546              : 
     547              : // Compute the ranges for DEPENDENCIES along PATH.
     548              : //
     549              : // DEPENDENCIES are path exit dependencies.  They are the set of SSA
     550              : // names, any of which could potentially change the value of the final
     551              : // conditional in PATH.  If none is given, the exit dependencies are
     552              : // calculated from the final conditional in the path.
     553              : 
     554              : void
     555     35558533 : path_range_query::compute_ranges (const bitmap_head *dependencies)
     556              : {
     557     35558533 :   if (DEBUG_SOLVER)
     558            0 :     fprintf (dump_file, "\n==============================================\n");
     559              : 
     560     35558533 :   if (dependencies)
     561     34771098 :     bitmap_copy (m_exit_dependencies, dependencies);
     562              :   else
     563       787435 :     compute_exit_dependencies (m_exit_dependencies);
     564              : 
     565     35558533 :   if (m_resolve)
     566              :     {
     567     21165241 :       path_oracle *p = get_path_oracle ();
     568     21165241 :       p->reset_path (&(m_ranger.relation ()));
     569              :     }
     570              : 
     571     35558533 :   if (DEBUG_SOLVER)
     572              :     {
     573            0 :       fprintf (dump_file, "path_range_query: compute_ranges for path: ");
     574            0 :       for (unsigned i = m_path.length (); i > 0; --i)
     575              :         {
     576            0 :           basic_block bb = m_path[i - 1];
     577            0 :           fprintf (dump_file, "%d", bb->index);
     578            0 :           if (i > 1)
     579            0 :             fprintf (dump_file, "->");
     580              :         }
     581            0 :       fprintf (dump_file, "\n");
     582              :     }
     583              : 
     584     62342489 :   while (1)
     585              :     {
     586     97901022 :       basic_block bb = curr_bb ();
     587              : 
     588     97901022 :       compute_ranges_in_block (bb);
     589     97901022 :       adjust_for_non_null_uses (bb);
     590              : 
     591     97901022 :       if (at_exit ())
     592              :         break;
     593              : 
     594     62342489 :       move_next ();
     595              :     }
     596              : 
     597     35558533 :   if (DEBUG_SOLVER)
     598              :     {
     599            0 :       get_path_oracle ()->dump (dump_file);
     600            0 :       dump (dump_file);
     601              :     }
     602     35558533 : }
     603              : 
     604              : // A folding aid used to register and query relations along a path.
     605              : // When queried, it returns relations as they would appear on exit to
     606              : // the path.
     607              : //
     608              : // Relations are registered on entry so the path_oracle knows which
     609              : // block to query the root oracle at when a relation lies outside the
     610              : // path.  However, when queried we return the relation on exit to the
     611              : // path, since the root_oracle ignores the registered.
     612              : 
     613              : class jt_fur_source : public fur_depend
     614              : {
     615              : public:
     616              :   jt_fur_source (gimple *s, path_range_query *, const vec<basic_block> &);
     617              :   relation_kind query_relation (tree op1, tree op2) override;
     618              :   bool register_relation (gimple *, relation_kind, tree op1, tree op2) override;
     619              :   bool register_relation (edge, relation_kind, tree op1, tree op2) override;
     620              : private:
     621              :   basic_block m_entry;
     622              : };
     623              : 
     624     77376967 : jt_fur_source::jt_fur_source (gimple *s,
     625              :                               path_range_query *query,
     626     77376967 :                               const vec<basic_block> &path)
     627     77376967 :   : fur_depend (s, query)
     628              : {
     629     77376967 :   gcc_checking_assert (!path.is_empty ());
     630              : 
     631     77376967 :   m_entry = path[path.length () - 1];
     632     77376967 : }
     633              : 
     634              : // Ignore statement and register relation on entry to path.  Return false if
     635              : // no new relation is registered.
     636              : 
     637              : bool
     638     10303438 : jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2)
     639              : {
     640     10303438 :   return m_query->relation ().record (m_entry, k, op1, op2);
     641              : }
     642              : 
     643              : // Ignore edge and register relation on entry to path.  Return false if no
     644              : // new relation is registered.
     645              : 
     646              : bool
     647     13455792 : jt_fur_source::register_relation (edge, relation_kind k, tree op1, tree op2)
     648              : {
     649     13455792 :   return m_query->relation ().record (m_entry, k, op1, op2);
     650              : }
     651              : 
     652              : relation_kind
     653     37264992 : jt_fur_source::query_relation (tree op1, tree op2)
     654              : {
     655     37264992 :   if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
     656              :     return VREL_VARYING;
     657              : 
     658     12611018 :   return m_query->relation ().query (m_entry, op1, op2);
     659              : }
     660              : 
     661              : // Return the range of STMT at the end of the path being analyzed.
     662              : 
     663              : bool
     664     88997977 : path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
     665              : {
     666     88997977 :   tree type = gimple_range_type (stmt);
     667              : 
     668     88997977 :   if (!type || !r.supports_type_p (type))
     669        14607 :     return false;
     670              : 
     671              :   // If resolving unknowns, fold the statement making use of any
     672              :   // relations along the path.
     673     88983370 :   if (m_resolve)
     674              :     {
     675     53785053 :       fold_using_range f;
     676     53785053 :       jt_fur_source src (stmt, this, m_path);
     677     53785053 :       if (!f.fold_stmt (r, stmt, src))
     678         5450 :         r.set_varying (type);
     679              :     }
     680              :   // Otherwise, fold without relations.
     681     35198317 :   else if (!fold_range (r, stmt, this))
     682            0 :     r.set_varying (type);
     683              : 
     684              :   return true;
     685              : }
     686              : 
     687              : // If possible, register the relation on the incoming edge E into PHI.
     688              : 
     689              : void
     690      8074012 : path_range_query::maybe_register_phi_relation (gphi *phi, edge e)
     691              : {
     692      8074012 :   tree arg = gimple_phi_arg_def (phi, e->dest_idx);
     693              : 
     694      8074012 :   if (!gimple_range_ssa_p (arg))
     695              :     return;
     696              : 
     697      6680827 :   if (relations_may_be_invalidated (e))
     698              :     return;
     699              : 
     700      4419256 :   basic_block bb = gimple_bb (phi);
     701      4419256 :   tree result = gimple_phi_result (phi);
     702              : 
     703              :   // Avoid recording the equivalence if the arg is defined in this
     704              :   // block, as that could create an ordering problem.
     705      4419256 :   if (ssa_defined_in_bb (arg, bb))
     706              :     return;
     707              : 
     708      4419256 :   if (dump_file && (dump_flags & TDF_DETAILS))
     709           50 :     fprintf (dump_file, "maybe_register_phi_relation in bb%d:", bb->index);
     710              : 
     711      4419256 :   get_path_oracle ()->killing_def (result);
     712      4419256 :   m_relation->record (entry_bb (), VREL_EQ, arg, result);
     713              : }
     714              : 
     715              : // Compute relations for each PHI in BB.  For example:
     716              : //
     717              : //   x_5 = PHI<y_9(5),...>
     718              : //
     719              : // If the path flows through BB5, we can register that x_5 == y_9.
     720              : 
     721              : void
     722     36356354 : path_range_query::compute_phi_relations (basic_block bb, basic_block prev)
     723              : {
     724     36356354 :   if (prev == NULL)
     725              :     return;
     726              : 
     727     36356354 :   edge e_in = find_edge (prev, bb);
     728              : 
     729     77650407 :   for (gphi_iterator iter = gsi_start_phis (bb); !gsi_end_p (iter);
     730     41294053 :        gsi_next (&iter))
     731              :     {
     732     41294053 :       gphi *phi = iter.phi ();
     733     41294053 :       tree result = gimple_phi_result (phi);
     734     41294053 :       unsigned nargs = gimple_phi_num_args (phi);
     735              : 
     736     41294053 :       if (!exit_dependency_p (result))
     737     33220041 :         continue;
     738              : 
     739     15687350 :       for (size_t i = 0; i < nargs; ++i)
     740     15687350 :         if (e_in == gimple_phi_arg_edge (phi, i))
     741              :           {
     742      8074012 :             maybe_register_phi_relation (phi, e_in);
     743      8074012 :             break;
     744              :           }
     745              :     }
     746              : }
     747              : 
     748              : // Compute outgoing relations from BB to NEXT.
     749              : 
     750              : void
     751     36356354 : path_range_query::compute_outgoing_relations (basic_block bb, basic_block next)
     752              : {
     753     72712708 :   if (gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (bb)))
     754              :     {
     755     23591914 :       int_range<2> r;
     756     23591914 :       edge e0 = EDGE_SUCC (bb, 0);
     757     23591914 :       edge e1 = EDGE_SUCC (bb, 1);
     758              : 
     759     23591914 :       if (e0->dest == next)
     760     10119098 :         gcond_edge_range (r, e0);
     761     13472816 :       else if (e1->dest == next)
     762     13472816 :         gcond_edge_range (r, e1);
     763              :       else
     764            0 :         gcc_unreachable ();
     765              : 
     766     23591914 :       jt_fur_source src (NULL, this, m_path);
     767     23591914 :       src.register_outgoing_edges (cond, r, e0, e1);
     768     23591914 :     }
     769     36356354 : }
        

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.