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-08-22 16:33:35 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     29639754 : path_range_query::path_range_query (gimple_ranger &ranger,
      40              :                                     const vec<basic_block> &path,
      41              :                                     const bitmap_head *dependencies,
      42              :                                     bool resolve)
      43     29639754 :   : m_cache (),
      44     29639754 :     m_ranger (ranger),
      45     29639754 :     m_resolve (resolve)
      46              : {
      47     29639754 :   share_query (ranger);
      48              :   // Override the relation oracle with a local path relation oracle.
      49     29639754 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      50              : 
      51     29639754 :   reset_path (path, dependencies);
      52     29639754 : }
      53              : 
      54      2121033 : path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
      55      2121033 :   : m_cache (),
      56      2121033 :     m_ranger (ranger),
      57      2121033 :     m_resolve (resolve)
      58              : {
      59      2121033 :   share_query (ranger);
      60              :   // Override the relation oracle with a local path relation oracle.
      61      2121033 :   m_relation = new path_oracle (&(m_ranger.relation ()));
      62      2121033 : }
      63              : 
      64     32560360 : path_range_query::~path_range_query ()
      65              : {
      66     31760787 :   delete m_relation;
      67     31760787 :   m_relation = NULL;
      68     32560360 : }
      69              : 
      70              : // Return TRUE if NAME is an exit dependency for the path.
      71              : 
      72              : bool
      73    145281918 : path_range_query::exit_dependency_p (tree name)
      74              : {
      75    145281918 :   return (TREE_CODE (name) == SSA_NAME
      76    145281918 :           && 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    383771789 : path_range_query::get_cache (vrange &r, tree name)
      83              : {
      84    383771789 :   if (!gimple_range_ssa_p (name))
      85     67324571 :     return get_global_range_query ()->range_of_expr (r, name);
      86              : 
      87    316447218 :   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     58518481 : path_range_query::defined_outside_path (tree name)
     124              : {
     125     58518481 :   gimple *def = SSA_NAME_DEF_STMT (name);
     126     58518481 :   basic_block bb = gimple_bb (def);
     127              : 
     128     58518481 :   return !bb || !m_path.contains (bb);
     129              : }
     130              : 
     131              : // Return the range of NAME on entry to the path.
     132              : 
     133              : void
     134     21717273 : path_range_query::range_on_path_entry (vrange &r, tree name)
     135              : {
     136     21717273 :   gcc_checking_assert (defined_outside_path (name));
     137     21717273 :   basic_block entry = entry_bb ();
     138     21717273 :   m_ranger.range_on_entry (r, entry, name);
     139     21717273 : }
     140              : 
     141              : // Return the range of NAME at the end of the path being analyzed.
     142              : 
     143              : bool
     144    217784712 : path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
     145              : {
     146    217784712 :   if (!r.supports_type_p (TREE_TYPE (name)))
     147              :     return false;
     148              : 
     149    217784712 :   if (get_cache (r, name))
     150              :     return true;
     151              : 
     152     61570912 :   if (m_resolve && defined_outside_path (name))
     153              :     {
     154     19962582 :       range_on_path_entry (r, name);
     155     19962582 :       m_cache.set_range (name, r);
     156     19962582 :       return true;
     157              :     }
     158              : 
     159              :   // We can be called from match.pd or elsewhere, with a context statement
     160              :   // that can be anywhere on the path.  Since we can only compute ranges
     161              :   // mid flight at the current path position, check that's the case,
     162              :   // otherwise fall through to the global range.
     163     41608330 :   if (stmt
     164     41485845 :       && gimple_bb (stmt) == curr_bb ()
     165     83093860 :       && range_defined_in_block (r, name, gimple_bb (stmt)))
     166              :     {
     167     19540688 :       if (TREE_CODE (name) == SSA_NAME)
     168              :         {
     169     19540688 :           value_range glob (TREE_TYPE (name));
     170     19540688 :           gimple_range_global (glob, name);
     171     19540688 :           r.intersect (glob);
     172     19540688 :         }
     173              : 
     174     19540688 :       m_cache.set_range (name, r);
     175     19540688 :       return true;
     176              :     }
     177              : 
     178     22067642 :   gimple_range_global (r, name);
     179     22067642 :   return true;
     180              : }
     181              : 
     182              : bool
     183    217784712 : path_range_query::range_of_expr (vrange &r, tree name, gimple *stmt)
     184              : {
     185    217784712 :   if (internal_range_of_expr (r, name, stmt))
     186              :     {
     187    217784712 :       if (r.undefined_p ())
     188       198608 :         m_undefined_path = true;
     189              : 
     190              :       return true;
     191              :     }
     192              :   return false;
     193              : }
     194              : 
     195              : bool
     196     28746708 : path_range_query::unreachable_path_p ()
     197              : {
     198     28746708 :   return m_undefined_path;
     199              : }
     200              : 
     201              : // Reset the current path to PATH.
     202              : 
     203              : void
     204     38425399 : path_range_query::reset_path (const vec<basic_block> &path,
     205              :                               const bitmap_head *dependencies)
     206              : {
     207     38425399 :   gcc_checking_assert (path.length () > 1);
     208     38425399 :   m_path = path.copy ();
     209     38425399 :   m_pos = m_path.length () - 1;
     210     38425399 :   m_undefined_path = false;
     211     38425399 :   m_cache.clear ();
     212              : 
     213     38425399 :   compute_ranges (dependencies);
     214     38425399 : }
     215              : 
     216              : bool
     217    281729696 : path_range_query::ssa_defined_in_bb (tree name, basic_block bb)
     218              : {
     219    281729696 :   return (TREE_CODE (name) == SSA_NAME
     220    277195132 :           && SSA_NAME_DEF_STMT (name)
     221    558924828 :           && gimple_bb (SSA_NAME_DEF_STMT (name)) == bb);
     222              : }
     223              : 
     224              : // Return the range of the result of PHI in R.
     225              : //
     226              : // Since PHIs are calculated in parallel at the beginning of the
     227              : // block, we must be careful to never save anything to the cache here.
     228              : // It is the caller's responsibility to adjust the cache.  Also,
     229              : // calculating the PHI's range must not trigger additional lookups.
     230              : 
     231              : void
     232     22393190 : path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
     233              : {
     234     22393190 :   tree name = gimple_phi_result (phi);
     235              : 
     236     44786380 :   if (at_entry ())
     237              :     {
     238      3630032 :       if (m_resolve && m_ranger.range_of_expr (r, name, phi))
     239              :         return;
     240              : 
     241              :       // Try to fold the phi exclusively with global values.
     242              :       // This will get things like PHI <5(99), 6(88)>.  We do this by
     243              :       // calling range_of_expr with no context.
     244      1794611 :       unsigned nargs = gimple_phi_num_args (phi);
     245      1794611 :       value_range arg_range (TREE_TYPE (name));
     246      1794611 :       r.set_undefined ();
     247      7787371 :       for (size_t i = 0; i < nargs; ++i)
     248              :         {
     249      4198149 :           tree arg = gimple_phi_arg_def (phi, i);
     250      4198149 :           if (m_ranger.range_of_expr (arg_range, arg, /*stmt=*/NULL))
     251      4198149 :             r.union_ (arg_range);
     252              :           else
     253              :             {
     254            0 :               r.set_varying (TREE_TYPE (name));
     255            0 :               return;
     256              :             }
     257              :         }
     258              :       return;
     259      1794611 :     }
     260              : 
     261     18763158 :   basic_block bb = gimple_bb (phi);
     262     18763158 :   basic_block prev = prev_bb ();
     263     18763158 :   edge e_in = find_edge (prev, bb);
     264              :   // The incoming edge the path supplies is never abnormal, so the
     265              :   // argument on it is a valid value for the PHI result even when the
     266              :   // result occurs in an abnormal PHI.
     267     18763158 :   gcc_checking_assert (!(e_in->flags & EDGE_ABNORMAL));
     268     18763158 :   tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e_in);
     269              :   // Avoid using the cache for ARGs defined in this block, as
     270              :   // that could create an ordering problem.
     271     18763158 :   if (ssa_defined_in_bb (arg, bb) || !get_cache (r, arg))
     272              :     {
     273      4888182 :       if (m_resolve)
     274              :         {
     275      2787740 :           value_range tmp (TREE_TYPE (name));
     276              :           // Using both the range on entry to the path, and the
     277              :           // range on this edge yields significantly better
     278              :           // results.
     279      2787740 :           if (TREE_CODE (arg) == SSA_NAME
     280      2787740 :               && defined_outside_path (arg))
     281      1754691 :             range_on_path_entry (r, arg);
     282              :           else
     283      1033049 :             r.set_varying (TREE_TYPE (name));
     284      2787740 :           m_ranger.range_on_edge (tmp, e_in, arg);
     285      2787740 :           r.intersect (tmp);
     286      2787740 :           return;
     287      2787740 :         }
     288      2100442 :       r.set_varying (TREE_TYPE (name));
     289              :     }
     290              : }
     291              : 
     292              : // If NAME is defined in BB, set R to the range of NAME, and return
     293              : // TRUE.  Otherwise, return FALSE.
     294              : 
     295              : bool
     296    235729095 : path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb)
     297              : {
     298              :   // Ranges can only be calculated at the current path position, both
     299              :   // while pre-computing the cache and when answering questions at the
     300              :   // path exit afterwards.
     301    235729095 :   gcc_assert (bb == curr_bb ());
     302              : 
     303    235729095 :   gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     304    235729095 :   basic_block def_bb = gimple_bb (def_stmt);
     305              : 
     306    235729095 :   if (def_bb != bb)
     307              :     return false;
     308              : 
     309     80622417 :   if (get_cache (r, name))
     310              :     return true;
     311              : 
     312     78759090 :   if (gimple_code (def_stmt) == GIMPLE_PHI)
     313     22393190 :     ssa_range_in_phi (r, as_a<gphi *> (def_stmt));
     314              :   else
     315              :     {
     316     56365900 :       if (name)
     317     56365900 :         get_path_oracle ()->killing_def (name);
     318              : 
     319     56365900 :       if (!range_of_stmt (r, def_stmt, name))
     320        15063 :         r.set_varying (TREE_TYPE (name));
     321              :     }
     322              : 
     323     78759090 :   if (bb && POINTER_TYPE_P (TREE_TYPE (name)))
     324     12756239 :     infer_oracle ().maybe_adjust_range (r, name, bb);
     325              : 
     326     78759090 :   if (DEBUG_SOLVER && (bb || !r.varying_p ()))
     327              :     {
     328            0 :       fprintf (dump_file, "range_defined_in_block (BB%d) for ", bb ? bb->index : -1);
     329            0 :       print_generic_expr (dump_file, name, TDF_SLIM);
     330            0 :       fprintf (dump_file, " is ");
     331            0 :       r.dump (dump_file);
     332            0 :       fprintf (dump_file, "\n");
     333              :     }
     334              : 
     335              :   return true;
     336              : }
     337              : 
     338              : // Compute ranges defined in the PHIs in this block.
     339              : 
     340              : void
     341    105082599 : path_range_query::compute_ranges_in_phis (basic_block bb)
     342              : {
     343              :   // PHIs must be resolved simultaneously on entry to the block
     344              :   // because any dependencies must be satisfied with values on entry.
     345              :   // Thus, we calculate all PHIs first, and then update the cache at
     346              :   // the end.
     347              : 
     348    204330619 :   for (auto iter = gsi_start_phis (bb); !gsi_end_p (iter); gsi_next (&iter))
     349              :     {
     350     99248020 :       gphi *phi = iter.phi ();
     351     99248020 :       tree name = gimple_phi_result (phi);
     352              : 
     353     99248020 :       if (!exit_dependency_p (name))
     354     78337712 :         continue;
     355              : 
     356     20910308 :       value_range r (TREE_TYPE (name));
     357     20910308 :       if (range_defined_in_block (r, name, bb))
     358     20910308 :         m_cache.set_range (name, r);
     359     20910308 :     }
     360    105082599 : }
     361              : 
     362              : // Return TRUE if relations may be invalidated after crossing edge E.
     363              : 
     364              : bool
     365     45998216 : path_range_query::relations_may_be_invalidated (edge e)
     366              : {
     367              :   // As soon as the path crosses a back edge, we can encounter
     368              :   // definitions of SSA_NAMEs that may have had a use in the path
     369              :   // already, so this will then be a new definition.  The relation
     370              :   // code is all designed around seeing things in dominator order, and
     371              :   // crossing a back edge in the path violates this assumption.
     372     45998216 :   return (e->flags & EDGE_DFS_BACK);
     373              : }
     374              : 
     375              : // Compute ranges defined in the current block, or exported to the
     376              : // next block.
     377              : 
     378              : void
     379    105082599 : path_range_query::compute_ranges_in_block (basic_block bb)
     380              : {
     381    105082599 :   bitmap_iterator bi;
     382    105082599 :   unsigned i;
     383              : 
     384    166251547 :   if (m_resolve && !at_entry ())
     385     38617152 :     compute_phi_relations (bb, prev_bb ());
     386              : 
     387              :   // Force recalculation of any names in the cache that are defined in
     388              :   // this block.  This can happen on interdependent SSA/phis in loops.
     389    362624582 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     390              :     {
     391    257541983 :       tree name = ssa_name (i);
     392    257541983 :       if (ssa_defined_in_bb (name, bb))
     393     61081729 :         m_cache.clear_range (name);
     394              :     }
     395              : 
     396              :   // Solve dependencies defined in this block, starting with the PHIs...
     397    105082599 :   compute_ranges_in_phis (bb);
     398              :   // ...and then the rest of the dependencies.
     399    362624582 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     400              :     {
     401    257541983 :       tree name = ssa_name (i);
     402    257541983 :       value_range r (TREE_TYPE (name));
     403              : 
     404    257541983 :       if (gimple_code (SSA_NAME_DEF_STMT (name)) != GIMPLE_PHI
     405    257541983 :           && range_defined_in_block (r, name, bb))
     406     40171421 :         m_cache.set_range (name, r);
     407    257541983 :     }
     408              : 
     409    105082599 :   if (at_exit ())
     410     38425399 :     return;
     411              : 
     412              :   // Solve dependencies that are exported to the next block.
     413     66657200 :   basic_block next = next_bb ();
     414     66657200 :   edge e = find_edge (bb, next);
     415              : 
     416     66657200 :   if (m_resolve && relations_may_be_invalidated (e))
     417              :     {
     418      2182971 :       if (DEBUG_SOLVER)
     419            0 :         fprintf (dump_file,
     420              :                  "Resetting relations as they may be invalidated in %d->%d.\n",
     421            0 :                  e->src->index, e->dest->index);
     422              : 
     423      2182971 :       path_oracle *p = get_path_oracle ();
     424              :       // ?? Instead of nuking the root oracle altogether, we could
     425              :       // reset the path oracle to search for relations from the top of
     426              :       // the loop with the root oracle.  Something for future development.
     427      2182971 :       p->reset_path ();
     428              :     }
     429              : 
     430     66657200 :   bitmap exports = gori_ssa ()->exports (bb);
     431     83525906 :   EXECUTE_IF_AND_IN_BITMAP (m_exit_dependencies, exports, 0, i, bi)
     432              :     {
     433     16868706 :       tree name = ssa_name (i);
     434     16868706 :       value_range r (TREE_TYPE (name));
     435     16868706 :       if (gori ().edge_range_p (r, e, name, *this))
     436              :         {
     437     15033976 :           value_range cached_range (TREE_TYPE (name));
     438     15033976 :           if (get_cache (cached_range, name))
     439     11922741 :             r.intersect (cached_range);
     440              : 
     441     15033976 :           m_cache.set_range (name, r);
     442     15033976 :           if (DEBUG_SOLVER)
     443              :             {
     444            0 :               fprintf (dump_file, "edge_range_p for ");
     445            0 :               print_generic_expr (dump_file, name, TDF_SLIM);
     446            0 :               fprintf (dump_file, " on edge %d->%d ",
     447            0 :                        e->src->index, e->dest->index);
     448            0 :               fprintf (dump_file, "is ");
     449            0 :               r.dump (dump_file);
     450            0 :               fprintf (dump_file, "\n");
     451              :             }
     452     15033976 :         }
     453     16868706 :     }
     454              : 
     455     66657200 :   if (m_resolve)
     456     38617152 :     compute_outgoing_relations (bb, next);
     457              : }
     458              : 
     459              : // Adjust all pointer exit dependencies in BB with non-null information.
     460              : 
     461              : void
     462    105082599 : path_range_query::adjust_for_non_null_uses (basic_block bb)
     463              : {
     464    105082599 :   prange r;
     465    105082599 :   bitmap_iterator bi;
     466    105082599 :   unsigned i;
     467              : 
     468    362624582 :   EXECUTE_IF_SET_IN_BITMAP (m_exit_dependencies, 0, i, bi)
     469              :     {
     470    257541983 :       tree name = ssa_name (i);
     471              : 
     472    257541983 :       if (!POINTER_TYPE_P (TREE_TYPE (name)))
     473    205308797 :         continue;
     474              : 
     475     52233186 :       if (get_cache (r, name))
     476              :         {
     477     21921682 :           if (!r.contains_zero_p ())
     478      8805347 :             continue;
     479              :         }
     480              :       else
     481     30311504 :         r.set_varying (TREE_TYPE (name));
     482              : 
     483     43427839 :       if (infer_oracle ().maybe_adjust_range (r, name, bb))
     484       882679 :         m_cache.set_range (name, r);
     485              :     }
     486    105082599 : }
     487              : 
     488              : // If NAME is a supported SSA_NAME, add it to the bitmap in dependencies.
     489              : 
     490              : bool
     491       163389 : path_range_query::add_to_exit_dependencies (tree name, bitmap dependencies)
     492              : {
     493       163389 :   if (TREE_CODE (name) == SSA_NAME
     494       163389 :       && value_range::supports_type_p (TREE_TYPE (name)))
     495       163389 :     return bitmap_set_bit (dependencies, SSA_NAME_VERSION (name));
     496              :   return false;
     497              : }
     498              : 
     499              : // Compute the exit dependencies to PATH.  These are essentially the
     500              : // SSA names used to calculate the final conditional along the path.
     501              : 
     502              : void
     503       799573 : path_range_query::compute_exit_dependencies (bitmap dependencies)
     504              : {
     505              :   // Start with the imports from the exit block...
     506       799573 :   basic_block exit = m_path[0];
     507       799573 :   bitmap_copy (dependencies, gori_ssa ()->imports (exit));
     508              : 
     509       799573 :   auto_vec<tree> worklist (bitmap_count_bits (dependencies));
     510       799573 :   bitmap_iterator bi;
     511       799573 :   unsigned i;
     512      2053582 :   EXECUTE_IF_SET_IN_BITMAP (dependencies, 0, i, bi)
     513              :     {
     514      1254009 :       tree name = ssa_name (i);
     515      1254009 :       worklist.quick_push (name);
     516              :     }
     517              : 
     518              :   // ...and add any operands used to define these imports.
     519      4587514 :   while (!worklist.is_empty ())
     520              :     {
     521      1494184 :       tree name = worklist.pop ();
     522      1494184 :       gimple *def_stmt = SSA_NAME_DEF_STMT (name);
     523      1821472 :       if (SSA_NAME_IS_DEFAULT_DEF (name)
     524      1494184 :           || !m_path.contains (gimple_bb (def_stmt)))
     525       327288 :         continue;
     526              : 
     527      1166896 :       if (gphi *phi = dyn_cast <gphi *> (def_stmt))
     528              :         {
     529      1899655 :           for (size_t i = 0; i < gimple_phi_num_args (phi); ++i)
     530              :             {
     531      1269081 :               edge e = gimple_phi_arg_edge (phi, i);
     532      1269081 :               tree arg = gimple_phi_arg (phi, i)->def;
     533              : 
     534      1269081 :               if (TREE_CODE (arg) == SSA_NAME
     535       803453 :                   && m_path.contains (e->src)
     536      1427863 :                   && bitmap_set_bit (dependencies, SSA_NAME_VERSION (arg)))
     537       148128 :                 worklist.safe_push (arg);
     538              :             }
     539              :         }
     540      2830079 :       else if (gassign *ass = dyn_cast <gassign *> (def_stmt))
     541              :         {
     542       498258 :           tree ssa[3];
     543       498258 :           unsigned count = gimple_range_ssa_names (ssa, 3, ass);
     544      1159905 :           for (unsigned j = 0; j < count; ++j)
     545       163389 :             if (add_to_exit_dependencies (ssa[j], dependencies))
     546        92047 :               worklist.safe_push (ssa[j]);
     547              :         }
     548              :     }
     549              :   // Exported booleans along the path, may help conditionals.
     550       799573 :   if (m_resolve)
     551      2614147 :     for (i = 0; i < m_path.length (); ++i)
     552              :       {
     553      1814574 :         basic_block bb = m_path[i];
     554      1814574 :         tree name;
     555      3689140 :         FOR_EACH_GORI_EXPORT_NAME (gori_ssa (), bb, name)
     556      1874566 :           if (TREE_CODE (TREE_TYPE (name)) == BOOLEAN_TYPE)
     557        57021 :             bitmap_set_bit (dependencies, SSA_NAME_VERSION (name));
     558              :       }
     559       799573 : }
     560              : 
     561              : // Compute the ranges for DEPENDENCIES along PATH.
     562              : //
     563              : // DEPENDENCIES are path exit dependencies.  They are the set of SSA
     564              : // names, any of which could potentially change the value of the final
     565              : // conditional in PATH.  If none is given, the exit dependencies are
     566              : // calculated from the final conditional in the path.
     567              : 
     568              : void
     569     38425399 : path_range_query::compute_ranges (const bitmap_head *dependencies)
     570              : {
     571     38425399 :   if (DEBUG_SOLVER)
     572            0 :     fprintf (dump_file, "\n==============================================\n");
     573              : 
     574     38425399 :   if (dependencies)
     575     37625826 :     bitmap_copy (m_exit_dependencies, dependencies);
     576              :   else
     577       799573 :     compute_exit_dependencies (m_exit_dependencies);
     578              : 
     579     38425399 :   if (m_resolve)
     580              :     {
     581     22551796 :       path_oracle *p = get_path_oracle ();
     582     22551796 :       p->reset_path (&(m_ranger.relation ()));
     583              :     }
     584              : 
     585     38425399 :   if (DEBUG_SOLVER)
     586              :     {
     587            0 :       fprintf (dump_file, "path_range_query: compute_ranges for path: ");
     588            0 :       for (unsigned i = m_path.length (); i > 0; --i)
     589              :         {
     590            0 :           basic_block bb = m_path[i - 1];
     591            0 :           fprintf (dump_file, "%d", bb->index);
     592            0 :           if (i > 1)
     593            0 :             fprintf (dump_file, "->");
     594              :         }
     595            0 :       fprintf (dump_file, "\n");
     596              :     }
     597              : 
     598    171739799 :   while (1)
     599              :     {
     600    105082599 :       basic_block bb = curr_bb ();
     601              : 
     602    105082599 :       compute_ranges_in_block (bb);
     603    105082599 :       adjust_for_non_null_uses (bb);
     604              : 
     605    105082599 :       if (at_exit ())
     606              :         break;
     607              : 
     608     66657200 :       move_next ();
     609     66657200 :     }
     610              : 
     611     38425399 :   if (DEBUG_SOLVER)
     612              :     {
     613            0 :       get_path_oracle ()->dump (dump_file);
     614            0 :       dump (dump_file);
     615              :     }
     616     38425399 : }
     617              : 
     618              : // A folding aid used to register and query relations along a path.
     619              : // When queried, it returns relations as they would appear on exit to
     620              : // the path.
     621              : //
     622              : // Relations are registered on entry so the path_oracle knows which
     623              : // block to query the root oracle at when a relation lies outside the
     624              : // path.  However, when queried we return the relation on exit to the
     625              : // path, since the root_oracle ignores the registered.
     626              : 
     627              : class jt_fur_source : public fur_depend
     628              : {
     629              : public:
     630              :   jt_fur_source (gimple *s, path_range_query *, const vec<basic_block> &);
     631              :   relation_kind query_relation (tree op1, tree op2) override;
     632              :   bool register_relation (gimple *, relation_kind, tree op1, tree op2) override;
     633              :   bool register_relation (edge, relation_kind, tree op1, tree op2) override;
     634              : private:
     635              :   basic_block m_entry;
     636              : };
     637              : 
     638     81498749 : jt_fur_source::jt_fur_source (gimple *s,
     639              :                               path_range_query *query,
     640              :                               const vec<basic_block> &path)
     641     81498749 :   : fur_depend (s, query)
     642              : {
     643     81498749 :   gcc_checking_assert (!path.is_empty ());
     644              : 
     645     81498749 :   m_entry = path[path.length () - 1];
     646     81498749 : }
     647              : 
     648              : // Ignore statement and register relation on entry to path.  Return false if
     649              : // no new relation is registered.
     650              : 
     651              : bool
     652     10917258 : jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2)
     653              : {
     654     10917258 :   return m_query->relation ().record (m_entry, k, op1, op2);
     655              : }
     656              : 
     657              : // Ignore edge and register relation on entry to path.  Return false if no
     658              : // new relation is registered.
     659              : 
     660              : bool
     661     14754476 : jt_fur_source::register_relation (edge, relation_kind k, tree op1, tree op2)
     662              : {
     663     14754476 :   return m_query->relation ().record (m_entry, k, op1, op2);
     664              : }
     665              : 
     666              : relation_kind
     667     39513699 : jt_fur_source::query_relation (tree op1, tree op2)
     668              : {
     669     39513699 :   if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
     670              :     return VREL_VARYING;
     671              : 
     672     13837247 :   return m_query->relation ().query (m_entry, op1, op2);
     673              : }
     674              : 
     675              : // Return the range of STMT at the end of the path being analyzed.
     676              : 
     677              : bool
     678     95981698 : path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
     679              : {
     680     95981698 :   tree type = gimple_range_type (stmt);
     681              : 
     682     95981698 :   if (!type || !r.supports_type_p (type))
     683              :     return false;
     684              : 
     685              :   // If resolving unknowns, fold the statement making use of any
     686              :   // relations along the path.
     687     95966635 :   if (m_resolve)
     688              :     {
     689     57152506 :       fold_using_range f;
     690     57152506 :       jt_fur_source src (stmt, this, m_path);
     691     57152506 :       if (!f.fold_stmt (r, stmt, src))
     692         4961 :         r.set_varying (type);
     693              :     }
     694              :   // Otherwise, fold without relations.
     695     38814129 :   else if (!fold_range (r, stmt, this))
     696            0 :     r.set_varying (type);
     697              : 
     698              :   return true;
     699              : }
     700              : 
     701              : // If possible, register the relation on the incoming edge E into PHI.
     702              : 
     703              : void
     704      9727731 : path_range_query::maybe_register_phi_relation (gphi *phi, edge e)
     705              : {
     706      9727731 :   tree arg = gimple_phi_arg_def (phi, e->dest_idx);
     707              : 
     708      9727731 :   if (!gimple_range_ssa_p (arg))
     709              :     return;
     710              : 
     711      7381064 :   if (relations_may_be_invalidated (e))
     712              :     return;
     713              : 
     714      5424555 :   basic_block bb = gimple_bb (phi);
     715      5424555 :   tree result = gimple_phi_result (phi);
     716              : 
     717              :   // Avoid recording the equivalence if the arg is defined in this
     718              :   // block, as that could create an ordering problem.
     719      5424555 :   if (ssa_defined_in_bb (arg, bb))
     720              :     return;
     721              : 
     722      5424555 :   if (dump_file && (dump_flags & TDF_DETAILS))
     723           54 :     fprintf (dump_file, "maybe_register_phi_relation in bb%d:", bb->index);
     724              : 
     725      5424555 :   get_path_oracle ()->killing_def (result);
     726      5424555 :   m_relation->record (entry_bb (), VREL_EQ, arg, result);
     727              : }
     728              : 
     729              : // Compute relations for each PHI in BB.  For example:
     730              : //
     731              : //   x_5 = PHI<y_9(5),...>
     732              : //
     733              : // If the path flows through BB5, we can register that x_5 == y_9.
     734              : 
     735              : void
     736     38617152 : path_range_query::compute_phi_relations (basic_block bb, basic_block prev)
     737              : {
     738     38617152 :   if (prev == NULL)
     739              :     return;
     740              : 
     741     38617152 :   edge e_in = find_edge (prev, bb);
     742              : 
     743     84651050 :   for (gphi_iterator iter = gsi_start_phis (bb); !gsi_end_p (iter);
     744     46033898 :        gsi_next (&iter))
     745              :     {
     746     46033898 :       gphi *phi = iter.phi ();
     747     46033898 :       tree result = gimple_phi_result (phi);
     748     46033898 :       unsigned nargs = gimple_phi_num_args (phi);
     749              : 
     750     46033898 :       if (!exit_dependency_p (result))
     751     36306167 :         continue;
     752              : 
     753     18049885 :       for (size_t i = 0; i < nargs; ++i)
     754     18049885 :         if (e_in == gimple_phi_arg_edge (phi, i))
     755              :           {
     756      9727731 :             maybe_register_phi_relation (phi, e_in);
     757      9727731 :             break;
     758              :           }
     759              :     }
     760              : }
     761              : 
     762              : // Compute outgoing relations from BB to NEXT.
     763              : 
     764              : void
     765     38617152 : path_range_query::compute_outgoing_relations (basic_block bb, basic_block next)
     766              : {
     767     77234304 :   if (gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (bb)))
     768              :     {
     769     24346243 :       int_range<2> r;
     770     24346243 :       edge e0 = EDGE_SUCC (bb, 0);
     771     24346243 :       edge e1 = EDGE_SUCC (bb, 1);
     772              : 
     773     24346243 :       if (e0->dest == next)
     774     10353340 :         gcond_edge_range (r, e0);
     775     13992903 :       else if (e1->dest == next)
     776     13992903 :         gcond_edge_range (r, e1);
     777              :       else
     778            0 :         gcc_unreachable ();
     779              : 
     780     24346243 :       jt_fur_source src (NULL, this, m_path);
     781     24346243 :       src.register_outgoing_edges (cond, r, e0, e1);
     782     24346243 :     }
     783     38617152 : }
        

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.