#include "gimple-range.h"
#include "fold-const.h"
#include "value-pointer-equiv.h"
+#include "tree-vrp.h"
// This is the classic EVRP folder which uses a dominator walk and pushes
// ranges into the next block if it is a single predecessor block.
simplify_using_ranges simplifier;
};
-// This is a ranger based folder which continues to use the dominator
-// walk to access the substitute and fold machinery. Ranges are calculated
-// on demand.
-
-class rvrp_folder : public substitute_and_fold_engine
-{
-public:
-
- rvrp_folder () : substitute_and_fold_engine (), m_simplifier ()
- {
- m_ranger = enable_ranger (cfun);
- m_simplifier.set_range_query (m_ranger, m_ranger->non_executable_edge_flag);
- m_pta = new pointer_equiv_analyzer (m_ranger);
- }
-
- ~rvrp_folder ()
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- m_ranger->dump (dump_file);
-
- m_ranger->export_global_ranges ();
- disable_ranger (cfun);
- delete m_pta;
- }
-
- tree value_of_expr (tree name, gimple *s = NULL) OVERRIDE
- {
- // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
- if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
- return NULL;
- tree ret = m_ranger->value_of_expr (name, s);
- if (!ret && supported_pointer_equiv_p (name))
- ret = m_pta->get_equiv (name);
- return ret;
- }
-
- tree value_on_edge (edge e, tree name) OVERRIDE
- {
- // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
- if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
- return NULL;
- tree ret = m_ranger->value_on_edge (e, name);
- if (!ret && supported_pointer_equiv_p (name))
- ret = m_pta->get_equiv (name);
- return ret;
- }
-
- tree value_of_stmt (gimple *s, tree name = NULL) OVERRIDE
- {
- // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
- if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
- return NULL;
- return m_ranger->value_of_stmt (s, name);
- }
-
- void pre_fold_bb (basic_block bb) OVERRIDE
- {
- m_pta->enter (bb);
- }
-
- void post_fold_bb (basic_block bb) OVERRIDE
- {
- m_pta->leave (bb);
- }
-
- void pre_fold_stmt (gimple *stmt) OVERRIDE
- {
- m_pta->visit_stmt (stmt);
- }
-
- bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
- {
- return m_simplifier.simplify (gsi);
- }
-
-private:
- DISABLE_COPY_AND_ASSIGN (rvrp_folder);
- gimple_ranger *m_ranger;
- simplify_using_ranges m_simplifier;
- pointer_equiv_analyzer *m_pta;
-};
-
// In a hybrid folder, start with an EVRP folder, and add the required
// fold_stmt bits to either try the ranger first or second.
//
static unsigned int
execute_early_vrp ()
{
+ if ((param_evrp_mode & EVRP_MODE_RVRP_FIRST) == EVRP_MODE_RVRP_ONLY)
+ return execute_ranger_vrp (cfun, false);
+
/* Ideally this setup code would move into the ctor for the folder
However, this setup can change the number of blocks which
invalidates the internal arrays that are set up by the dominator
folder.substitute_and_fold ();
break;
}
- case EVRP_MODE_RVRP_ONLY:
- {
- rvrp_folder folder;
- folder.substitute_and_fold ();
- break;
- }
case EVRP_MODE_EVRP_FIRST:
{
hybrid_folder folder (true);
#include "gimple-array-bounds.h"
#include "gimple-range.h"
#include "gimple-range-path.h"
+#include "value-pointer-equiv.h"
/* Set of SSA names found live during the RPO traversal of the function
for still active basic-blocks. */
return 0;
}
+// This is a ranger based folder which continues to use the dominator
+// walk to access the substitute and fold machinery. Ranges are calculated
+// on demand.
+
+class rvrp_folder : public substitute_and_fold_engine
+{
+public:
+
+ rvrp_folder (gimple_ranger *r) : substitute_and_fold_engine (),
+ m_simplifier (r, r->non_executable_edge_flag)
+ {
+ m_ranger = r;
+ m_pta = new pointer_equiv_analyzer (m_ranger);
+ }
+
+ ~rvrp_folder ()
+ {
+ delete m_pta;
+ }
+
+ tree value_of_expr (tree name, gimple *s = NULL) OVERRIDE
+ {
+ // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
+ if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+ return NULL;
+ tree ret = m_ranger->value_of_expr (name, s);
+ if (!ret && supported_pointer_equiv_p (name))
+ ret = m_pta->get_equiv (name);
+ return ret;
+ }
+
+ tree value_on_edge (edge e, tree name) OVERRIDE
+ {
+ // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
+ if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+ return NULL;
+ tree ret = m_ranger->value_on_edge (e, name);
+ if (!ret && supported_pointer_equiv_p (name))
+ ret = m_pta->get_equiv (name);
+ return ret;
+ }
+
+ tree value_of_stmt (gimple *s, tree name = NULL) OVERRIDE
+ {
+ // Shortcircuit subst_and_fold callbacks for abnormal ssa_names.
+ if (TREE_CODE (name) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+ return NULL;
+ return m_ranger->value_of_stmt (s, name);
+ }
+
+ void pre_fold_bb (basic_block bb) OVERRIDE
+ {
+ m_pta->enter (bb);
+ }
+
+ void post_fold_bb (basic_block bb) OVERRIDE
+ {
+ m_pta->leave (bb);
+ }
+
+ void pre_fold_stmt (gimple *stmt) OVERRIDE
+ {
+ m_pta->visit_stmt (stmt);
+ }
+
+ bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
+ {
+ return m_simplifier.simplify (gsi);
+ }
+
+private:
+ DISABLE_COPY_AND_ASSIGN (rvrp_folder);
+ gimple_ranger *m_ranger;
+ simplify_using_ranges m_simplifier;
+ pointer_equiv_analyzer *m_pta;
+};
+
+/* Main entry point for a VRP pass using just ranger. This can be called
+ from anywhere to perform a VRP pass, including from EVRP. */
+
+unsigned int
+execute_ranger_vrp (struct function *fun, bool warn_array_bounds_p)
+{
+ 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);
+
+ gimple_ranger *ranger = enable_ranger (fun);
+ rvrp_folder folder (ranger);
+ folder.substitute_and_fold ();
+ ranger->export_global_ranges ();
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ ranger->dump (dump_file);
+
+
+ if (warn_array_bounds && warn_array_bounds_p)
+ {
+ // Set all edges as executable, except those ranger says aren't.
+ int non_exec_flag = ranger->non_executable_edge_flag;
+ basic_block bb;
+ FOR_ALL_BB_FN (bb, fun)
+ {
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->flags & non_exec_flag)
+ e->flags &= ~EDGE_EXECUTABLE;
+ else
+ e->flags |= EDGE_EXECUTABLE;
+ }
+ array_bounds_checker array_checker (fun, ranger);
+ array_checker.check ();
+ }
+
+ disable_ranger (fun);
+ scev_finalize ();
+ loop_optimizer_finalize ();
+ return 0;
+}
+
namespace {
const pass_data pass_data_vrp =