diff options
Diffstat (limited to 'gcc/tree-vrp.cc')
-rw-r--r-- | gcc/tree-vrp.cc | 148 |
1 files changed, 134 insertions, 14 deletions
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index d7b194f..19d8f99 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -1092,6 +1092,106 @@ execute_ranger_vrp (struct function *fun, bool warn_array_bounds_p, return 0; } +// Implement a Fast VRP folder. Not quite as effective but faster. + +class fvrp_folder : public substitute_and_fold_engine +{ +public: + fvrp_folder (dom_ranger *dr) : substitute_and_fold_engine (), + m_simplifier (dr) + { m_dom_ranger = dr; } + + ~fvrp_folder () { } + + 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; + return m_dom_ranger->value_of_expr (name, s); + } + + 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; + return m_dom_ranger->value_on_edge (e, name); + } + + 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_dom_ranger->value_of_stmt (s, name); + } + + void pre_fold_bb (basic_block bb) override + { + m_dom_ranger->pre_bb (bb); + // Now process the PHIs in advance. + gphi_iterator psi = gsi_start_phis (bb); + for ( ; !gsi_end_p (psi); gsi_next (&psi)) + { + tree name = gimple_range_ssa_p (PHI_RESULT (psi.phi ())); + if (name) + { + Value_Range vr(TREE_TYPE (name)); + m_dom_ranger->range_of_stmt (vr, psi.phi (), name); + } + } + } + + void post_fold_bb (basic_block bb) override + { + m_dom_ranger->post_bb (bb); + } + + void pre_fold_stmt (gimple *s) override + { + // Ensure range_of_stmt has been called. + tree type = gimple_range_type (s); + if (type) + { + Value_Range vr(type); + m_dom_ranger->range_of_stmt (vr, s); + } + } + + bool fold_stmt (gimple_stmt_iterator *gsi) override + { + bool ret = m_simplifier.simplify (gsi); + if (!ret) + ret = ::fold_stmt (gsi, follow_single_use_edges); + return ret; + } + +private: + DISABLE_COPY_AND_ASSIGN (fvrp_folder); + simplify_using_ranges m_simplifier; + dom_ranger *m_dom_ranger; +}; + + +// Main entry point for a FAST VRP pass using a dom ranger. + +unsigned int +execute_fast_vrp (struct function *fun) +{ + calculate_dominance_info (CDI_DOMINATORS); + dom_ranger dr; + fvrp_folder folder (&dr); + + gcc_checking_assert (!fun->x_range_query); + fun->x_range_query = &dr; + + folder.substitute_and_fold (); + + fun->x_range_query = NULL; + return 0; +} + namespace { const pass_data pass_data_vrp = @@ -1120,36 +1220,50 @@ const pass_data pass_data_early_vrp = ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ), }; -static int vrp_pass_num = 0; +const pass_data pass_data_fast_vrp = +{ + GIMPLE_PASS, /* type */ + "fvrp", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_TREE_FAST_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_vrp : public gimple_opt_pass { public: - pass_vrp (gcc::context *ctxt, const pass_data &data_) - : gimple_opt_pass (data_, ctxt), data (data_), warn_array_bounds_p (false), - my_pass (vrp_pass_num++) - {} + pass_vrp (gcc::context *ctxt, const pass_data &data_, bool warn_p) + : gimple_opt_pass (data_, ctxt), data (data_), + warn_array_bounds_p (warn_p), final_p (false) + { } /* opt_pass methods: */ - opt_pass * clone () final override { return new pass_vrp (m_ctxt, data); } + opt_pass * clone () final override + { return new pass_vrp (m_ctxt, data, false); } void set_pass_param (unsigned int n, bool param) final override { gcc_assert (n == 0); - warn_array_bounds_p = param; + final_p = param; } bool gate (function *) final override { return flag_tree_vrp != 0; } unsigned int execute (function *fun) final override { - // Early VRP pass. - if (my_pass == 0) - return execute_ranger_vrp (fun, /*warn_array_bounds_p=*/false, false); + // Check for fast vrp. + if (&data == &pass_data_fast_vrp) + return execute_fast_vrp (fun); - return execute_ranger_vrp (fun, warn_array_bounds_p, my_pass == 2); + return execute_ranger_vrp (fun, warn_array_bounds_p, final_p); } private: const pass_data &data; bool warn_array_bounds_p; - int my_pass; + bool final_p; }; // class pass_vrp const pass_data pass_data_assumptions = @@ -1219,13 +1333,19 @@ public: gimple_opt_pass * make_pass_vrp (gcc::context *ctxt) { - return new pass_vrp (ctxt, pass_data_vrp); + return new pass_vrp (ctxt, pass_data_vrp, true); } gimple_opt_pass * make_pass_early_vrp (gcc::context *ctxt) { - return new pass_vrp (ctxt, pass_data_early_vrp); + return new pass_vrp (ctxt, pass_data_early_vrp, false); +} + +gimple_opt_pass * +make_pass_fast_vrp (gcc::context *ctxt) +{ + return new pass_vrp (ctxt, pass_data_fast_vrp, false); } gimple_opt_pass * |