]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Create a ranger-local flag for non-executable edges.
authorAndrew MacLeod <amacleod@redhat.com>
Wed, 22 Sep 2021 20:58:22 +0000 (16:58 -0400)
committerAndrew MacLeod <amacleod@redhat.com>
Thu, 23 Sep 2021 16:56:43 +0000 (12:56 -0400)
Instead of repurposing EDGE_EXECUTABLE, ranger creates a local flag and
ultizes it throughout.

* gimple-range-cache.cc (ranger_cache::ranger_cache): Take
non-executable_edge flag as parameter.
* gimple-range-cache.h (ranger_cache): Adjust prototype.
* gimple-range-gori.cc (gori_compute::gori_compute): Take
non-executable_edge flag as parameter.
(gori_compute::outgoing_edge_range_p): Check new flag.
* gimple-range-gori.h (gori_compute): Adjust prototype.
* gimple-range.cc (gimple_ranger::gimple_ranger): Create new flag.
(gimple_ranger::range_on_edge): Check new flag.
* gimple-range.h (gimple_ranger::non_executable_edge_flag): New.
* gimple-ssa-evrp.c (rvrp_folder): Pass ranger flag to simplifer.
(hybrid_folder::hybrid_folder): Set ranger non-executable flag value.
(hybrid_folder::fold_stmt): Set flag value in the simplifer.
* vr-values.c (simplify_using_ranges::set_and_propagate_unexecutable):
Use not_executable flag if provided inmstead of EDGE_EXECUTABLE.
(simplify_using_ranges::simplify_switch_using_ranges): Clear
EDGE_EXECUTABLE like it originally did.
(simplify_using_ranges::cleanup_edges_and_switches): Clear any
NON_EXECUTABLE flags.
(simplify_using_ranges::simplify_using_ranges): Adjust.
* vr-values.h (class simplify_using_ranges): Adjust.
(simplify_using_ranges::set_range_query): Add non-executable flag param.

gcc/gimple-range-cache.cc
gcc/gimple-range-cache.h
gcc/gimple-range-gori.cc
gcc/gimple-range-gori.h
gcc/gimple-range.cc
gcc/gimple-range.h
gcc/gimple-ssa-evrp.c
gcc/vr-values.c
gcc/vr-values.h

index b856b212169bf60e31f028b05186c7b9aec1b83d..61043d3f37507056e4618f76c2124aede3169c71 100644 (file)
@@ -750,7 +750,8 @@ temporal_cache::set_always_current (tree name)
 
 // --------------------------------------------------------------------------
 
-ranger_cache::ranger_cache ()
+ranger_cache::ranger_cache (int not_executable_flag)
+                                               : m_gori (not_executable_flag)
 {
   m_workback.create (0);
   m_workback.safe_grow_cleared (last_basic_block_for_fn (cfun));
index 3b55673fd29aa32b9fd6430f60de19b7ac92d939..4937a0b305a5befedf8608a6f8fab210d01fb1af 100644 (file)
@@ -92,7 +92,7 @@ private:
 class ranger_cache : public range_query
 {
 public:
-  ranger_cache ();
+  ranger_cache (int not_executable_flag);
   ~ranger_cache ();
 
   virtual bool range_of_expr (irange &r, tree name, gimple *stmt);
index f5a35287beda2e441979787e72c36d6f55b3784a..4a1ade7f921b1039022e0b7625c2314f5040f0db 100644 (file)
@@ -634,8 +634,9 @@ debug (gori_map &g)
 
 // Construct a gori_compute object.
 
-gori_compute::gori_compute () : tracer ("GORI ")
+gori_compute::gori_compute (int not_executable_flag) : tracer ("GORI ")
 {
+  m_not_executable_flag = not_executable_flag;
   // Create a boolean_type true and false range.
   m_bool_zero = int_range<2> (boolean_false_node, boolean_false_node);
   m_bool_one = int_range<2> (boolean_true_node, boolean_true_node);
@@ -1214,7 +1215,7 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
   int_range_max lhs;
   unsigned idx;
 
-  if ((e->flags & EDGE_EXECUTABLE) == 0)
+  if ((e->flags & m_not_executable_flag))
     {
       r.set_undefined ();
       if (dump_file && (dump_flags & TDF_DETAILS))
index 688468c879082b53bb305c1e523901d75a313e45..ec0b95145f00924e11aa859a948da1308924e30c 100644 (file)
@@ -147,12 +147,16 @@ private:
 // expr_range_in_bb is simply a wrapper which calls ssa_range_in_bb for 
 // SSA_NAMES and otherwise simply calculates the range of the expression.
 //
+// The constructor takes a flag value to use on edges to check for the
+// NON_EXECUTABLE_EDGE property.  The zero default means no flag is checked.
+// All value requests from NON_EXECUTABLE_EDGE edges are returned UNDEFINED.
+//
 // The remaining routines are internal use only.
 
 class gori_compute : public gori_map
 {
 public:
-  gori_compute ();
+  gori_compute (int not_executable_flag = 0);
   bool outgoing_edge_range_p (irange &r, edge e, tree name, range_query &q);
   bool has_edge_range_p (tree name, edge e = NULL);
   void dump (FILE *f);
@@ -181,6 +185,7 @@ private:
 
   gimple_outgoing_range outgoing;      // Edge values for COND_EXPR & SWITCH_EXPR.
   range_tracer tracer;
+  int m_not_executable_flag;
 };
 
 // These routines provide a GIMPLE interface to the range-ops code.
index 625d13647f75436bb72a1d639c27716e5e46a923..d4108db18557609eaeb130b54bf7c28a98381125 100644 (file)
@@ -34,15 +34,29 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "tree-scalar-evolution.h"
 #include "gimple-range.h"
-#include "domwalk.h"
 
-gimple_ranger::gimple_ranger () : tracer ("")
+gimple_ranger::gimple_ranger () :
+       non_executable_edge_flag (cfun),
+       m_cache (non_executable_edge_flag),
+       tracer ("")
 {
   // If the cache has a relation oracle, use it.
   m_oracle = m_cache.oracle ();
   if (dump_file && (param_evrp_mode & EVRP_MODE_TRACE))
     tracer.enable_trace ();
-  set_all_edges_as_executable (cfun);
+
+  // Ensure the not_executable flag is clear everywhere.
+  if (flag_checking)
+    {
+      basic_block bb;
+      FOR_ALL_BB_FN (bb, cfun)
+       {
+         edge_iterator ei;
+         edge e;
+         FOR_EACH_EDGE (e, ei, bb->succs)
+           gcc_checking_assert ((e->flags & non_executable_edge_flag) == 0);
+       }
+    }
 }
 
 bool
@@ -174,7 +188,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
     }
 
   // Check to see if the edge is executable.
-  if ((e->flags & EDGE_EXECUTABLE) == 0)
+  if ((e->flags & non_executable_edge_flag))
     {
       r.set_undefined ();
       if (idx)
index eaebb9c5833793cfb262903d88d20c643a7e08f6..191a075a1b0115f8d4f93b6554c9eb3981b40f69 100644 (file)
@@ -56,6 +56,7 @@ public:
   inline gori_compute &gori ()  { return m_cache.m_gori; }
   virtual void dump (FILE *f) OVERRIDE;
   void dump_bb (FILE *f, basic_block bb);
+  auto_edge_flag non_executable_edge_flag;
 protected:
   bool fold_range_internal (irange &r, gimple *s, tree name);
   ranger_cache m_cache;
index 254542ef4ccb7c39e3bdb444d947e401fcdeffa1..437f19471f14e9055c602f0411fbc7402fae83d9 100644 (file)
@@ -121,7 +121,7 @@ public:
   rvrp_folder () : substitute_and_fold_engine (), m_simplifier ()
   {
     m_ranger = enable_ranger (cfun);
-    m_simplifier.set_range_query (m_ranger);
+    m_simplifier.set_range_query (m_ranger, m_ranger->non_executable_edge_flag);
     m_pta = new pointer_equiv_analyzer (m_ranger);
   }
       
@@ -205,12 +205,16 @@ public:
     if (evrp_first)
       {
        first = &m_range_analyzer;
+       first_exec_flag = 0;
        second = m_ranger;
+       second_exec_flag = m_ranger->non_executable_edge_flag;
       }
      else
       {
        first = m_ranger;
+       first_exec_flag = m_ranger->non_executable_edge_flag;
        second = &m_range_analyzer;
+       second_exec_flag = 0;
       }
     m_pta = new pointer_equiv_analyzer (m_ranger);
   }
@@ -227,11 +231,11 @@ public:
 
   bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
     {
-      simplifier.set_range_query (first);
+      simplifier.set_range_query (first, first_exec_flag);
       if (simplifier.simplify (gsi))
        return true;
 
-      simplifier.set_range_query (second);
+      simplifier.set_range_query (second, second_exec_flag);
       if (simplifier.simplify (gsi))
        {
          if (dump_file)
@@ -267,7 +271,9 @@ private:
   DISABLE_COPY_AND_ASSIGN (hybrid_folder);
   gimple_ranger *m_ranger;
   range_query *first;
+  int first_exec_flag;
   range_query *second;
+  int second_exec_flag;
   pointer_equiv_analyzer *m_pta;
   tree choose_value (tree evrp_val, tree ranger_val);
 };
index 3b8d0674471a749ae37bd17a196c0a154bf523ce..9bf58f416f2d86f2fcb2a494861fa6807fa52fb7 100644 (file)
@@ -3460,19 +3460,21 @@ range_fits_type_p (const value_range *vr,
 void
 simplify_using_ranges::set_and_propagate_unexecutable (edge e)
 {
-  // If EXECUUTABLE is already clear, we're done.
-  if ((e->flags & EDGE_EXECUTABLE) == 0)
+  // If not_executable is already set, we're done.
+  // This works in the absence of a flag as well.
+  if ((e->flags & m_not_executable_flag) == m_not_executable_flag)
     return;
 
-  e->flags &= ~EDGE_EXECUTABLE;
+  e->flags |= m_not_executable_flag;
+  m_flag_set_edges.safe_push (e);
 
   // Check if the destination block needs to propagate the property.
   basic_block bb = e->dest;
 
-  // If any entry edge is marked EXECUTABLE, we are done.
+  // If any incoming edge is executable, we are done.
   edge_iterator ei;
   FOR_EACH_EDGE (e, ei, bb->preds)
-    if (e->flags & EDGE_EXECUTABLE)
+    if ((e->flags & m_not_executable_flag) == 0)
       return;
 
   // This block is also unexecutable, propagate to all exit edges as well.
@@ -3805,6 +3807,7 @@ simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt)
        }
       to_remove_edges.safe_push (e);
       set_and_propagate_unexecutable (e);
+      e->flags &= ~EDGE_EXECUTABLE;
       e->flags |= EDGE_IGNORE;
     }
 
@@ -3822,6 +3825,12 @@ simplify_using_ranges::cleanup_edges_and_switches (void)
   edge e;
   switch_update *su;
 
+  /* Clear any edges marked as not executable.  */
+  if (m_not_executable_flag)
+    {
+      FOR_EACH_VEC_ELT (m_flag_set_edges, i, e)
+       e->flags &= ~m_not_executable_flag;
+    }
   /* Remove dead edges from SWITCH_EXPR optimization.  This leaves the
      CFG in a broken state and requires a cfg_cleanup run.  */
   FOR_EACH_VEC_ELT (to_remove_edges, i, e)
@@ -4124,11 +4133,14 @@ simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b,
   return false;
 }
 
-simplify_using_ranges::simplify_using_ranges (range_query *query)
+simplify_using_ranges::simplify_using_ranges (range_query *query,
+                                             int not_executable_flag)
   : query (query)
 {
   to_remove_edges = vNULL;
   to_update_switch_stmts = vNULL;
+  m_not_executable_flag = not_executable_flag;
+  m_flag_set_edges = vNULL;
 }
 
 simplify_using_ranges::~simplify_using_ranges ()
index 46939081c61d960c3b6e6873b75f5b935b683264..821bcb9d58d552a6af4f8a9efb79e70d3aa1bf25 100644 (file)
@@ -30,9 +30,11 @@ along with GCC; see the file COPYING3.  If not see
 class simplify_using_ranges
 {
 public:
-  simplify_using_ranges (class range_query *query = NULL);
+  simplify_using_ranges (range_query *query = NULL,
+                        int not_executable_flag = 0);
   ~simplify_using_ranges ();
-  void set_range_query (class range_query *q) { query = q; }
+  void set_range_query (class range_query *q, int not_executable_flag = 0)
+      { query = q; m_not_executable_flag = not_executable_flag; }
 
   bool simplify (gimple_stmt_iterator *);
 
@@ -82,6 +84,8 @@ private:
   vec<edge> to_remove_edges;
   vec<switch_update> to_update_switch_stmts;
   class range_query *query;
+  int m_not_executable_flag;   // Non zero if not_executable flag exists.
+  vec<edge> m_flag_set_edges;  // List of edges with flag to be cleared.
 };
 
 /* The VR_VALUES class holds the current view of range information