diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2020-11-21 18:26:21 +0100 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2021-04-30 18:17:17 +0200 |
commit | d8ea47033a726c9b3455ead98b6ddce2403ec6d9 (patch) | |
tree | c9a74b07b091406b717571a92bbbc06ae7599584 /gcc/tree-vrp.c | |
parent | 71834be5b68e0c9839f0647e1bbf1eec4e4bbf49 (diff) | |
download | gcc-d8ea47033a726c9b3455ead98b6ddce2403ec6d9.zip gcc-d8ea47033a726c9b3455ead98b6ddce2403ec6d9.tar.gz gcc-d8ea47033a726c9b3455ead98b6ddce2403ec6d9.tar.bz2 |
Jump threader refactor.
This is an overall refactor of the jump threader, both for the low level
bits in tree-ssa-threadupdate.* and the high level bits in
tree-ssa-threadedge.*.
There should be no functional changes.
Some of the benefits of the refactor are:
a) Eliminates some icky global state (for example the x_vr_values hack).
b) Provides some semblance of an API for the threader.
c) Makes it clearer to see what parts are from the high level
threader, and what parts belong in the low level path registry and
BB threading mechanism.
d) Avoids passing a ton of variables around.
e) Provides for easier sharing with the backward threader.
f) Merged simplify stmt code in VRP and DOM as they were nearly
identical.
This has been bootstrapped and regression tested on x86-64 Linux.
Jeff had also been testing this path as part of his Fedora throughout the
off-season.
gcc/ChangeLog:
* tree-ssa-dom.c (class dom_jump_threader_simplifier): New.
(class dom_opt_dom_walker): Initialize some class variables.
(pass_dominator::execute): Pass evrp_range_analyzer and
dom_jump_threader_simplifier to dom_opt_dom_walker.
Adjust for some functions moving into classes.
(simplify_stmt_for_jump_threading): Adjust and move to...
(jump_threader_simplifier::simplify): ...here.
(dom_opt_dom_walker::before_dom_children): Adjust for
m_evrp_range_analyzer.
(dom_opt_dom_walker::after_dom_children): Remove x_vr_values hack.
(test_for_singularity): Place in dom_opt_dom_walker class.
(dom_opt_dom_walker::optimize_stmt): The argument
evrp_range_analyzer is now a class field.
* tree-ssa-threadbackward.c (class thread_jumps): Add m_registry.
(thread_jumps::thread_through_all_blocks): New.
(thread_jumps::convert_and_register_current_path): Use m_registry.
(pass_thread_jumps::execute): Adjust for thread_through_all_blocks
being in the threader class.
(pass_early_thread_jumps::execute): Same.
* tree-ssa-threadedge.c (threadedge_initialize_values): Move...
(jump_threader::jump_threader): ...here.
(threadedge_finalize_values): Move...
(jump_threader::~jump_threader): ...here.
(jump_threader::remove_jump_threads_including): New.
(jump_threader::thread_through_all_blocks): New.
(record_temporary_equivalences_from_phis): Move...
(jump_threader::record_temporary_equivalences_from_phis): ...here.
(record_temporary_equivalences_from_stmts_at_dest): Move...
(jump_threader::record_temporary_equivalences_from_stmts_at_dest):
Here...
(simplify_control_stmt_condition_1): Move to jump_threader class.
(simplify_control_stmt_condition): Move...
(jump_threader::simplify_control_stmt_condition): ...here.
(thread_around_empty_blocks): Move...
(jump_threader::thread_around_empty_blocks): ...here.
(thread_through_normal_block): Move...
(jump_threader::thread_through_normal_block): ...here.
(thread_across_edge): Move...
(jump_threader::thread_across_edge): ...here.
(thread_outgoing_edges): Move...
(jump_threader::thread_outgoing_edges): ...here.
* tree-ssa-threadedge.h: Move externally facing functings...
(class jump_threader): ...here...
(class jump_threader_simplifier): ...and here.
* tree-ssa-threadupdate.c (struct redirection_data): Remove comment.
(jump_thread_path_allocator::jump_thread_path_allocator): New.
(jump_thread_path_allocator::~jump_thread_path_allocator): New.
(jump_thread_path_allocator::allocate_thread_edge): New.
(jump_thread_path_allocator::allocate_thread_path): New.
(jump_thread_path_registry::jump_thread_path_registry): New.
(jump_thread_path_registry::~jump_thread_path_registry): New.
(jump_thread_path_registry::allocate_thread_edge): New.
(jump_thread_path_registry::allocate_thread_path): New.
(dump_jump_thread_path): Make extern.
(debug (const vec<jump_thread_edge *> &path)): New.
(struct removed_edges): Move to tree-ssa-threadupdate.h.
(struct thread_stats_d): Remove.
(remove_ctrl_stmt_and_useless_edges): Make static.
(lookup_redirection_data): Move...
(jump_thread_path_registry::lookup_redirection_data): ...here.
(ssa_redirect_edges): Make static.
(thread_block_1): Move...
(jump_thread_path_registry::thread_block_1): ...here.
(thread_block): Move...
(jump_thread_path_registry::thread_block): ...here.
(thread_through_loop_header): Move...
(jump_thread_path_registry::thread_through_loop_header): ...here.
(mark_threaded_blocks): Move...
(jump_thread_path_registry::mark_threaded_blocks): ...here.
(debug_path): Move...
(jump_thread_path_registry::debug_path): ...here.
(debug_all_paths): Move...
(jump_thread_path_registry::dump): ..here.
(rewire_first_differing_edge): Move...
(jump_thread_path_registry::rewire_first_differing_edge): ...here.
(adjust_paths_after_duplication): Move...
(jump_thread_path_registry::adjust_paths_after_duplication): ...here.
(duplicate_thread_path): Move...
(jump_thread_path_registry::duplicate_thread_path): ..here.
(remove_jump_threads_including): Move...
(jump_thread_path_registry::remove_jump_threads_including): ...here.
(thread_through_all_blocks): Move to...
(jump_thread_path_registry::thread_through_all_blocks): ...here.
(delete_jump_thread_path): Remove.
(register_jump_thread): Move...
(jump_thread_path_registry::register_jump_thread): ...here.
* tree-ssa-threadupdate.h: Move externally facing functions...
(class jump_thread_path_allocator): ...here...
(class jump_thread_path_registry): ...and here.
(thread_through_all_blocks): Remove.
(struct removed_edges): New.
(register_jump_thread): Remove.
(remove_jump_threads_including): Remove.
(delete_jump_thread_path): Remove.
(remove_ctrl_stmt_and_useless_edges): Remove.
(free_dom_edge_info): New prototype.
* tree-vrp.c: Remove x_vr_values hack.
(class vrp_jump_threader_simplifier): New.
(vrp_jump_threader_simplifier::simplify): New.
(vrp_jump_threader::vrp_jump_threader): Adjust method signature.
Remove m_dummy_cond.
Instantiate m_simplifier and m_threader.
(vrp_jump_threader::thread_through_all_blocks): New.
(vrp_jump_threader::simplify_stmt): Remove.
(vrp_jump_threader::after_dom_children): Do not set m_dummy_cond.
Remove x_vr_values hack.
(execute_vrp): Adjust for thread_through_all_blocks being in a
class.
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 157 |
1 files changed, 66 insertions, 91 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index d968ef2..12e6e6f 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2373,9 +2373,6 @@ lhs_of_dominating_assert (tree op, basic_block bb, gimple *stmt) return op; } -/* A hack. */ -static class vr_values *x_vr_values; - /* Searches the case label vector VEC for the index *IDX of the CASE_LABEL that includes the value VAL. The search is restricted to the range [START_IDX, n - 1] where n is the size of VEC. @@ -4163,6 +4160,54 @@ vrp_folder::fold_stmt (gimple_stmt_iterator *si) return simplifier.simplify (si); } +class vrp_jump_threader_simplifier : public jump_threader_simplifier +{ +public: + vrp_jump_threader_simplifier (vr_values *v, avail_exprs_stack *avails) + : jump_threader_simplifier (v, avails) {} + +private: + tree simplify (gimple *, gimple *, basic_block) OVERRIDE; +}; + +tree +vrp_jump_threader_simplifier::simplify (gimple *stmt, + gimple *within_stmt, + basic_block bb) +{ + /* First see if the conditional is in the hash table. */ + tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt, false, true); + if (cached_lhs && is_gimple_min_invariant (cached_lhs)) + return cached_lhs; + + if (gcond *cond_stmt = dyn_cast <gcond *> (stmt)) + { + tree op0 = gimple_cond_lhs (cond_stmt); + op0 = lhs_of_dominating_assert (op0, bb, stmt); + + tree op1 = gimple_cond_rhs (cond_stmt); + op1 = lhs_of_dominating_assert (op1, bb, stmt); + + simplify_using_ranges simplifier (m_vr_values); + return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt), + op0, op1, within_stmt); + } + + if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt)) + { + tree op = gimple_switch_index (switch_stmt); + if (TREE_CODE (op) != SSA_NAME) + return NULL_TREE; + + op = lhs_of_dominating_assert (op, bb, stmt); + + const value_range_equiv *vr = m_vr_values->get_value_range (op); + return find_case_label_range (switch_stmt, vr); + } + + return jump_threader_simplifier::simplify (stmt, within_stmt, bb); +} + /* Blocks which have more than one predecessor and more than one successor present jump threading opportunities, i.e., when the block is reached from a specific predecessor, we @@ -4186,7 +4231,7 @@ vrp_folder::fold_stmt (gimple_stmt_iterator *si) class vrp_jump_threader : public dom_walker { public: - vrp_jump_threader (struct function *, vr_values *); + vrp_jump_threader (function *, vr_values *); ~vrp_jump_threader (); void thread_jumps () @@ -4194,9 +4239,13 @@ public: walk (m_fun->cfg->x_entry_block_ptr); } + void thread_through_all_blocks () + { + // FIXME: Put this in the destructor? + m_threader->thread_through_all_blocks (false); + } + private: - static tree simplify_stmt (gimple *stmt, gimple *within_stmt, - avail_exprs_stack *, basic_block); virtual edge before_dom_children (basic_block); virtual void after_dom_children (basic_block); @@ -4205,7 +4254,8 @@ private: const_and_copies *m_const_and_copies; avail_exprs_stack *m_avail_exprs_stack; hash_table<expr_elt_hasher> *m_avail_exprs; - gcond *m_dummy_cond; + vrp_jump_threader_simplifier *m_simplifier; + jump_threader *m_threader; }; vrp_jump_threader::vrp_jump_threader (struct function *fun, vr_values *v) @@ -4227,11 +4277,15 @@ vrp_jump_threader::vrp_jump_threader (struct function *fun, vr_values *v) that might be recorded. */ m_const_and_copies = new const_and_copies (); - m_dummy_cond = NULL; m_fun = fun; m_vr_values = v; m_avail_exprs = new hash_table<expr_elt_hasher> (1024); m_avail_exprs_stack = new avail_exprs_stack (m_avail_exprs); + + m_simplifier = new vrp_jump_threader_simplifier (m_vr_values, + m_avail_exprs_stack); + m_threader = new jump_threader (m_const_and_copies, m_avail_exprs_stack, + m_simplifier); } vrp_jump_threader::~vrp_jump_threader () @@ -4242,6 +4296,8 @@ vrp_jump_threader::~vrp_jump_threader () delete m_const_and_copies; delete m_avail_exprs; delete m_avail_exprs_stack; + delete m_simplifier; + delete m_threader; } /* Called before processing dominator children of BB. We want to look @@ -4284,89 +4340,12 @@ vrp_jump_threader::before_dom_children (basic_block bb) return NULL; } -/* A trivial wrapper so that we can present the generic jump threading - code with a simple API for simplifying statements. STMT is the - statement we want to simplify, WITHIN_STMT provides the location - for any overflow warnings. - - ?? This should be cleaned up. There's a virtually identical copy - of this function in tree-ssa-dom.c. */ - -tree -vrp_jump_threader::simplify_stmt (gimple *stmt, - gimple *within_stmt, - avail_exprs_stack *avail_exprs_stack, - basic_block bb) -{ - /* First see if the conditional is in the hash table. */ - tree cached_lhs = avail_exprs_stack->lookup_avail_expr (stmt, false, true); - if (cached_lhs && is_gimple_min_invariant (cached_lhs)) - return cached_lhs; - - class vr_values *vr_values = x_vr_values; - if (gcond *cond_stmt = dyn_cast <gcond *> (stmt)) - { - tree op0 = gimple_cond_lhs (cond_stmt); - op0 = lhs_of_dominating_assert (op0, bb, stmt); - - tree op1 = gimple_cond_rhs (cond_stmt); - op1 = lhs_of_dominating_assert (op1, bb, stmt); - - simplify_using_ranges simplifier (vr_values); - return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt), - op0, op1, within_stmt); - } - - if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt)) - { - tree op = gimple_switch_index (switch_stmt); - if (TREE_CODE (op) != SSA_NAME) - return NULL_TREE; - - op = lhs_of_dominating_assert (op, bb, stmt); - - const value_range_equiv *vr = vr_values->get_value_range (op); - return find_case_label_range (switch_stmt, vr); - } - - if (gassign *assign_stmt = dyn_cast <gassign *> (stmt)) - { - tree lhs = gimple_assign_lhs (assign_stmt); - if (TREE_CODE (lhs) == SSA_NAME - && (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) - || POINTER_TYPE_P (TREE_TYPE (lhs))) - && stmt_interesting_for_vrp (stmt)) - { - edge dummy_e; - tree dummy_tree; - value_range_equiv new_vr; - vr_values->extract_range_from_stmt (stmt, &dummy_e, - &dummy_tree, &new_vr); - tree singleton; - if (new_vr.singleton_p (&singleton)) - return singleton; - } - } - - return NULL_TREE; -} - /* Called after processing dominator children of BB. This is where we actually call into the threader. */ void vrp_jump_threader::after_dom_children (basic_block bb) { - if (!m_dummy_cond) - m_dummy_cond = gimple_build_cond (NE_EXPR, - integer_zero_node, integer_zero_node, - NULL, NULL); - - x_vr_values = m_vr_values; - thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies, - m_avail_exprs_stack, NULL, - simplify_stmt); - x_vr_values = NULL; - + m_threader->thread_outgoing_edges (bb); m_avail_exprs_stack->pop_to_marker (); m_const_and_copies->pop_to_marker (); } @@ -4500,8 +4479,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p) vrp_asserts assert_engine (fun); assert_engine.insert_range_assertions (); - threadedge_initialize_values (); - /* For visiting PHI nodes we need EDGE_DFS_BACK computed. */ mark_dfs_back_edges (); @@ -4577,9 +4554,7 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p) Note the SSA graph update will occur during the normal TODO processing by the pass manager. */ - thread_through_all_blocks (false); - - threadedge_finalize_values (); + threader.thread_through_all_blocks (); scev_finalize (); loop_optimizer_finalize (); |