From d73d443762e1741b810143b2333801cf952c8f17 Mon Sep 17 00:00:00 2001
From: Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
Date: Fri, 24 Jun 2016 14:45:24 +1000
Subject: [PATCH 4/6] Add early vrp
---
gcc/Makefile.in | 1 +
gcc/common.opt | 4 +
gcc/doc/invoke.texi | 9 +
gcc/passes.def | 1 +
gcc/testsuite/g++.dg/tree-ssa/pr31146-2.C | 2 +-
gcc/testsuite/gcc.dg/tree-ssa/evrp1.c | 13 ++
gcc/testsuite/gcc.dg/tree-ssa/evrp2.c | 18 ++
gcc/testsuite/gcc.dg/tree-ssa/evrp3.c | 15 ++
gcc/testsuite/gcc.dg/tree-ssa/pr20318.c | 4 +-
gcc/testsuite/gcc.dg/tree-ssa/pr22117.c | 4 +-
gcc/testsuite/gcc.dg/tree-ssa/pr25382.c | 4 +-
gcc/testsuite/gcc.dg/tree-ssa/pr68431.c | 4 +-
gcc/testsuite/gcc.dg/tree-ssa/vrp19.c | 6 +-
gcc/testsuite/gcc.dg/tree-ssa/vrp23.c | 4 +-
gcc/testsuite/gcc.dg/tree-ssa/vrp24.c | 5 +-
gcc/testsuite/gcc.dg/tree-ssa/vrp58.c | 4 +-
gcc/testsuite/gcc.dg/tree-ssa/vrp67.c | 4 +-
gcc/testsuite/gcc.dg/tree-ssa/vrp98.c | 6 +-
gcc/timevar.def | 1 +
gcc/tree-early-vrp.c | 324 ++++++++++++++++++++++++++++++
gcc/tree-pass.h | 1 +
21 files changed, 411 insertions(+), 23 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/evrp1.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/evrp2.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/evrp3.c
create mode 100644 gcc/tree-early-vrp.c
@@ -1528,6 +1528,7 @@ OBJS = \
tree-vect-loop-manip.o \
tree-vect-slp.o \
tree-vectorizer.o \
+ tree-early-vrp.o \
tree-vrp.o \
tree.o \
valtrack.o \
@@ -2471,6 +2471,10 @@ ftree-vrp
Common Report Var(flag_tree_vrp) Init(0) Optimization
Perform Value Range Propagation on trees.
+ftree-evrp
+Common Report Var(flag_tree_early_vrp) Init(1) Optimization
+Perform Early Value Range Propagation on trees.
+
fsplit-paths
Common Report Var(flag_split_paths) Init(0) Optimization
Split paths leading to loop backedges.
@@ -7665,6 +7665,10 @@ enabled by default at @option{-O2} and higher. Null pointer check
elimination is only done if @option{-fdelete-null-pointer-checks} is
enabled.
+@item -ftree-evrp
+@opindex ftree-evrp
+Perform Early Value Range Propagation on trees.
+
@item -fsplit-paths
@opindex fsplit-paths
Split paths leading to loop backedges. This can improve dead code
@@ -12270,6 +12274,11 @@ is made by appending @file{.slp} to the source file name.
Dump each function after Value Range Propagation (VRP). The file name
is made by appending @file{.vrp} to the source file name.
+@item early vrp
+@opindex fdump-tree-evrp
+Dump each function after Early Value Range Propagation (EVRP). The file name
+is made by appending @file{.evrp} to the source file name.
+
@item oaccdevlow
@opindex fdump-tree-oaccdevlow
Dump each function after applying device-specific OpenACC transformations.
@@ -102,6 +102,7 @@ along with GCC; see the file COPYING3. If not see
early optimizations again. It is thus good idea to do this
late. */
NEXT_PASS (pass_split_functions);
+ NEXT_PASS (pass_early_vrp);
POP_INSERT_PASSES ()
NEXT_PASS (pass_release_ssa_names);
NEXT_PASS (pass_rebuild_cgraph_edges);
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-forwprop1" } */
+/* { dg-options "-O -fno-tree-evrp -fdump-tree-forwprop1" } */
#include <new>
new file mode 100644
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int foo (int i);
+int bar (int j)
+{
+ if (j > 2)
+ return foo (j + 2);
+ else
+ return j;
+}
+
+/* { dg-final { scan-tree-dump "\\\[5, \\+INF" "evrp" } } */
new file mode 100644
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int foo (int i);
+int bar2 (int j)
+{
+ if (j > 2)
+ {
+ if (j < 7)
+ return foo (j + 1);
+ else
+ return foo (j + 2);
+ }
+ return j;
+}
+
+
+/* { dg-final { scan-tree-dump "\\\[4, 7\\\]" "evrp" } } */
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int foo (int i);
+void bar (int j)
+{
+ unsigned int i;
+ for (i = 0; i < 10; ++i)
+ {
+ bar (i + 1);
+ }
+}
+
+/* { dg-final { scan-tree-dump "\\\[1, 10\\\]" "evrp" } } */
+
@@ -1,5 +1,5 @@
/* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
-/* { dg-options "-O2 -fdump-tree-original -fdump-tree-vrp1 -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdump-tree-original -fdump-tree-evrp -fdelete-null-pointer-checks" } */
extern int* f(int) __attribute__((returns_nonnull));
extern void eliminate ();
@@ -14,4 +14,4 @@ void h () {
}
/* { dg-final { scan-tree-dump-times "== 0" 1 "original" } } */
-/* { dg-final { scan-tree-dump-times "Folding predicate\[^\\n\]*to 0" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate\[^\\n\]*to 0" 1 "evrp" } } */
@@ -3,7 +3,7 @@
known to be zero after entering the first two "if" statements. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
void link_error (void);
@@ -21,4 +21,4 @@ foo (int *p, int q)
}
}
-/* { dg-final { scan-tree-dump-times "Folding predicate r_.* != 0B to 0" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate r_.* != 0B to 0" 1 "evrp" } } */
@@ -3,7 +3,7 @@
Check that VRP now gets ranges from BIT_AND_EXPRs. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-evrp" } */
int
foo (int a)
@@ -15,4 +15,4 @@ foo (int a)
return 1;
}
-/* { dg-final { scan-tree-dump-times "Folding predicate b_.* > 300 to 0" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate b_.* > 300 to 0" 1 "evrp" } } */
@@ -1,5 +1,5 @@
/* PR tree-optimization/68431 */
-/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fdump-tree-evrp-details" } */
unsigned int x = 1;
int
@@ -13,4 +13,4 @@ main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "Folding predicate .*to 0" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate .*to 0" 1 "evrp" } } */
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-vrp1" } */
+/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-evrp" } */
#include <limits.h>
extern void abort ();
@@ -22,5 +22,5 @@ int g (int b) {
}
return 1;
}
-/* { dg-final { scan-tree-dump "Folding predicate a_. < 0 to 0" "vrp1" } } */
-/* { dg-final { scan-tree-dump "Folding predicate b_. >= 0 to 1" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Folding predicate a_. < 0 to 0" "evrp" } } */
+/* { dg-final { scan-tree-dump "Folding predicate b_. >= 0 to 1" "evrp" } } */
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fdump-tree-evrp-details" } */
void aa (void);
void aos (void);
@@ -45,5 +45,5 @@ L8:
/* The n_sets > 0 test can be simplified into n_sets == 1 since the
only way to reach the test is when n_sets <= 1, and the only value
which satisfies both conditions is n_sets == 1. */
-/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "evrp" } } */
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fdump-tree-evrp-details -fdump-tree-vrp1-details" } */
struct rtx_def;
@@ -91,5 +91,6 @@ L7:
The second n_sets > 0 test can also be simplified into n_sets == 1
as the only way to reach the tests is when n_sets <= 1 and the only
value which satisfies both conditions is n_sets == 1. */
-/* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "evrp" } } */
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+/* { dg-options "-O2 -fdump-tree-evrp-details" } */
long long
foo (long long a, signed char b, signed char c)
@@ -9,4 +9,4 @@ foo (long long a, signed char b, signed char c)
}
/* { dg-final { scan-tree-dump "Folded into" "vrp1" { target int32plus } } } */
-/* { dg-final { scan-tree-dump "Folding statement: _\[0-9\]\* = \\(long long int\\) bc_\[0-9\]\*;" "vrp1" { target int16 } } } */
+/* { dg-final { scan-tree-dump "Folding statement: _\[0-9\]\* = \\(long long int\\) bc_\[0-9\]\*;" "evrp" { target int16 } } } */
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
extern void link_error (void);
@@ -36,4 +36,4 @@ unsigned baz (unsigned i)
return i;
}
-/* { dg-final { scan-tree-dump-times "Folding predicate" 3 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate" 3 "evrp" } } */
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target int128 } */
-/* { dg-options "-Os -fdump-tree-vrp1-details" } */
+/* { dg-options "-Os -fdump-tree-evrp-details -fdump-tree-evrp-details" } */
#include <stdint.h>
#include <limits.h>
@@ -36,6 +36,6 @@ foo (bigger_than_word a, word b, uint8_t c)
return ret;
}
-/* { dg-final { scan-tree-dump "Folded into: if \\(_\[0-9\]+ == 1\\)" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Folded into: if \\(_\[0-9\]+ == 1\\)" "evrp" } } */
/* { dg-final { scan-tree-dump-not "Folded into: if \\(_\[0-9\]+ == 2\\)" "vrp1" } } */
-/* { dg-final { scan-tree-dump "Folded into: if \\(_\[0-9\]+ == 3\\)" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Folded into: if \\(_\[0-9\]+ == 3\\)" "evrp" } } */
@@ -147,6 +147,7 @@ DEFTIMEVAR (TV_TREE_CFG , "tree CFG construction")
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_COPY_PROP , "tree copy propagation")
DEFTIMEVAR (TV_FIND_REFERENCED_VARS , "tree find ref. vars")
DEFTIMEVAR (TV_TREE_PTA , "tree PTA")
new file mode 100644
@@ -0,0 +1,324 @@
+/* Early Value Range Propagation (VRP) Implementation.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "insn-codes.h"
+#include "rtl.h"
+#include "tree.h"
+#include "gimple.h"
+#include "cfghooks.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "optabs-tree.h"
+#include "gimple-pretty-print.h"
+#include "diagnostic-core.h"
+#include "flags.h"
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "cfganal.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+#include "tree-cfg.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
+#include "tree-ssa.h"
+#include "intl.h"
+#include "cfgloop.h"
+#include "tree-scalar-evolution.h"
+#include "tree-ssa-propagate.h"
+#include "tree-chrec.h"
+#include "tree-ssa-threadupdate.h"
+#include "tree-ssa-scopedtables.h"
+#include "tree-ssa-threadedge.h"
+#include "omp-low.h"
+#include "target.h"
+#include "case-cfn-macros.h"
+#include "domwalk.h"
+#include "tree-vrp.h"
+
+/* A simplified non-iterative version of visit_phi_node which discovers
+ value ranges for PHI definition. I.e. whenever there is a backedge
+ in the PHI set the PHI definition to VARYING. */
+
+static enum ssa_prop_result
+vrp_visit_phi_node_local (gphi *phi)
+{
+ size_t i;
+ tree lhs = PHI_RESULT (phi);
+ value_range vr_result = VR_INITIALIZER;
+ bool first = true;
+ int edges;
+
+ edges = 0;
+ for (i = 0; i < gimple_phi_num_args (phi); i++)
+ {
+ edge e = gimple_phi_arg_edge (phi, i);
+ tree arg = PHI_ARG_DEF (phi, i);
+ value_range vr_arg = VR_INITIALIZER;
+ ++edges;
+
+ /* If there is a back-edge, set the result to VARYING. */
+ if (e->flags & EDGE_DFS_BACK
+ || e->flags & EDGE_ABNORMAL)
+ {
+ set_value_range_to_varying (&vr_result);
+ break;
+ }
+
+ if (TREE_CODE (arg) == SSA_NAME)
+ vr_arg = *(get_value_range (arg));
+ else
+ set_value_range_to_varying (&vr_arg);
+
+ /* If any of the RHS value is VARYING, set the result to VARYING. */
+ if (vr_arg.type == VR_VARYING)
+ {
+ set_value_range_to_varying (&vr_result);
+ break;
+ }
+
+ /* Set/meet the RHS value range with the result so far. */
+ if (first)
+ set_value_range (&vr_result, vr_arg.type, vr_arg.min,
+ vr_arg.max, vr_arg.equiv);
+ else
+ vrp_meet (&vr_result, &vr_arg);
+ first = false;
+
+ if (vr_result.type == VR_VARYING)
+ break;
+ }
+
+ /* Check if the value range has changed and return accordingly. */
+ if (update_value_range (lhs, &vr_result))
+ {
+ if (vr_result.type == VR_VARYING)
+ {
+ set_value_range_to_varying (&vr_result);
+ return SSA_PROP_VARYING;
+ }
+ return SSA_PROP_INTERESTING;
+ }
+
+ return SSA_PROP_NOT_INTERESTING;
+}
+
+/* Visit the basic blocks in the dominance order and set the Value Ranges (VR) for
+ SSA_NAMEs in the scope. Use this VR to discover more VRs. Restore the old VR
+ once the scope is exited. */
+
+class evrp_dom_walker : public dom_walker
+{
+public:
+ evrp_dom_walker ()
+ : dom_walker (CDI_DOMINATORS), cond_stack (vNULL) {}
+
+ void finalize_dom_walker ();
+ virtual edge before_dom_children (basic_block);
+
+ /* Cond_stack holds the old VR. */
+ vec<std::pair <basic_block, std::pair <tree, value_range*> > > cond_stack;
+};
+
+edge evrp_dom_walker::before_dom_children (basic_block bb)
+{
+ /* If we are going out of scope, restore the old VR. */
+ while (!cond_stack.is_empty ()
+ && !dominated_by_p (CDI_DOMINATORS, bb, cond_stack.last ().first))
+ {
+ tree var = cond_stack.last ().second.first;
+ value_range *vr = cond_stack.last ().second.second;
+ value_range *vr_to_del = get_value_range (var);
+ XDELETE (vr_to_del);
+ change_value_range (var, vr);
+ cond_stack.pop ();
+ }
+
+ /* See if there is any new scope is entered with new VR and set that VR to
+ ssa_name before visiting the statements in the scope. */
+ if (single_pred_p (bb))
+ {
+ edge te = NULL, fe = NULL;
+ edge e = single_pred_edge (bb);
+ value_range vr = VR_INITIALIZER;
+ gimple *stmt = last_stmt (e->src);
+
+ if (stmt
+ && gimple_code (stmt) == GIMPLE_COND
+ && INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt))))
+ {
+ extract_true_false_edges_from_block (e->src,
+ &te, &fe);
+ tree op0 = gimple_cond_lhs (stmt);
+ tree op1 = gimple_cond_rhs (stmt);
+ tree_code code = gimple_cond_code (stmt);
+ value_range *old_vr = get_value_range (op0);
+
+ /* Discover VR when condition is true. */
+ if (te == e
+ && !TREE_OVERFLOW_P (op0)
+ && !TREE_OVERFLOW_P (op1))
+ {
+ tree cond = build2 (code, boolean_type_node, op0, op1);
+ tree a = build2 (ASSERT_EXPR, TREE_TYPE (op0), op0, cond);
+ extract_range_from_assert (&vr, a);
+ if (old_vr->type == VR_RANGE || old_vr->type == VR_ANTI_RANGE)
+ vrp_intersect_ranges (&vr, old_vr);
+ }
+ /* Discover VR when condition is false. */
+ else if (fe == e
+ && !TREE_OVERFLOW_P (op0)
+ && !TREE_OVERFLOW_P (op1))
+ {
+ tree_code code
+ = invert_tree_comparison (gimple_cond_code (stmt),
+ HONOR_NANS (op0));
+ tree cond = build2 (code, boolean_type_node, op0, op1);
+ tree a = build2 (ASSERT_EXPR, TREE_TYPE (op0), op0, cond);
+ extract_range_from_assert (&vr, a);
+ if (old_vr->type == VR_RANGE || old_vr->type == VR_ANTI_RANGE)
+ vrp_intersect_ranges (&vr, old_vr);
+ }
+
+ /* If we found any usable VR, set the VR to ssa_name and create a
+ restore point in the cond_stack with the old VR. */
+ if (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
+ {
+ value_range *new_vr = XCNEW (value_range);
+ *new_vr = vr;
+ cond_stack.safe_push (std::make_pair (bb,
+ std::make_pair (op0,
+ old_vr)));
+ change_value_range (op0, new_vr);
+ }
+ }
+ }
+
+ /* Visit stmts and discover any new VRs possible. */
+ gimple_stmt_iterator gsi;
+ for (gphi_iterator gpi = gsi_start_phis (bb);
+ !gsi_end_p (gpi); gsi_next (&gpi))
+ {
+ gphi *phi = gpi.phi ();
+ if (stmt_interesting_for_vrp (phi))
+ vrp_visit_phi_node_local (phi);
+ }
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ edge taken_edge_p;
+ tree output_p;
+ if (stmt_interesting_for_vrp (stmt))
+ vrp_visit_stmt (stmt, &taken_edge_p, &output_p);
+ }
+
+ return NULL;
+}
+
+
+/* Restore the old VRs maintained in the cond_stack. */
+void evrp_dom_walker::finalize_dom_walker ()
+{
+ while (!cond_stack.is_empty ())
+ {
+ tree var = cond_stack.last ().second.first;
+ value_range *vr_to_del = get_value_range (var);
+ XDELETE (vr_to_del);
+ value_range *vr = cond_stack.last ().second.second;
+ change_value_range (var, vr);
+ cond_stack.pop ();
+ }
+}
+
+static unsigned int
+execute_early_vrp ()
+{
+ basic_block bb;
+ edge e;
+ edge_iterator ei;
+
+ loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
+ rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
+ scev_initialize ();
+ calculate_dominance_info (CDI_DOMINATORS);
+ vrp_initialize ();
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ e->flags |= EDGE_EXECUTABLE;
+ }
+
+ evrp_dom_walker walker;
+ walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ walker.finalize_dom_walker ();
+
+ vrp_finalize (false, false);
+ free_numbers_of_iterations_estimates (cfun);
+
+ scev_finalize ();
+ loop_optimizer_finalize ();
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_early_vrp =
+{
+ GIMPLE_PASS, /* type */
+ "evrp", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_TREE_EARLY_VRP, /* tv_id */
+ PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all),
+};
+
+class pass_early_vrp : public gimple_opt_pass
+{
+public:
+ pass_early_vrp (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_early_vrp, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_early_vrp (m_ctxt); }
+ virtual bool gate (function *) { return flag_tree_early_vrp != 0; }
+ virtual unsigned int execute (function *)
+ { return execute_early_vrp (); }
+
+}; // class pass_vrp
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_early_vrp (gcc::context *ctxt)
+{
+ return new pass_early_vrp (ctxt);
+}
@@ -440,6 +440,7 @@ extern gimple_opt_pass *make_pass_fre (gcc::context *ctxt);
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_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);
--
1.9.1