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-02-28 14:20:25 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     26916356 : path_range_query::path_range_query (gimple_ranger &ranger,
      40              :                                     const vec<basic_block> &path,
      41              :                                     const bitmap_head *dependencies,
      42     26916356 :                                     bool resolve)
      43     26916356 :   : m_cache (),
      44     26916356 :     m_ranger (ranger),
      45     26916356 :     m_resolve (resolve)
      46              : {
      47     26916356 :   share_query (ranger);
      48              :   // Override the relation oracle with a local path relation oracle.
      49     26916356 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      50              : 
      51     26916356 :   reset_path (path, dependencies);
      52     26916356 : }
      53              : 
      54      2083233 : path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
      55      2083233 :   : m_cache (),
      56      2083233 :     m_ranger (ranger),
      57      2083233 :     m_resolve (resolve)
      58              : {
      59      2083233 :   share_query (ranger);
      60              :   // Override the relation oracle with a local path relation oracle.
      61      2083233 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      62      2083233 : }
      63              : 
      64     29788896 : path_range_query::~path_range_query ()
      65              : {
      66     28999589 :   delete m_relation;
      67     28999589 :   m_relation = NULL;
      68     29788896 : }
      69              : 
      70              : // Return TRUE if NAME is an exit dependency for the path.
      71              : 
      72              : bool
      73    130359727 : path_range_query::exit_dependency_p (tree name)
      74              : {
      75    130359727 :   return (TREE_CODE (name) == SSA_NAME
      76    130359727 :           && 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    346280907 : path_range_query::get_cache (vrange &r, tree name)
      83              : {
      84    346280907 :   if (!gimple_range_ssa_p (name))
      85     61129456 :     return get_global_range_query ()->range_of_expr (r, name);
      86              : 
      87    285151451 :   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     55435373 : path_range_query::defined_outside_path (tree name)
     124              : {
     125     55435373 :   gimple *def = SSA_NAME_DEF_STMT (name);
     126     55435373 :   basic_block bb = gimple_bb (def);
     127              : 
     128     55435373 :   return !bb || !m_path.contains (bb);
     129              : }
     130              : 
     131              : // Return the range of NAME on entry to the path.
     132              : 
     133              : void
     134     20659895 : path_range_query::range_on_path_entry (vrange &r, tree name)
     135              : {
     136     20659895 :   gcc_checking_assert (defined_outside_path (name));
     137     20659895 :   basic_block entry = entry_bb ();
     138     20659895 :   m_ranger.range_on_entry (r, entry, name);
     139     20659895 : }
     140              : 
     141              : // Return the range of NAME at the end of the path being analyzed.
     142              : 
     143              : bool
     144    196528603 : path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
     145              : {
     146    196528603 :   if (!r.supports_type_p (TREE_TYPE (name)))
     147              :     return false;
     148              : 
     149    196528603 :   if (get_cache (r, name))
     150              :     return true;
     151              : 
     152     56383924 :   if (m_resolve && defined_outside_path (name))
     153              :     {
     154     19233136 :       range_on_path_entry (r, name);
     155     19233136 :       m_cache.set_range (name, r);
     156     19233136 :       return true;
     157              :     }
     158              : 
     159     37150788 :   if (stmt
     160     37150788 :       && range_defined_in_block (r, name, gimple_bb (stmt)))
     161              :     {
     162     17658566 :       if (TREE_CODE (name) == SSA_NAME)
     163              :         {
     164     17658566 :           value_range glob (TREE_TYPE (name));
     165     17658566 :           gimple_range_global (glob, name);
     166     17658566 :           r.intersect (glob);
     167     17658566 :         }
     168              : 
     169     17658566 :       m_cache.set_range (name, r);
     170     17658566 :       return true;
     171              :     }
     172              : 
     173     19492222 :   gimple_range_global (r, name);
     174     19492222 :   return true;
     175              : }
     176              : 
     177              : bool
     178    196528603 : path_range_query::range_of_expr (vrange &r, tree name, gimple *stmt)
     179              : {
     180    196528603 :   if (internal_range_of_expr (r, name, stmt))
     181              :     {
     182    196528603 :       if (r.undefined_p ())
     183       141367 :         m_undefined_path = true;
     184              : 
     185    196528603 :       return true;
     186              :     }
     187              :   return false;
     188              : }
     189              : 
     190              : bool
     191     26003643 : path_range_query::unreachable_path_p ()
     192              : {
     193     26003643 :   return m_undefined_path;
     194              : }
     195              : 
     196              : // Reset the current path to PATH.
     197              : 
     198              : void
     199     35597439 : path_range_query::reset_path (const vec<basic_block> &path,
     200              :                               const bitmap_head *dependencies)
     201              : {
     202     35597439 :   gcc_checking_assert (path.length () > 1);
     203     35597439 :   m_path = path.copy ();
     204     35597439 :   m_pos = m_path.length () - 1;
     205     35597439 :   m_undefined_path = false;
     206     35597439 :   m_cache.clear ();
     207              : 
     208     35597439 :   compute_ranges (dependencies);
     209     35597439 : }
     210              : 
     211              : bool
     212    252716283 : path_range_query::ssa_defined_in_bb (tree name, basic_block bb)
     213              : {
     214    252716283 :   return (TREE_CODE (name) == SSA_NAME
     215    250420586 :           && SSA_NAME_DEF_STMT (name)
     216    503136869 :           && 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     18880379 : path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
     228              : {
     229     18880379 :   tree name = gimple_phi_result (phi);
     230              : 
     231     37760758 :   if (at_entry ())
     232              :     {
     233      3878944 :       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      1911571 :       unsigned nargs = gimple_phi_num_args (phi);
     240      1911571 :       value_range arg_range (TREE_TYPE (name));
     241      1911571 :       r.set_undefined ();
     242      6215047 :       for (size_t i = 0; i < nargs; ++i)
     243              :         {
     244      4303476 :           tree arg = gimple_phi_arg_def (phi, i);
     245      4303476 :           if (m_ranger.range_of_expr (arg_range, arg, /*stmt=*/NULL))
     246      4303476 :             r.union_ (arg_range);
     247              :           else
     248              :             {
     249            0 :               r.set_varying (TREE_TYPE (name));
     250            0 :               return;
     251              :             }
     252              :         }
     253              :       return;
     254      1911571 :     }
     255              : 
     256     15001435 :   basic_block bb = gimple_bb (phi);
     257     15001435 :   basic_block prev = prev_bb ();
     258     15001435 :   edge e_in = find_edge (prev, bb);
     259     15001435 :   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     15001435 :   if (ssa_defined_in_bb (arg, bb) || !get_cache (r, arg))
     263              :     {
     264      4611688 :       if (m_resolve)
     265              :         {
     266      2617376 :           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      2617376 :           if (TREE_CODE (arg) == SSA_NAME
     271      2617376 :               && defined_outside_path (arg))
     272      1426759 :             range_on_path_entry (r, arg);
     273              :           else
     274      1190617 :             r.set_varying (TREE_TYPE (name));
     275      2617376 :           m_ranger.range_on_edge (tmp, e_in, arg);
     276      2617376 :           r.intersect (tmp);
     277      2617376 :           return;
     278      2617376 :         }
     279      1994312 :       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    216099891 : path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb)
     288              : {
     289    216099891 :   gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     290    216099891 :   basic_block def_bb = gimple_bb (def_stmt);
     291              : 
     292    216099891 :   if (def_bb != bb)
     293              :     return false;
     294              : 
     295     73027590 :   if (get_cache (r, name))
     296              :     return true;
     297              : 
     298     71291599 :   if (gimple_code (def_stmt) == GIMPLE_PHI)
     299     18880379 :     ssa_range_in_phi (r, as_a<gphi *> (def_stmt));
     300              :   else
     301              :     {
     302     52411220 :       if (name)
     303     52411220 :         get_path_oracle ()->killing_def (name);
     304              : 
     305     52411220 :       if (!range_of_stmt (r, def_stmt, name))
     306        14607 :         r.set_varying (TREE_TYPE (name));
     307              :     }
     308              : 
     309     71291599 :   if (bb && POINTER_TYPE_P (TREE_TYPE (name)))
     310     11182805 :     infer_oracle ().maybe_adjust_range (r, name, bb);
     311              : 
     312     71291599 :   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     98011379 : 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    186895075 :   for (auto iter = gsi_start_phis (bb); !gsi_end_p (iter); gsi_next (&iter))
     335              :     {
     336     88883696 :       gphi *phi = iter.phi ();
     337     88883696 :       tree name = gimple_phi_result (phi);
     338              : 
     339     88883696 :       if (!exit_dependency_p (name))
     340     71280594 :         continue;
     341              : 
     342     17603102 :       value_range r (TREE_TYPE (name));
     343     17603102 :       if (range_defined_in_block (r, name, bb))
     344     17603102 :         m_cache.set_range (name, r);
     345     17603102 :     }
     346     98011379 : }
     347              : 
     348              : // Return TRUE if relations may be invalidated after crossing edge E.
     349              : 
     350              : bool
     351     43086372 : 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     43086372 :   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     98011379 : path_range_query::compute_ranges_in_block (basic_block bb)
     366              : {
     367     98011379 :   bitmap_iterator bi;
     368     98011379 :   unsigned i;
     369              : 
     370    155629083 :   if (m_resolve && !at_entry ())
     371     36416950 :     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    331329760 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     376              :     {
     377    233318381 :       tree name = ssa_name (i);
     378    233318381 :       if (ssa_defined_in_bb (name, bb))
     379     55369024 :         m_cache.clear_range (name);
     380              :     }
     381              : 
     382              :   // Solve dependencies defined in this block, starting with the PHIs...
     383     98011379 :   compute_ranges_in_phis (bb);
     384              :   // ...and then the rest of the dependencies.
     385    331329760 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     386              :     {
     387    233318381 :       tree name = ssa_name (i);
     388    233318381 :       value_range r (TREE_TYPE (name));
     389              : 
     390    233318381 :       if (gimple_code (SSA_NAME_DEF_STMT (name)) != GIMPLE_PHI
     391    233318381 :           && range_defined_in_block (r, name, bb))
     392     37765922 :         m_cache.set_range (name, r);
     393    233318381 :     }
     394              : 
     395     98011379 :   if (at_exit ())
     396     35597439 :     return;
     397              : 
     398              :   // Solve dependencies that are exported to the next block.
     399     62413940 :   basic_block next = next_bb ();
     400     62413940 :   edge e = find_edge (bb, next);
     401              : 
     402     62413940 :   if (m_resolve && relations_may_be_invalidated (e))
     403              :     {
     404      2522211 :       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      2522211 :       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      2522211 :       p->reset_path ();
     414              :     }
     415              : 
     416     62413940 :   bitmap exports = gori_ssa ()->exports (bb);
     417     80864494 :   EXECUTE_IF_AND_IN_BITMAP (m_exit_dependencies, exports, 0, i, bi)
     418              :     {
     419     18450554 :       tree name = ssa_name (i);
     420     18450554 :       value_range r (TREE_TYPE (name));
     421     18450554 :       if (gori ().edge_range_p (r, e, name, *this))
     422              :         {
     423     16626442 :           value_range cached_range (TREE_TYPE (name));
     424     16626442 :           if (get_cache (cached_range, name))
     425     13172224 :             r.intersect (cached_range);
     426              : 
     427     16626442 :           m_cache.set_range (name, r);
     428     16626442 :           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     16626442 :         }
     439     18450554 :     }
     440              : 
     441     62413940 :   if (m_resolve)
     442     36416950 :     compute_outgoing_relations (bb, next);
     443              : }
     444              : 
     445              : // Adjust all pointer exit dependencies in BB with non-null information.
     446              : 
     447              : void
     448     98011379 : path_range_query::adjust_for_non_null_uses (basic_block bb)
     449              : {
     450     98011379 :   prange r;
     451     98011379 :   bitmap_iterator bi;
     452     98011379 :   unsigned i;
     453              : 
     454    331329760 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     455              :     {
     456    233318381 :       tree name = ssa_name (i);
     457              : 
     458    233318381 :       if (!POINTER_TYPE_P (TREE_TYPE (name)))
     459    187023956 :         continue;
     460              : 
     461     46294425 :       if (get_cache (r, name))
     462              :         {
     463     19380711 :           if (r.nonzero_p ())
     464      7799406 :             continue;
     465              :         }
     466              :       else
     467     26913714 :         r.set_varying (TREE_TYPE (name));
     468              : 
     469     38495019 :       if (infer_oracle ().maybe_adjust_range (r, name, bb))
     470       835633 :         m_cache.set_range (name, r);
     471              :     }
     472     98011379 : }
     473              : 
     474              : // If NAME is a supported SSA_NAME, add it to the bitmap in dependencies.
     475              : 
     476              : bool
     477       165545 : path_range_query::add_to_exit_dependencies (tree name, bitmap dependencies)
     478              : {
     479       165545 :   if (TREE_CODE (name) == SSA_NAME
     480       165545 :       && value_range::supports_type_p (TREE_TYPE (name)))
     481       165545 :     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       789307 : path_range_query::compute_exit_dependencies (bitmap dependencies)
     490              : {
     491              :   // Start with the imports from the exit block...
     492       789307 :   basic_block exit = m_path[0];
     493       789307 :   bitmap_copy (dependencies, gori_ssa ()->imports (exit));
     494              : 
     495       789307 :   auto_vec<tree> worklist (bitmap_count_bits (dependencies));
     496       789307 :   bitmap_iterator bi;
     497       789307 :   unsigned i;
     498      2025912 :   EXECUTE_IF_SET_IN_BITMAP (dependencies, 0, i, bi)
     499              :     {
     500      1236605 :       tree name = ssa_name (i);
     501      1236605 :       worklist.quick_push (name);
     502              :     }
     503              : 
     504              :   // ...and add any operands used to define these imports.
     505      4548356 :   while (!worklist.is_empty ())
     506              :     {
     507      1484871 :       tree name = worklist.pop ();
     508      1484871 :       gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     509      1809588 :       if (SSA_NAME_IS_DEFAULT_DEF (name)
     510      1484871 :           || !m_path.contains (gimple_bb (def_stmt)))
     511       324717 :         continue;
     512              : 
     513      1160154 :       if (gphi *phi = dyn_cast <gphi *> (def_stmt))
     514              :         {
     515      1890254 :           for (size_t i = 0; i < gimple_phi_num_args (phi); ++i)
     516              :             {
     517      1262659 :               edge e = gimple_phi_arg_edge (phi, i);
     518      1262659 :               tree arg = gimple_phi_arg (phi, i)->def;
     519              : 
     520      1262659 :               if (TREE_CODE (arg) == SSA_NAME
     521       801734 :                   && m_path.contains (e->src)
     522      1425088 :                   && bitmap_set_bit (dependencies, SSA_NAME_VERSION (arg)))
     523       151931 :                 worklist.safe_push (arg);
     524              :             }
     525              :         }
     526      2806737 :       else if (gassign *ass = dyn_cast <gassign *> (def_stmt))
     527              :         {
     528       487313 :           tree ssa[3];
     529       487313 :           unsigned count = gimple_range_ssa_names (ssa, 3, ass);
     530       652858 :           for (unsigned j = 0; j < count; ++j)
     531       165545 :             if (add_to_exit_dependencies (ssa[j], dependencies))
     532        96335 :               worklist.safe_push (ssa[j]);
     533              :         }
     534              :     }
     535              :   // Exported booleans along the path, may help conditionals.
     536       789307 :   if (m_resolve)
     537      2579923 :     for (i = 0; i < m_path.length (); ++i)
     538              :       {
     539      1790616 :         basic_block bb = m_path[i];
     540      1790616 :         tree name;
     541      3644976 :         FOR_EACH_GORI_EXPORT_NAME (gori_ssa (), bb, name)
     542      1854360 :           if (TREE_CODE (TREE_TYPE (name)) == BOOLEAN_TYPE)
     543        57710 :             bitmap_set_bit (dependencies, SSA_NAME_VERSION (name));
     544              :       }
     545       789307 : }
     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     35597439 : path_range_query::compute_ranges (const bitmap_head *dependencies)
     556              : {
     557     35597439 :   if (DEBUG_SOLVER)
     558            0 :     fprintf (dump_file, "\n==============================================\n");
     559              : 
     560     35597439 :   if (dependencies)
     561     34808132 :     bitmap_copy (m_exit_dependencies, dependencies);
     562              :   else
     563       789307 :     compute_exit_dependencies (m_exit_dependencies);
     564              : 
     565     35597439 :   if (m_resolve)
     566              :     {
     567     21200754 :       path_oracle *p = get_path_oracle ();
     568     21200754 :       p->reset_path (&(m_ranger.relation ()));
     569              :     }
     570              : 
     571     35597439 :   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     62413940 :   while (1)
     585              :     {
     586     98011379 :       basic_block bb = curr_bb ();
     587              : 
     588     98011379 :       compute_ranges_in_block (bb);
     589     98011379 :       adjust_for_non_null_uses (bb);
     590              : 
     591     98011379 :       if (at_exit ())
     592              :         break;
     593              : 
     594     62413940 :       move_next ();
     595              :     }
     596              : 
     597     35597439 :   if (DEBUG_SOLVER)
     598              :     {
     599            0 :       get_path_oracle ()->dump (dump_file);
     600            0 :       dump (dump_file);
     601              :     }
     602     35597439 : }
     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     77571863 : jt_fur_source::jt_fur_source (gimple *s,
     625              :                               path_range_query *query,
     626     77571863 :                               const vec<basic_block> &path)
     627     77571863 :   : fur_depend (s, query)
     628              : {
     629     77571863 :   gcc_checking_assert (!path.is_empty ());
     630              : 
     631     77571863 :   m_entry = path[path.length () - 1];
     632     77571863 : }
     633              : 
     634              : // Ignore statement and register relation on entry to path.  Return false if
     635              : // no new relation is registered.
     636              : 
     637              : bool
     638     10300437 : jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2)
     639              : {
     640     10300437 :   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     13540370 : jt_fur_source::register_relation (edge, relation_kind k, tree op1, tree op2)
     648              : {
     649     13540370 :   return m_query->relation ().record (m_entry, k, op1, op2);
     650              : }
     651              : 
     652              : relation_kind
     653     37313479 : jt_fur_source::query_relation (tree op1, tree op2)
     654              : {
     655     37313479 :   if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
     656              :     return VREL_VARYING;
     657              : 
     658     12662993 :   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     89167026 : path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
     665              : {
     666     89167026 :   tree type = gimple_range_type (stmt);
     667              : 
     668     89167026 :   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     89152419 :   if (m_resolve)
     674              :     {
     675     53936998 :       fold_using_range f;
     676     53936998 :       jt_fur_source src (stmt, this, m_path);
     677     53936998 :       if (!f.fold_stmt (r, stmt, src))
     678         5451 :         r.set_varying (type);
     679              :     }
     680              :   // Otherwise, fold without relations.
     681     35215421 :   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      8045572 : path_range_query::maybe_register_phi_relation (gphi *phi, edge e)
     691              : {
     692      8045572 :   tree arg = gimple_phi_arg_def (phi, e->dest_idx);
     693              : 
     694      8045572 :   if (!gimple_range_ssa_p (arg))
     695              :     return;
     696              : 
     697      6669422 :   if (relations_may_be_invalidated (e))
     698              :     return;
     699              : 
     700      4396467 :   basic_block bb = gimple_bb (phi);
     701      4396467 :   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      4396467 :   if (ssa_defined_in_bb (arg, bb))
     706              :     return;
     707              : 
     708      4396467 :   if (dump_file && (dump_flags & TDF_DETAILS))
     709           50 :     fprintf (dump_file, "maybe_register_phi_relation in bb%d:", bb->index);
     710              : 
     711      4396467 :   get_path_oracle ()->killing_def (result);
     712      4396467 :   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     36416950 : path_range_query::compute_phi_relations (basic_block bb, basic_block prev)
     723              : {
     724     36416950 :   if (prev == NULL)
     725              :     return;
     726              : 
     727     36416950 :   edge e_in = find_edge (prev, bb);
     728              : 
     729     77892981 :   for (gphi_iterator iter = gsi_start_phis (bb); !gsi_end_p (iter);
     730     41476031 :        gsi_next (&iter))
     731              :     {
     732     41476031 :       gphi *phi = iter.phi ();
     733     41476031 :       tree result = gimple_phi_result (phi);
     734     41476031 :       unsigned nargs = gimple_phi_num_args (phi);
     735              : 
     736     41476031 :       if (!exit_dependency_p (result))
     737     33430459 :         continue;
     738              : 
     739     15570755 :       for (size_t i = 0; i < nargs; ++i)
     740     15570755 :         if (e_in == gimple_phi_arg_edge (phi, i))
     741              :           {
     742      8045572 :             maybe_register_phi_relation (phi, e_in);
     743      8045572 :             break;
     744              :           }
     745              :     }
     746              : }
     747              : 
     748              : // Compute outgoing relations from BB to NEXT.
     749              : 
     750              : void
     751     36416950 : path_range_query::compute_outgoing_relations (basic_block bb, basic_block next)
     752              : {
     753     72833900 :   if (gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (bb)))
     754              :     {
     755     23634865 :       int_range<2> r;
     756     23634865 :       edge e0 = EDGE_SUCC (bb, 0);
     757     23634865 :       edge e1 = EDGE_SUCC (bb, 1);
     758              : 
     759     23634865 :       if (e0->dest == next)
     760     10128648 :         gcond_edge_range (r, e0);
     761     13506217 :       else if (e1->dest == next)
     762     13506217 :         gcond_edge_range (r, e1);
     763              :       else
     764            0 :         gcc_unreachable ();
     765              : 
     766     23634865 :       jt_fur_source src (NULL, this, m_path);
     767     23634865 :       src.register_outgoing_edges (cond, r, e0, e1);
     768     23634865 :     }
     769     36416950 : }
        

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.