]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Check in initial version of Early Ranger VRP
authorAndrew Macleod <amacleod@gcc.gnu.org>
Tue, 3 Apr 2018 14:56:54 +0000 (14:56 +0000)
committerAndrew Macleod <amacleod@gcc.gnu.org>
Tue, 3 Apr 2018 14:56:54 +0000 (14:56 +0000)
disable with -fno-rvrp

From-SVN: r259033

12 files changed:
gcc/common.opt
gcc/gimple-ssa-evrp.c
gcc/passes.c
gcc/passes.def
gcc/range-op.c
gcc/ssa-range-global.c
gcc/ssa-range-global.h
gcc/ssa-range-stmt.c
gcc/ssa-range.c
gcc/ssa-range.h
gcc/timevar.def
gcc/tree-pass.h

index e0bc4d1bb18d2e42b352ff09760105c1fee96f16..c2a82aa83e34d971872664c2678bed8f1f3fd017 100644 (file)
@@ -2646,6 +2646,11 @@ ftree-vrp
 Common Report Var(flag_tree_vrp) Init(0) Optimization
 Perform Value Range Propagation on trees.
 
+ftree-rvrp
+Common Report Var(flag_tree_rvrp) Init(1) Optimization
+Perform New Ranger Value Range Propagation on trees.
+
+
 fsplit-paths
 Common Report Var(flag_split_paths) Init(0) Optimization
 Split paths leading to loop backedges.
index c9bbf09a4064e5fc6c35e6eb71c015363d7d905f..11d53ce8e1125c31ed433bbce5074c28383721c9 100644 (file)
@@ -41,6 +41,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-cfgcleanup.h"
 #include "vr-values.h"
 #include "gimple-ssa-evrp-analyze.h"
+#include "ssa-range.h"
+#include "ssa-range-global.h"
+
 
 class evrp_folder : public substitute_and_fold_engine
 {
@@ -347,3 +350,174 @@ make_pass_early_vrp (gcc::context *ctxt)
   return new pass_early_vrp (ctxt);
 }
 
+
+/* Main entry point for the early Ranger vrp pass.  */
+
+static bool
+argument_ok_to_propagate (tree name)
+{
+  if (TREE_CODE (name) != SSA_NAME)
+    return true;
+  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+    {
+      // From may_propagate_copy
+      if (SSA_NAME_IS_DEFAULT_DEF (name) && (SSA_NAME_VAR (name) == NULL_TREE
+          || TREE_CODE (SSA_NAME_VAR (name)) == VAR_DECL))
+      return true;
+    }
+  // probably dont need this.
+  if (virtual_operand_p (name))
+    return false;
+  return true;
+}
+
+static unsigned int
+execute_ranger_vrp ()
+{
+  path_ranger ranger;
+  
+  basic_block bb;
+  irange r;
+  wide_int i;
+  unsigned x;
+  bitmap_iterator bi;
+  bitmap touched = BITMAP_ALLOC (NULL);
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      gcond *cond;
+      gimple *stmt = last_stmt (bb);
+      if (stmt && (cond = dyn_cast <gcond *> (stmt)))
+        {
+         if (dump_file)
+           {
+             fprintf (dump_file, "Considering ");
+             print_gimple_stmt (dump_file, cond, 0,0);
+           }
+         if (ranger.path_range_stmt (r, stmt))
+           {
+             if (dump_file)
+               {
+                 fprintf (dump_file, "Found a range for the expression: ");
+                 r.dump (dump_file);
+                 fprintf (dump_file, "\n");
+               }
+
+             if (r.singleton_p (i))
+               {
+                 if (!argument_ok_to_propagate (gimple_cond_lhs (cond)) ||
+                     !argument_ok_to_propagate (gimple_cond_rhs (cond)))
+                   {
+                     if (dump_file)
+                       {
+                         fprintf (dump_file, "Found  BB%d branch",bb->index);
+                         print_gimple_stmt (dump_file, stmt, 0, 0);
+                         fprintf (dump_file, "cannot eliminate. proprules.\n");
+                         fprintf (stderr,"\n  *********************** caught one\n");
+                       }
+                     continue;
+                   }
+
+                 /* If either operand is an ssa_name, set the touched bit for
+                    potential removal later if no uses are left.  */
+                 tree t = valid_irange_ssa (gimple_cond_lhs (cond));
+                 if (t)
+                   bitmap_set_bit (touched, SSA_NAME_VERSION (t));
+                 t = valid_irange_ssa (gimple_cond_rhs (cond));
+                 if (t)
+                   bitmap_set_bit (touched, SSA_NAME_VERSION (t));
+
+                 if (dump_file)
+                   {
+                     fprintf (dump_file, "eliminating BB%d branch",bb->index);
+                     print_gimple_stmt (dump_file, stmt, 0, 0);
+                   }
+
+                 /* Rewrite the condition to either true or false.  */
+                 if (wi::eq_p (i, 0))
+                   gimple_cond_make_false (cond);
+                 else
+                   gimple_cond_make_true (cond);
+
+                 if (dump_file)
+                   {
+                     fprintf (dump_file, "Re-written to: \n");
+                     print_gimple_stmt (dump_file, cond, 0, 0);
+                     fprintf (dump_file, "\n");
+                   }
+               }
+           }
+       }
+
+    }
+
+  // Now visit each name that was rewritten and see if the definiing statement
+  // can be deleted due to no more uses in the program
+  EXECUTE_IF_SET_IN_BITMAP (touched, 0, x, bi)
+    {
+      tree name = ssa_name (x);
+      gimple *s = SSA_NAME_DEF_STMT (name);
+      
+      if (s)
+        {
+         if (has_zero_uses (name))
+           {
+             if (dump_file)
+               {
+                 fprintf (dump_file, "Should delete");
+                 print_gimple_stmt (dump_file, s, 0, 0);
+               }
+           }
+         else
+           {
+             if (dump_file)
+               {
+                 fprintf (dump_file, "Still has uses, Could not delete ");
+                 print_gimple_stmt (dump_file, s, 0, 0);
+               }
+           }
+       }
+    }
+  return 0;
+}
+
+namespace {
+
+const pass_data pass_data_ranger_vrp =
+{
+  GIMPLE_PASS, /* type */
+  "rvrp", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_TREE_RANGER_VRP, /* tv_id */
+  PROP_ssa, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  ( TODO_cleanup_cfg | TODO_verify_all ),
+};
+
+class pass_ranger_vrp : public gimple_opt_pass
+{
+public:
+  pass_ranger_vrp (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_ranger_vrp, ctxt)
+    {}
+
+  /* opt_pass methods: */
+  opt_pass * clone () { return new pass_ranger_vrp (m_ctxt); }
+  virtual bool gate (function *)
+    {
+      return flag_tree_rvrp != 0;
+    }
+  virtual unsigned int execute (function *)
+    { return execute_ranger_vrp (); }
+
+}; // class pass_vrp
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_ranger_vrp (gcc::context *ctxt)
+{
+  return new pass_ranger_vrp (ctxt);
+}
+
index c09cd921306b972ba4af8e48d32f7eb09ed7d9f7..6d26da6c8481fd4ad0311a3ef0a0ed50ea870c60 100644 (file)
@@ -2494,6 +2494,12 @@ execute_one_pass (opt_pass *pass)
     do_per_function (verify_curr_properties,
                     (void *)(size_t)pass->properties_required);
 
+  if (pass->name && !strcmp (pass->name, "rvrp"))
+    {
+      path_ranger r;
+      r.exercise (dump_file);
+    }
+
   /* Do it!  */
   todo_after = pass->execute (cfun);
 
@@ -2558,12 +2564,6 @@ execute_one_pass (opt_pass *pass)
   if (!current_function_decl)
     symtab->process_new_functions ();
 
-  if (pass->name && !strcmp (pass->name, "ssa"))
-    {
-      path_ranger r;
-      r.exercise (dump_file);
-    }
-
   pass_fini_dump_file (pass);
 
   if (pass->type != SIMPLE_IPA_PASS && pass->type != IPA_PASS)
index 3ebcfc30349fff2f55540a61885ebc23e9da9e38..7f2b7ea76eda165e98ebf6b2482991e416e889f1 100644 (file)
@@ -93,6 +93,7 @@ along with GCC; see the file COPYING3.  If not see
             execute TODO_rebuild_alias at this point.  */
          NEXT_PASS (pass_build_ealias);
          NEXT_PASS (pass_fre);
+         NEXT_PASS (pass_ranger_vrp);
          NEXT_PASS (pass_early_vrp);
          NEXT_PASS (pass_merge_phi);
           NEXT_PASS (pass_dse);
index 61917274296976c75636245f63d618ed4394734e..9837710db01c1e8da0eb6ab8f9ac858f3bdaacc5 100644 (file)
@@ -1011,6 +1011,14 @@ bool
 operator_multiply::op1_irange (irange& r, const irange& lhs,
                               const irange& op2) const
 {
+  wide_int c;
+  // For overflow types. all we know is that the lower "precsion / 2" bits
+  // match up with the range of the LHS.  See if we know anything about
+  // the zero bits.
+  if (lhs.singleton_p (c) && TYPE_OVERFLOW_WRAPS (lhs.get_type ()))
+   {
+     return false;
+   }
   return op_rr (OPM_DIV, r, lhs, op2);
 }
 
@@ -1018,6 +1026,14 @@ bool
 operator_multiply::op2_irange (irange& r, const irange& lhs,
                               const irange& op1) const
 {
+  wide_int c;
+  // For overflow types. all we know is that the lower "precsion / 2" bits
+  // match up with the range of the LHS.  See if we know anything about
+  // the zero bits.
+  if (lhs.singleton_p (c) && TYPE_OVERFLOW_WRAPS (lhs.get_type ()))
+   {
+     return false;
+   }
   return op_rr (OPM_DIV, r, lhs, op1);
 }
 
index d477be34b1947db6a06387261df49c8c88003f50..12a78f4c18b8139ef52dc56977f23c0b7c0d339b 100644 (file)
@@ -59,6 +59,7 @@ public:
   ~ssa_global_cache ();
   bool get_global_range (irange& r, tree name)  const;
   void set_global_range (tree name, const irange&r);
+  void clear_global_range (tree name);
   void clear ();
   void copy_to_range_info ();
   void dump (FILE *f = stderr);
@@ -112,6 +113,13 @@ set_global_ssa_range (tree name, const irange&r)
   globals->set_global_range (name, r);
 }
 
+/* Clear the global range for NAME.  */
+void
+clear_global_ssa_range (tree name)
+{
+  gcc_assert (globals);
+  globals->clear_global_range (name);
+}
 // ---------------------------------------------------------------
 
 /* Initialize a global cache.  */
@@ -157,6 +165,13 @@ ssa_global_cache::set_global_range (tree name, const irange& r)
     }
 }
 
+/* Set the range for NAME to R in the glonbal cache.  */
+void
+ssa_global_cache::clear_global_range (tree name)
+{
+  tab[SSA_NAME_VERSION (name)] = NULL;
+}
+
 /* Clear the global cache.  */
 void
 ssa_global_cache::clear ()
index 95e94e39163818542fd652506b5b809e77f01e64..69accee2b8389c062d1f2f4cba0e1839bb3c39af 100644 (file)
@@ -27,5 +27,6 @@ void dump_global_ssa_range_cache (FILE *f);
 
 bool get_global_ssa_range (irange& r, tree name);
 void set_global_ssa_range (tree name, const irange&r);
+void clear_global_ssa_range (tree name);
 
 #endif /* GCC_SSA_RANGE_GLOBAL_H  */
index 606b1af656998dd0c0da5625aaf2e1844b590515..181a4b560a181e23218e029b3aedcbb52a7ffd14 100644 (file)
@@ -147,11 +147,22 @@ range_stmt::fold (irange &res, const irange& r1) const
   irange_operator *handler = irange_op_handler (code);
   gcc_assert (handler != NULL);
 
+  // Empty ranges are viral.  
+  if (r1.empty_p ())
+    {
+      if (lhs)
+        res.clear (TREE_TYPE (lhs));
+      else
+        res.clear (r1.get_type ());
+      return true;
+    }
+
   /* Single ssa operations require the LHS type as the second range.  */
   if (lhs)
     r2.set_range_for_type (TREE_TYPE (lhs));
   else
     r2.clear ();
+
   return handler->fold_range (res, r1, r2);
 }
 
@@ -165,6 +176,13 @@ range_stmt::fold (irange &res, const irange& r1, const irange& r2) const
   irange_operator *handler = irange_op_handler (code);
   gcc_assert (handler != NULL);
 
+  // Empty ranges are viral.  
+  if (r1.empty_p () || r2.empty_p ())
+    {
+      res.clear (r1.get_type ());
+      return true;
+    }
+
   // Make sure this isnt a unary operation being passed a second range.
   gcc_assert (op2);
   return handler->fold_range (res, r1, r2);
index ceeb9cc903fdcc6f3bb7bcad39027a9fc63a1768..c185a9c51a6addd5d3924519e4412bad5e1e9589 100644 (file)
@@ -253,16 +253,15 @@ bool
 path_ranger::path_range_entry (irange& r, tree name, basic_block bb)
 {
   gimple *def_stmt;
-  basic_block def_bb;
+  basic_block def_bb = NULL;
 
   if (!valid_irange_ssa (name))
     return false;
 
   def_stmt = SSA_NAME_DEF_STMT (name);
-  if (!def_stmt)
-    return false;
+  if (def_stmt)
+    def_bb = gimple_bb (def_stmt);;
 
-  def_bb = gimple_bb (def_stmt);;
   if (!def_bb)
     def_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
 
@@ -291,18 +290,22 @@ path_ranger::path_range_edge (irange& r, tree name, edge e)
   if (!valid_irange_ssa (name))
     return false;
 
+  /* Get an initial range for NAME.  */
+  
   gimple *stmt = SSA_NAME_DEF_STMT (name);
   if (stmt && gimple_bb (stmt) == e->src)
     {
-      if (!path_range_of_def (r, stmt))
-        get_global_ssa_range (r, name);
+      /* If it is in this block, evaluate it.  */
+      if (!path_range_stmt (r, stmt))
+        return false;
     }
   else
-    /* Get the range for the def and possible basic block.  */
+    /* The name comes from outside this block, so evaluate it's value on
+       entry to the block.  */
     if (!path_range_entry (r, name, bb))
-      return false;
+      error (" Why can't we get a live on entry range? ");
 
-  /* Now intersect it with what we know about this edge.  */
+  /* Now intersect it with what NAME evaluates to on this edge.  */
   irange edge_range;
   if (range_on_edge (edge_range, name, e))
     {
@@ -333,7 +336,7 @@ path_ranger::determine_block (tree name, basic_block bb, basic_block def_bb)
   /* Avoid infinite recursion by marking this block as calculated.  */
   block_cache->get_block_ranges (name).set_bb_range_for_type (bb);
 
-  /* Visit each predecessor to reseolve them.  */
+  /* Visit each predecessor to resolve them.  */
   FOR_EACH_EDGE (e, ei, bb->preds)
     {
       determine_block (name, e->src, def_bb);
@@ -345,7 +348,7 @@ path_ranger::determine_block (tree name, basic_block bb, basic_block def_bb)
     {
       irange pred_range;
       basic_block src = e->src;
-      // Should be using range_on_def
+      // Should be using range_on_def??? or something.
       if (src == def_bb)
         get_global_ssa_range (pred_range, name);
       else
@@ -374,58 +377,146 @@ path_ranger::determine_block (tree name, basic_block bb, basic_block def_bb)
     block_cache->get_block_ranges (name).set_bb_range (bb, block_result);
 }
 
+
+bool
+path_ranger::process_phi (irange &r, gphi *phi)
+{
+  tree phi_def = gimple_phi_result (phi);
+  unsigned x;
+
+  if (!valid_irange_ssa (phi_def))
+    return false;
+
+  // If this node has already been processed, just return it.
+  if (get_global_ssa_range (r, phi_def))
+    return true;
+
+  // Avoid infinite recursion by initializing global cache 
+  r.set_range (phi_def);
+  set_global_ssa_range (phi_def, r);
+  // And start with an empty range, unioning in each areument's range.
+  r.clear (TREE_TYPE (phi_def));
+  for (x = 0; x < gimple_phi_num_args (phi); x++)
+    {
+      irange arg_range;
+      tree arg = gimple_phi_arg_def (phi, x);
+      edge e = gimple_phi_arg_edge (phi, x);
+      if (!path_range_edge (arg_range, arg, e))
+       if (!get_operand_range (arg_range, arg))
+         return false;
+
+      normalize_bool_type (r, arg_range);
+      r.union_ (arg_range);
+      if (r.range_for_type_p ())
+       break;
+    }
+
+  set_global_ssa_range (phi_def, r);
+  return true;
+}
+
 bool
 path_ranger::path_range_stmt (irange& r, tree name, gimple *g)
 {
-#if 0
+  return path_get_operand (r, name, gimple_bb (g));
+}
+
+
+bool
+path_ranger::path_range_stmt (irange& r, gimple *g)
+{
+  tree name = gimple_get_lhs (g);
+  irange range_op1, range_op2;
+  range_stmt rn;
+  basic_block bb = gimple_bb (g);
+
   if (is_a <gphi *> (g))
     {
       gphi *phi = as_a <gphi *> (g);
-      tree phi_def = gimple_phi_result (phi);
-      irange tmp;
-      unsigned x;
+      return process_phi (r, phi);
+    }
+  // Not all statements have a LHS.  */
+  if (name)
+    {
+      // If this STMT has already been processed, return that value. 
+      if (get_global_ssa_range (r, name))
+       return true;
+     
+      // avoid infinite recursion by initializing global cache 
+      r.set_range (name);
+      set_global_ssa_range (name, r);
+    }
 
-      /* Only calculate ranges for PHI defs.  */
-      if (phi_def != name)
-        return false;
+  rn = g;
+  if (!rn.valid ())
+    return false;
 
-      r.clear (TREE_TYPE (name));
+  if (!path_get_operand (range_op1, rn.operand1 (), bb))
+    return false;
+    
+  // If this is a unary operation, call fold now.  
+  if (!rn.operand2 ())
+    return rn.fold (r, range_op1);
 
-      for (x = 0; x < gimple_phi_num_args (phi); x++)
-        {
-         bool res;
-         tree arg = gimple_phi_arg_def (phi, x);
-         if (TREE_CODE (arg) == SSA_NAME)
-           res = path_range_edge (tmp, arg, gimple_phi_arg_edge (phi, x));
-         else
-           res = get_operand_range (tmp, arg);
-          if (res)
-           r.union_ (tmp);
-         else
-           {
-             r.set_range_for_type (name);
-             return false;
-           }
-         if (r.range_for_type_p ())
-           return true;
-       }
-      return true;
+  if (!path_get_operand (range_op2, rn.operand2 (), bb))
+    return false;
+
+  normalize_bool_type (range_op1, range_op2);
+  bool res = rn.fold (r, range_op1, range_op2);
 
+  if (name)
+    {
+      if (res)
+       set_global_ssa_range (name, r);
+      else
+       clear_global_ssa_range (name);
     }
-#endif
-  return range_on_stmt (r, name, g);
+  return res;
 }
 
 
-static inline bool
+static inline gimple *
 ssa_name_same_bb_p (tree name, basic_block bb)
 {
   gimple *g = SSA_NAME_DEF_STMT (name);
   if (!g || gimple_bb (g) != bb)
-   return false;
-  return true;
+   return NULL;
+  return g;
 }
 
+
+/* Determine a range for NAME in basic block BB.
+   If FULL is true, then rescursively call the path ranger to fully evaluate
+   a range for NAME.
+   if FULL is false, then dont go outside the current block to find a best 
+   guess range.
+   if edge E is specified, then only follow E for calculations.  */
+
+bool
+path_ranger::path_get_operand (irange &r, tree name, basic_block bb)
+{
+  if (!valid_irange_ssa (name))
+    return get_operand_range (r, name);
+    
+  // check if the defining statement is in the same block.
+  gimple *s = ssa_name_same_bb_p (name, bb);
+  if (s)
+    {
+      // This means NAME is defined in the same block, simply try to extract 
+      // a range from that statement. 
+      if (!path_range_stmt (r, s))
+       return get_operand_range (r, name);
+      return true;
+    }
+
+  if (path_range_entry (r, name, bb))
+    return true;
+  return get_operand_range (r, name);
+}
+
+
 bool
 path_ranger::path_fold_stmt (irange &r, range_stmt &rn, basic_block bb, edge e)
 {
@@ -482,8 +573,7 @@ path_ranger::path_range_of_def (irange &r, gimple *g, edge e)
 
   range_stmt rn(g);
   if (!rn.valid())
-    return false;
-
+    return false; 
   return path_fold_stmt (r, rn, bb, e);
 
 }
@@ -494,7 +584,7 @@ path_ranger::path_range_of_def (irange &r, gimple *g, edge e)
 bool
 path_ranger::path_range_of_def (irange &r, gimple *g)
 {
-  tree name = gimple_get_lhs (g);
+  tree name;
   basic_block bb = gimple_bb (g);
   tree arg;
   irange range_op1, range_op2;
@@ -517,7 +607,7 @@ path_ranger::path_range_of_def (irange &r, gimple *g)
       if (get_global_ssa_range (r, phi_def))
         return true;
 
-      // avoid infinite recursion by initializing global cache 
+      // Avoid infinite recursion by initializing global cache 
       r.set_range (phi_def);
       set_global_ssa_range (phi_def, r);
 
@@ -545,7 +635,10 @@ path_ranger::path_range_of_def (irange &r, gimple *g)
     return false;
 
   name = gimple_get_lhs (g);
-  gcc_checking_assert (name);
+
+  /* If there is no LHS, then we are simply folding an expression.  */
+  if (!name)
+    return path_fold_stmt (r, rn, bb);
 
   if (get_global_ssa_range (r, name))
     return true;
index 1ae47d3a2b79c6a8fa6a6da64e7ddb3cc84b0f89..98fb5801376aeade4acbb8d3e802a6f980c7b9a3 100644 (file)
@@ -35,6 +35,9 @@ private:
   bool path_range_reverse (irange &r, tree name, const vec<basic_block> &);
   bool path_fold_stmt (irange &r, range_stmt &rn, basic_block bb,
                       edge e = NULL);
+  bool process_phi (irange &r, gphi *phi);
+  bool path_get_operand (irange &r, tree name, basic_block bb);
+
 public:
   enum path_range_direction { FORWARD, REVERSE };
   path_ranger ();
@@ -43,7 +46,11 @@ public:
   /* What is the known range of name from its DEF point to edge E.  */
   bool path_range_edge (irange& r, tree name, edge e);
   bool path_range_entry (irange& r, tree name, basic_block bb);
+  // Specifying NAME give the range of NAME before G is executed.
   bool path_range_stmt (irange& r, tree name, gimple *g);
+  // no NAME, give the range of the LHS of the statement.
+  bool path_range_stmt (irange& r, gimple *g);
+
   bool path_range (irange &r, tree name, const vec<basic_block> &bbs,
                   enum path_range_direction, edge start_edge = NULL);
   // Evaluate expression within a BB as much as possible.
index 91221ae5b0ef23746d7b7dad4b2f631ef33b482d..d1a72ecd38d1f1b817a0a643d9d89f3856c9451a 100644 (file)
@@ -152,6 +152,7 @@ DEFTIMEVAR (TV_TREE_CLEANUP_CFG          , "tree CFG cleanup")
 DEFTIMEVAR (TV_TREE_TAIL_MERGE       , "tree tail merge")
 DEFTIMEVAR (TV_TREE_VRP              , "tree VRP")
 DEFTIMEVAR (TV_TREE_EARLY_VRP        , "tree Early VRP")
+DEFTIMEVAR (TV_TREE_RANGER_VRP       , "tree Ranger VRP")
 DEFTIMEVAR (TV_TREE_COPY_PROP        , "tree copy propagation")
 DEFTIMEVAR (TV_FIND_REFERENCED_VARS  , "tree find ref. vars")
 DEFTIMEVAR (TV_TREE_PTA                     , "tree PTA")
index 93a6a99eb7a16a47a9bd2a534fc64103cc517127..2f06a83c7952a3a08507b84d78fa83bd596a2a48 100644 (file)
@@ -450,6 +450,7 @@ extern gimple_opt_pass *make_pass_check_data_deps (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_copy_prop (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_isolate_erroneous_paths (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_early_vrp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_ranger_vrp (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_vrp (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_uncprop (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_return_slot (gcc::context *ctxt);