aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Macleod <amacleod@gcc.gnu.org>2018-04-03 14:56:54 +0000
committerAndrew Macleod <amacleod@gcc.gnu.org>2018-04-03 14:56:54 +0000
commit55af7b3530fa80054640f71c0d122a9fed7fe47a (patch)
tree789ed72dd7bd0b21d9029cc7bd0045bfddf01bba
parent7ce6c8b321a7d6243a2bdecc4de7c64fca4f211a (diff)
Check in initial version of Early Ranger VRP
disable with -fno-rvrp From-SVN: r259033
-rw-r--r--gcc/common.opt5
-rw-r--r--gcc/gimple-ssa-evrp.c174
-rw-r--r--gcc/passes.c12
-rw-r--r--gcc/passes.def1
-rw-r--r--gcc/range-op.c16
-rw-r--r--gcc/ssa-range-global.c15
-rw-r--r--gcc/ssa-range-global.h1
-rw-r--r--gcc/ssa-range-stmt.c18
-rw-r--r--gcc/ssa-range.c189
-rw-r--r--gcc/ssa-range.h7
-rw-r--r--gcc/timevar.def1
-rw-r--r--gcc/tree-pass.h1
12 files changed, 386 insertions, 54 deletions
diff --git a/gcc/common.opt b/gcc/common.opt
index e0bc4d1bb18..c2a82aa83e3 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -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.
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index c9bbf09a406..11d53ce8e11 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -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);
+}
+
diff --git a/gcc/passes.c b/gcc/passes.c
index c09cd921306..6d26da6c848 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -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)
diff --git a/gcc/passes.def b/gcc/passes.def
index 3ebcfc30349..7f2b7ea76ed 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -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);
diff --git a/gcc/range-op.c b/gcc/range-op.c
index 61917274296..9837710db01 100644
--- a/gcc/range-op.c
+++ b/gcc/range-op.c
@@ -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);
}
diff --git a/gcc/ssa-range-global.c b/gcc/ssa-range-global.c
index d477be34b19..12a78f4c18b 100644
--- a/gcc/ssa-range-global.c
+++ b/gcc/ssa-range-global.c
@@ -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 ()
diff --git a/gcc/ssa-range-global.h b/gcc/ssa-range-global.h
index 95e94e39163..69accee2b83 100644
--- a/gcc/ssa-range-global.h
+++ b/gcc/ssa-range-global.h
@@ -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 */
diff --git a/gcc/ssa-range-stmt.c b/gcc/ssa-range-stmt.c
index 606b1af6569..181a4b560a1 100644
--- a/gcc/ssa-range-stmt.c
+++ b/gcc/ssa-range-stmt.c
@@ -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);
diff --git a/gcc/ssa-range.c b/gcc/ssa-range.c
index ceeb9cc903f..c185a9c51a6 100644
--- a/gcc/ssa-range.c
+++ b/gcc/ssa-range.c
@@ -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;
diff --git a/gcc/ssa-range.h b/gcc/ssa-range.h
index 1ae47d3a2b7..98fb5801376 100644
--- a/gcc/ssa-range.h
+++ b/gcc/ssa-range.h
@@ -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.
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 91221ae5b0e..d1a72ecd38d 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -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")
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 93a6a99eb7a..2f06a83c795 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -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);