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-04-20 14:57:17 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     26691316 : path_range_query::path_range_query (gimple_ranger &ranger,
      40              :                                     const vec<basic_block> &path,
      41              :                                     const bitmap_head *dependencies,
      42     26691316 :                                     bool resolve)
      43     26691316 :   : m_cache (),
      44     26691316 :     m_ranger (ranger),
      45     26691316 :     m_resolve (resolve)
      46              : {
      47     26691316 :   share_query (ranger);
      48              :   // Override the relation oracle with a local path relation oracle.
      49     26691316 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      50              : 
      51     26691316 :   reset_path (path, dependencies);
      52     26691316 : }
      53              : 
      54      2086980 : path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
      55      2086980 :   : m_cache (),
      56      2086980 :     m_ranger (ranger),
      57      2086980 :     m_resolve (resolve)
      58              : {
      59      2086980 :   share_query (ranger);
      60              :   // Override the relation oracle with a local path relation oracle.
      61      2086980 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      62      2086980 : }
      63              : 
      64     29562215 : path_range_query::~path_range_query ()
      65              : {
      66     28778296 :   delete m_relation;
      67     28778296 :   m_relation = NULL;
      68     29562215 : }
      69              : 
      70              : // Return TRUE if NAME is an exit dependency for the path.
      71              : 
      72              : bool
      73    126645331 : path_range_query::exit_dependency_p (tree name)
      74              : {
      75    126645331 :   return (TREE_CODE (name) == SSA_NAME
      76    126645331 :           && 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    342103991 : path_range_query::get_cache (vrange &r, tree name)
      83              : {
      84    342103991 :   if (!gimple_range_ssa_p (name))
      85     60618186 :     return get_global_range_query ()->range_of_expr (r, name);
      86              : 
      87    281485805 :   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     54662292 : path_range_query::defined_outside_path (tree name)
     124              : {
     125     54662292 :   gimple *def = SSA_NAME_DEF_STMT (name);
     126     54662292 :   basic_block bb = gimple_bb (def);
     127              : 
     128     54662292 :   return !bb || !m_path.contains (bb);
     129              : }
     130              : 
     131              : // Return the range of NAME on entry to the path.
     132              : 
     133              : void
     134     20399595 : path_range_query::range_on_path_entry (vrange &r, tree name)
     135              : {
     136     20399595 :   gcc_checking_assert (defined_outside_path (name));
     137     20399595 :   basic_block entry = entry_bb ();
     138     20399595 :   m_ranger.range_on_entry (r, entry, name);
     139     20399595 : }
     140              : 
     141              : // Return the range of NAME at the end of the path being analyzed.
     142              : 
     143              : bool
     144    194980891 : path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
     145              : {
     146    194980891 :   if (!r.supports_type_p (TREE_TYPE (name)))
     147              :     return false;
     148              : 
     149    194980891 :   if (get_cache (r, name))
     150              :     return true;
     151              : 
     152     55854643 :   if (m_resolve && defined_outside_path (name))
     153              :     {
     154     19033889 :       range_on_path_entry (r, name);
     155     19033889 :       m_cache.set_range (name, r);
     156     19033889 :       return true;
     157              :     }
     158              : 
     159     36820754 :   if (stmt
     160     36820754 :       && range_defined_in_block (r, name, gimple_bb (stmt)))
     161              :     {
     162     17357106 :       if (TREE_CODE (name) == SSA_NAME)
     163              :         {
     164     17357106 :           value_range glob (TREE_TYPE (name));
     165     17357106 :           gimple_range_global (glob, name);
     166     17357106 :           r.intersect (glob);
     167     17357106 :         }
     168              : 
     169     17357106 :       m_cache.set_range (name, r);
     170     17357106 :       return true;
     171              :     }
     172              : 
     173     19463648 :   gimple_range_global (r, name);
     174     19463648 :   return true;
     175              : }
     176              : 
     177              : bool
     178    194980891 : path_range_query::range_of_expr (vrange &r, tree name, gimple *stmt)
     179              : {
     180    194980891 :   if (internal_range_of_expr (r, name, stmt))
     181              :     {
     182    194980891 :       if (r.undefined_p ())
     183       145170 :         m_undefined_path = true;
     184              : 
     185    194980891 :       return true;
     186              :     }
     187              :   return false;
     188              : }
     189              : 
     190              : bool
     191     25789149 : path_range_query::unreachable_path_p ()
     192              : {
     193     25789149 :   return m_undefined_path;
     194              : }
     195              : 
     196              : // Reset the current path to PATH.
     197              : 
     198              : void
     199     35196663 : path_range_query::reset_path (const vec<basic_block> &path,
     200              :                               const bitmap_head *dependencies)
     201              : {
     202     35196663 :   gcc_checking_assert (path.length () > 1);
     203     35196663 :   m_path = path.copy ();
     204     35196663 :   m_pos = m_path.length () - 1;
     205     35196663 :   m_undefined_path = false;
     206     35196663 :   m_cache.clear ();
     207              : 
     208     35196663 :   compute_ranges (dependencies);
     209     35196663 : }
     210              : 
     211              : bool
     212    247752337 : path_range_query::ssa_defined_in_bb (tree name, basic_block bb)
     213              : {
     214    247752337 :   return (TREE_CODE (name) == SSA_NAME
     215    245519172 :           && SSA_NAME_DEF_STMT (name)
     216    493271509 :           && 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     18259229 : path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
     228              : {
     229     18259229 :   tree name = gimple_phi_result (phi);
     230              : 
     231     36518458 :   if (at_entry ())
     232              :     {
     233      3775006 :       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      1870887 :       unsigned nargs = gimple_phi_num_args (phi);
     240      1870887 :       value_range arg_range (TREE_TYPE (name));
     241      1870887 :       r.set_undefined ();
     242      6084999 :       for (size_t i = 0; i < nargs; ++i)
     243              :         {
     244      4214112 :           tree arg = gimple_phi_arg_def (phi, i);
     245      4214112 :           if (m_ranger.range_of_expr (arg_range, arg, /*stmt=*/NULL))
     246      4214112 :             r.union_ (arg_range);
     247              :           else
     248              :             {
     249            0 :               r.set_varying (TREE_TYPE (name));
     250            0 :               return;
     251              :             }
     252              :         }
     253              :       return;
     254      1870887 :     }
     255              : 
     256     14484223 :   basic_block bb = gimple_bb (phi);
     257     14484223 :   basic_block prev = prev_bb ();
     258     14484223 :   edge e_in = find_edge (prev, bb);
     259     14484223 :   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     14484223 :   if (ssa_defined_in_bb (arg, bb) || !get_cache (r, arg))
     263              :     {
     264      4456470 :       if (m_resolve)
     265              :         {
     266      2526401 :           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      2526401 :           if (TREE_CODE (arg) == SSA_NAME
     271      2526401 :               && defined_outside_path (arg))
     272      1365706 :             range_on_path_entry (r, arg);
     273              :           else
     274      1160695 :             r.set_varying (TREE_TYPE (name));
     275      2526401 :           m_ranger.range_on_edge (tmp, e_in, arg);
     276      2526401 :           r.intersect (tmp);
     277      2526401 :           return;
     278      2526401 :         }
     279      1930069 :       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    213362698 : path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb)
     288              : {
     289    213362698 :   gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     290    213362698 :   basic_block def_bb = gimple_bb (def_stmt);
     291              : 
     292    213362698 :   if (def_bb != bb)
     293              :     return false;
     294              : 
     295     71666216 :   if (get_cache (r, name))
     296              :     return true;
     297              : 
     298     69961674 :   if (gimple_code (def_stmt) == GIMPLE_PHI)
     299     18259229 :     ssa_range_in_phi (r, as_a<gphi *> (def_stmt));
     300              :   else
     301              :     {
     302     51702445 :       if (name)
     303     51702445 :         get_path_oracle ()->killing_def (name);
     304              : 
     305     51702445 :       if (!range_of_stmt (r, def_stmt, name))
     306        14614 :         r.set_varying (TREE_TYPE (name));
     307              :     }
     308              : 
     309     69961674 :   if (bb && POINTER_TYPE_P (TREE_TYPE (name)))
     310     10961011 :     infer_oracle ().maybe_adjust_range (r, name, bb);
     311              : 
     312     69961674 :   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     96950022 : 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    183351826 :   for (auto iter = gsi_start_phis (bb); !gsi_end_p (iter); gsi_next (&iter))
     335              :     {
     336     86401804 :       gphi *phi = iter.phi ();
     337     86401804 :       tree name = gimple_phi_result (phi);
     338              : 
     339     86401804 :       if (!exit_dependency_p (name))
     340     69358421 :         continue;
     341              : 
     342     17043383 :       value_range r (TREE_TYPE (name));
     343     17043383 :       if (range_defined_in_block (r, name, bb))
     344     17043383 :         m_cache.set_range (name, r);
     345     17043383 :     }
     346     96950022 : }
     347              : 
     348              : // Return TRUE if relations may be invalidated after crossing edge E.
     349              : 
     350              : bool
     351     42394407 : 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     42394407 :   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     96950022 : path_range_query::compute_ranges_in_block (basic_block bb)
     366              : {
     367     96950022 :   bitmap_iterator bi;
     368     96950022 :   unsigned i;
     369              : 
     370    153838052 :   if (m_resolve && !at_entry ())
     371     35967467 :     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    326034690 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     376              :     {
     377    229084668 :       tree name = ssa_name (i);
     378    229084668 :       if (ssa_defined_in_bb (name, bb))
     379     54309110 :         m_cache.clear_range (name);
     380              :     }
     381              : 
     382              :   // Solve dependencies defined in this block, starting with the PHIs...
     383     96950022 :   compute_ranges_in_phis (bb);
     384              :   // ...and then the rest of the dependencies.
     385    326034690 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     386              :     {
     387    229084668 :       tree name = ssa_name (i);
     388    229084668 :       value_range r (TREE_TYPE (name));
     389              : 
     390    229084668 :       if (gimple_code (SSA_NAME_DEF_STMT (name)) != GIMPLE_PHI
     391    229084668 :           && range_defined_in_block (r, name, bb))
     392     37265727 :         m_cache.set_range (name, r);
     393    229084668 :     }
     394              : 
     395     96950022 :   if (at_exit ())
     396     35196663 :     return;
     397              : 
     398              :   // Solve dependencies that are exported to the next block.
     399     61753359 :   basic_block next = next_bb ();
     400     61753359 :   edge e = find_edge (bb, next);
     401              : 
     402     61753359 :   if (m_resolve && relations_may_be_invalidated (e))
     403              :     {
     404      2494695 :       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      2494695 :       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      2494695 :       p->reset_path ();
     414              :     }
     415              : 
     416     61753359 :   bitmap exports = gori_ssa ()->exports (bb);
     417     80209978 :   EXECUTE_IF_AND_IN_BITMAP (m_exit_dependencies, exports, 0, i, bi)
     418              :     {
     419     18456619 :       tree name = ssa_name (i);
     420     18456619 :       value_range r (TREE_TYPE (name));
     421     18456619 :       if (gori ().edge_range_p (r, e, name, *this))
     422              :         {
     423     16542303 :           value_range cached_range (TREE_TYPE (name));
     424     16542303 :           if (get_cache (cached_range, name))
     425     13094026 :             r.intersect (cached_range);
     426              : 
     427     16542303 :           m_cache.set_range (name, r);
     428     16542303 :           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     16542303 :         }
     439     18456619 :     }
     440              : 
     441     61753359 :   if (m_resolve)
     442     35967467 :     compute_outgoing_relations (bb, next);
     443              : }
     444              : 
     445              : // Adjust all pointer exit dependencies in BB with non-null information.
     446              : 
     447              : void
     448     96950022 : path_range_query::adjust_for_non_null_uses (basic_block bb)
     449              : {
     450     96950022 :   prange r;
     451     96950022 :   bitmap_iterator bi;
     452     96950022 :   unsigned i;
     453              : 
     454    326034690 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     455              :     {
     456    229084668 :       tree name = ssa_name (i);
     457              : 
     458    229084668 :       if (!POINTER_TYPE_P (TREE_TYPE (name)))
     459    183463899 :         continue;
     460              : 
     461     45620769 :       if (get_cache (r, name))
     462              :         {
     463     19035393 :           if (r.nonzero_p ())
     464      7618120 :             continue;
     465              :         }
     466              :       else
     467     26585376 :         r.set_varying (TREE_TYPE (name));
     468              : 
     469     38002649 :       if (infer_oracle ().maybe_adjust_range (r, name, bb))
     470       847233 :         m_cache.set_range (name, r);
     471              :     }
     472     96950022 : }
     473              : 
     474              : // If NAME is a supported SSA_NAME, add it to the bitmap in dependencies.
     475              : 
     476              : bool
     477       159639 : path_range_query::add_to_exit_dependencies (tree name, bitmap dependencies)
     478              : {
     479       159639 :   if (TREE_CODE (name) == SSA_NAME
     480       159639 :       && value_range::supports_type_p (TREE_TYPE (name)))
     481       159639 :     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       783919 : path_range_query::compute_exit_dependencies (bitmap dependencies)
     490              : {
     491              :   // Start with the imports from the exit block...
     492       783919 :   basic_block exit = m_path[0];
     493       783919 :   bitmap_copy (dependencies, gori_ssa ()->imports (exit));
     494              : 
     495       783919 :   auto_vec<tree> worklist (bitmap_count_bits (dependencies));
     496       783919 :   bitmap_iterator bi;
     497       783919 :   unsigned i;
     498      2012090 :   EXECUTE_IF_SET_IN_BITMAP (dependencies, 0, i, bi)
     499              :     {
     500      1228171 :       tree name = ssa_name (i);
     501      1228171 :       worklist.quick_push (name);
     502              :     }
     503              : 
     504              :   // ...and add any operands used to define these imports.
     505      4496466 :   while (!worklist.is_empty ())
     506              :     {
     507      1464314 :       tree name = worklist.pop ();
     508      1464314 :       gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     509      1785806 :       if (SSA_NAME_IS_DEFAULT_DEF (name)
     510      1464314 :           || !m_path.contains (gimple_bb (def_stmt)))
     511       321492 :         continue;
     512              : 
     513      1142822 :       if (gphi *phi = dyn_cast <gphi *> (def_stmt))
     514              :         {
     515      1872092 :           for (size_t i = 0; i < gimple_phi_num_args (phi); ++i)
     516              :             {
     517      1250590 :               edge e = gimple_phi_arg_edge (phi, i);
     518      1250590 :               tree arg = gimple_phi_arg (phi, i)->def;
     519              : 
     520      1250590 :               if (TREE_CODE (arg) == SSA_NAME
     521       789453 :                   && m_path.contains (e->src)
     522      1407158 :                   && bitmap_set_bit (dependencies, SSA_NAME_VERSION (arg)))
     523       146253 :                 worklist.safe_push (arg);
     524              :             }
     525              :         }
     526      2769553 :       else if (gassign *ass = dyn_cast <gassign *> (def_stmt))
     527              :         {
     528       476027 :           tree ssa[3];
     529       476027 :           unsigned count = gimple_range_ssa_names (ssa, 3, ass);
     530       635666 :           for (unsigned j = 0; j < count; ++j)
     531       159639 :             if (add_to_exit_dependencies (ssa[j], dependencies))
     532        89890 :               worklist.safe_push (ssa[j]);
     533              :         }
     534              :     }
     535              :   // Exported booleans along the path, may help conditionals.
     536       783919 :   if (m_resolve)
     537      2560604 :     for (i = 0; i < m_path.length (); ++i)
     538              :       {
     539      1776685 :         basic_block bb = m_path[i];
     540      1776685 :         tree name;
     541      3617402 :         FOR_EACH_GORI_EXPORT_NAME (gori_ssa (), bb, name)
     542      1840717 :           if (TREE_CODE (TREE_TYPE (name)) == BOOLEAN_TYPE)
     543        57494 :             bitmap_set_bit (dependencies, SSA_NAME_VERSION (name));
     544              :       }
     545       783919 : }
     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     35196663 : path_range_query::compute_ranges (const bitmap_head *dependencies)
     556              : {
     557     35196663 :   if (DEBUG_SOLVER)
     558            0 :     fprintf (dump_file, "\n==============================================\n");
     559              : 
     560     35196663 :   if (dependencies)
     561     34412744 :     bitmap_copy (m_exit_dependencies, dependencies);
     562              :   else
     563       783919 :     compute_exit_dependencies (m_exit_dependencies);
     564              : 
     565     35196663 :   if (m_resolve)
     566              :     {
     567     20920563 :       path_oracle *p = get_path_oracle ();
     568     20920563 :       p->reset_path (&(m_ranger.relation ()));
     569              :     }
     570              : 
     571     35196663 :   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     61753359 :   while (1)
     585              :     {
     586     96950022 :       basic_block bb = curr_bb ();
     587              : 
     588     96950022 :       compute_ranges_in_block (bb);
     589     96950022 :       adjust_for_non_null_uses (bb);
     590              : 
     591     96950022 :       if (at_exit ())
     592              :         break;
     593              : 
     594     61753359 :       move_next ();
     595              :     }
     596              : 
     597     35196663 :   if (DEBUG_SOLVER)
     598              :     {
     599            0 :       get_path_oracle ()->dump (dump_file);
     600            0 :       dump (dump_file);
     601              :     }
     602     35196663 : }
     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     76551217 : jt_fur_source::jt_fur_source (gimple *s,
     625              :                               path_range_query *query,
     626     76551217 :                               const vec<basic_block> &path)
     627     76551217 :   : fur_depend (s, query)
     628              : {
     629     76551217 :   gcc_checking_assert (!path.is_empty ());
     630              : 
     631     76551217 :   m_entry = path[path.length () - 1];
     632     76551217 : }
     633              : 
     634              : // Ignore statement and register relation on entry to path.  Return false if
     635              : // no new relation is registered.
     636              : 
     637              : bool
     638     10154699 : jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2)
     639              : {
     640     10154699 :   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     13433278 : jt_fur_source::register_relation (edge, relation_kind k, tree op1, tree op2)
     648              : {
     649     13433278 :   return m_query->relation ().record (m_entry, k, op1, op2);
     650              : }
     651              : 
     652              : relation_kind
     653     36751269 : jt_fur_source::query_relation (tree op1, tree op2)
     654              : {
     655     36751269 :   if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
     656              :     return VREL_VARYING;
     657              : 
     658     12432363 :   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     88058659 : path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
     665              : {
     666     88058659 :   tree type = gimple_range_type (stmt);
     667              : 
     668     88058659 :   if (!type || !r.supports_type_p (type))
     669        14614 :     return false;
     670              : 
     671              :   // If resolving unknowns, fold the statement making use of any
     672              :   // relations along the path.
     673     88044045 :   if (m_resolve)
     674              :     {
     675     53147592 :       fold_using_range f;
     676     53147592 :       jt_fur_source src (stmt, this, m_path);
     677     53147592 :       if (!f.fold_stmt (r, stmt, src))
     678         5450 :         r.set_varying (type);
     679              :     }
     680              :   // Otherwise, fold without relations.
     681     34896453 :   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      7775434 : path_range_query::maybe_register_phi_relation (gphi *phi, edge e)
     691              : {
     692      7775434 :   tree arg = gimple_phi_arg_def (phi, e->dest_idx);
     693              : 
     694      7775434 :   if (!gimple_range_ssa_p (arg))
     695              :     return;
     696              : 
     697      6426940 :   if (relations_may_be_invalidated (e))
     698              :     return;
     699              : 
     700      4183446 :   basic_block bb = gimple_bb (phi);
     701      4183446 :   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      4183446 :   if (ssa_defined_in_bb (arg, bb))
     706              :     return;
     707              : 
     708      4183446 :   if (dump_file && (dump_flags & TDF_DETAILS))
     709           50 :     fprintf (dump_file, "maybe_register_phi_relation in bb%d:", bb->index);
     710              : 
     711      4183446 :   get_path_oracle ()->killing_def (result);
     712      4183446 :   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     35967467 : path_range_query::compute_phi_relations (basic_block bb, basic_block prev)
     723              : {
     724     35967467 :   if (prev == NULL)
     725              :     return;
     726              : 
     727     35967467 :   edge e_in = find_edge (prev, bb);
     728              : 
     729     76210994 :   for (gphi_iterator iter = gsi_start_phis (bb); !gsi_end_p (iter);
     730     40243527 :        gsi_next (&iter))
     731              :     {
     732     40243527 :       gphi *phi = iter.phi ();
     733     40243527 :       tree result = gimple_phi_result (phi);
     734     40243527 :       unsigned nargs = gimple_phi_num_args (phi);
     735              : 
     736     40243527 :       if (!exit_dependency_p (result))
     737     32468093 :         continue;
     738              : 
     739     15030781 :       for (size_t i = 0; i < nargs; ++i)
     740     15030781 :         if (e_in == gimple_phi_arg_edge (phi, i))
     741              :           {
     742      7775434 :             maybe_register_phi_relation (phi, e_in);
     743      7775434 :             break;
     744              :           }
     745              :     }
     746              : }
     747              : 
     748              : // Compute outgoing relations from BB to NEXT.
     749              : 
     750              : void
     751     35967467 : path_range_query::compute_outgoing_relations (basic_block bb, basic_block next)
     752              : {
     753     71934934 :   if (gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (bb)))
     754              :     {
     755     23403625 :       int_range<2> r;
     756     23403625 :       edge e0 = EDGE_SUCC (bb, 0);
     757     23403625 :       edge e1 = EDGE_SUCC (bb, 1);
     758              : 
     759     23403625 :       if (e0->dest == next)
     760     10046751 :         gcond_edge_range (r, e0);
     761     13356874 :       else if (e1->dest == next)
     762     13356874 :         gcond_edge_range (r, e1);
     763              :       else
     764            0 :         gcc_unreachable ();
     765              : 
     766     23403625 :       jt_fur_source src (NULL, this, m_path);
     767     23403625 :       src.register_outgoing_edges (cond, r, e0, e1);
     768     23403625 :     }
     769     35967467 : }
        

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.