diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
commit | e252b51ccde010cbd2a146485d8045103cd99533 (patch) | |
tree | e060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/tree-ssa-dom.c | |
parent | f10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff) | |
parent | 104c05c5284b7822d770ee51a7d91946c7e56d50 (diff) | |
download | gcc-e252b51ccde010cbd2a146485d8045103cd99533.zip gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2 |
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/tree-ssa-dom.c')
-rw-r--r-- | gcc/tree-ssa-dom.c | 257 |
1 files changed, 143 insertions, 114 deletions
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 81abf35..49d8f96 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -585,19 +585,52 @@ record_edge_info (basic_block bb) } } +class dom_jump_threader_simplifier : public jump_threader_simplifier +{ +public: + dom_jump_threader_simplifier (vr_values *v, + avail_exprs_stack *avails) + : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { } + +private: + tree simplify (gimple *, gimple *, basic_block, jt_state *) override; + avail_exprs_stack *m_avail_exprs_stack; +}; + +tree +dom_jump_threader_simplifier::simplify (gimple *stmt, + gimple *within_stmt, + basic_block bb, + jt_state *state) +{ + /* 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) + return cached_lhs; + + return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state); +} class dom_opt_dom_walker : public dom_walker { public: dom_opt_dom_walker (cdi_direction direction, - class const_and_copies *const_and_copies, - class avail_exprs_stack *avail_exprs_stack, - gcond *dummy_cond) - : dom_walker (direction, REACHABLE_BLOCKS), - m_const_and_copies (const_and_copies), - m_avail_exprs_stack (avail_exprs_stack), - evrp_range_analyzer (true), - m_dummy_cond (dummy_cond) { } + jump_threader *threader, + jt_state *state, + evrp_range_analyzer *analyzer, + const_and_copies *const_and_copies, + avail_exprs_stack *avail_exprs_stack) + : dom_walker (direction, REACHABLE_BLOCKS) + { + m_evrp_range_analyzer = analyzer; + m_state = state; + m_dummy_cond = gimple_build_cond (NE_EXPR, integer_zero_node, + integer_zero_node, NULL, NULL); + m_const_and_copies = const_and_copies; + m_avail_exprs_stack = avail_exprs_stack; + m_threader = threader; + } virtual edge before_dom_children (basic_block); virtual void after_dom_children (basic_block); @@ -608,9 +641,6 @@ private: class const_and_copies *m_const_and_copies; class avail_exprs_stack *m_avail_exprs_stack; - /* VRP data. */ - class evrp_range_analyzer evrp_range_analyzer; - /* Dummy condition to avoid creating lots of throw away statements. */ gcond *m_dummy_cond; @@ -619,6 +649,13 @@ private: the statement is a conditional with a statically determined value. */ edge optimize_stmt (basic_block, gimple_stmt_iterator *, bool *); + + + void test_for_singularity (gimple *, avail_exprs_stack *); + + jump_threader *m_threader; + evrp_range_analyzer *m_evrp_range_analyzer; + jt_state *m_state; }; /* Jump threading, redundancy elimination and const/copy propagation. @@ -695,10 +732,8 @@ pass_dominator::execute (function *fun) gcc.dg/tree-ssa/pr21417.c can't be threaded if loop preheader is missing. We should improve jump threading in future then LOOPS_HAVE_PREHEADERS won't be needed here. */ - loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES); - - /* Initialize the value-handle array. */ - threadedge_initialize_values (); + loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES + | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS); /* We need accurate information regarding back edges in the CFG for jump threading; this may include back edges that are not part of @@ -715,12 +750,17 @@ pass_dominator::execute (function *fun) FOR_EACH_BB_FN (bb, fun) record_edge_info (bb); - gcond *dummy_cond = gimple_build_cond (NE_EXPR, integer_zero_node, - integer_zero_node, NULL, NULL); - /* Recursively walk the dominator tree optimizing statements. */ - dom_opt_dom_walker walker (CDI_DOMINATORS, const_and_copies, - avail_exprs_stack, dummy_cond); + evrp_range_analyzer analyzer (true); + dom_jump_threader_simplifier simplifier (&analyzer, avail_exprs_stack); + jt_state state (const_and_copies, avail_exprs_stack, &analyzer); + jump_threader threader (&simplifier, &state); + dom_opt_dom_walker walker (CDI_DOMINATORS, + &threader, + &state, + &analyzer, + const_and_copies, + avail_exprs_stack); walker.walk (fun->cfg->x_entry_block_ptr); /* Look for blocks where we cleared EDGE_EXECUTABLE on an outgoing @@ -749,7 +789,7 @@ pass_dominator::execute (function *fun) containing any edge leaving BB. */ if (found) FOR_EACH_EDGE (e, ei, bb->succs) - remove_jump_threads_including (e); + threader.remove_jump_threads_including (e); } } @@ -773,7 +813,7 @@ pass_dominator::execute (function *fun) free_all_edge_infos (); /* Thread jumps, creating duplicate blocks as needed. */ - cfg_altered |= thread_through_all_blocks (may_peel_loop_headers_p); + cfg_altered |= threader.thread_through_all_blocks (may_peel_loop_headers_p); if (cfg_altered) free_dominance_info (CDI_DOMINATORS); @@ -849,9 +889,6 @@ pass_dominator::execute (function *fun) delete avail_exprs_stack; delete const_and_copies; - /* Free the value-handle array. */ - threadedge_finalize_values (); - return 0; } @@ -863,72 +900,6 @@ make_pass_dominator (gcc::context *ctxt) return new pass_dominator (ctxt); } -/* A hack until we remove threading from tree-vrp.c and bring the - simplification routine into the dom_opt_dom_walker class. */ -static class vr_values *x_vr_values; - -/* A trivial wrapper so that we can present the generic jump - threading code with a simple API for simplifying statements. - - ?? This should be cleaned up. There's a virtually identical copy - of this function in tree-vrp.c. */ - -static tree -simplify_stmt_for_jump_threading (gimple *stmt, - gimple *within_stmt ATTRIBUTE_UNUSED, - class avail_exprs_stack *avail_exprs_stack, - basic_block bb ATTRIBUTE_UNUSED) -{ - /* First query our hash table to see if the expression is available - there. A non-NULL return value will be either a constant or another - SSA_NAME. */ - tree cached_lhs = avail_exprs_stack->lookup_avail_expr (stmt, false, true); - if (cached_lhs) - return cached_lhs; - - /* If the hash table query failed, query VRP information. This is - essentially the same as tree-vrp's simplification routine. The - copy in tree-vrp is scheduled for removal in gcc-9. */ - if (gcond *cond_stmt = dyn_cast <gcond *> (stmt)) - { - simplify_using_ranges simplifier (x_vr_values); - return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt), - gimple_cond_lhs (cond_stmt), - gimple_cond_rhs (cond_stmt), - 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; - - const value_range_equiv *vr = x_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; - x_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; -} - /* Valueize hook for gimple_fold_stmt_to_constant_1. */ static tree @@ -1417,7 +1388,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "\n\nOptimizing block #%d\n\n", bb->index); - evrp_range_analyzer.enter (bb); + m_evrp_range_analyzer->enter (bb); /* Push a marker on the stacks of local information so that we know how far to unwind when we finalize this block. */ @@ -1454,8 +1425,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb) continue; } - /* Compute range information and optimize the stmt. */ - evrp_range_analyzer.record_ranges_from_stmt (gsi_stmt (gsi), false); + m_state->record_ranges_from_stmt (gsi_stmt (gsi), false); bool removed_p = false; taken_edge = this->optimize_stmt (bb, &gsi, &removed_p); if (!removed_p) @@ -1500,17 +1470,10 @@ dom_opt_dom_walker::before_dom_children (basic_block bb) void dom_opt_dom_walker::after_dom_children (basic_block bb) { - x_vr_values = &evrp_range_analyzer; - thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies, - m_avail_exprs_stack, - &evrp_range_analyzer, - simplify_stmt_for_jump_threading); - x_vr_values = NULL; - - /* These remove expressions local to BB from the tables. */ + m_threader->thread_outgoing_edges (bb); m_avail_exprs_stack->pop_to_marker (); m_const_and_copies->pop_to_marker (); - evrp_range_analyzer.leave (bb); + m_evrp_range_analyzer->leave (bb); } /* Search for redundant computations in STMT. If any are found, then @@ -1849,9 +1812,9 @@ cprop_into_stmt (gimple *stmt, vr_values *vr_values) This is similar to code in VRP. */ -static void -test_for_singularity (gimple *stmt, gcond *dummy_cond, - avail_exprs_stack *avail_exprs_stack) +void +dom_opt_dom_walker::test_for_singularity (gimple *stmt, + avail_exprs_stack *avail_exprs_stack) { /* We want to support gimple conditionals as well as assignments where the RHS contains a conditional. */ @@ -1897,11 +1860,12 @@ test_for_singularity (gimple *stmt, gcond *dummy_cond, test_code = GE_EXPR; /* Update the dummy statement so we can query the hash tables. */ - gimple_cond_set_code (dummy_cond, test_code); - gimple_cond_set_lhs (dummy_cond, lhs); - gimple_cond_set_rhs (dummy_cond, rhs); + gimple_cond_set_code (m_dummy_cond, test_code); + gimple_cond_set_lhs (m_dummy_cond, lhs); + gimple_cond_set_rhs (m_dummy_cond, rhs); tree cached_lhs - = avail_exprs_stack->lookup_avail_expr (dummy_cond, false, false); + = avail_exprs_stack->lookup_avail_expr (m_dummy_cond, + false, false); /* If the lookup returned 1 (true), then the expression we queried was in the hash table. As a result there is only @@ -1927,6 +1891,66 @@ test_for_singularity (gimple *stmt, gcond *dummy_cond, } } +/* If STMT is a comparison of two uniform vectors reduce it to a comparison + of scalar objects, otherwise leave STMT unchanged. */ + +static void +reduce_vector_comparison_to_scalar_comparison (gimple *stmt) +{ + if (gimple_code (stmt) == GIMPLE_COND) + { + tree lhs = gimple_cond_lhs (stmt); + tree rhs = gimple_cond_rhs (stmt); + + /* We may have a vector comparison where both arms are uniform + vectors. If so, we can simplify the vector comparison down + to a scalar comparison. */ + if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE + && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE) + { + /* If either operand is an SSA_NAME, then look back to its + defining statement to try and get at a suitable source. */ + if (TREE_CODE (rhs) == SSA_NAME) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (rhs); + if (gimple_assign_single_p (def_stmt)) + rhs = gimple_assign_rhs1 (def_stmt); + } + + if (TREE_CODE (lhs) == SSA_NAME) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (lhs); + if (gimple_assign_single_p (def_stmt)) + lhs = gimple_assign_rhs1 (def_stmt); + } + + /* Now see if they are both uniform vectors and if so replace + the vector comparison with a scalar comparison. */ + tree rhs_elem = rhs ? uniform_vector_p (rhs) : NULL_TREE; + tree lhs_elem = lhs ? uniform_vector_p (lhs) : NULL_TREE; + if (rhs_elem && lhs_elem) + { + if (dump_file && dump_flags & TDF_DETAILS) + { + fprintf (dump_file, "Reducing vector comparison: "); + print_gimple_stmt (dump_file, stmt, 0); + } + + gimple_cond_set_rhs (as_a <gcond *>(stmt), rhs_elem); + gimple_cond_set_lhs (as_a <gcond *>(stmt), lhs_elem); + gimple_set_modified (stmt, true); + + if (dump_file && dump_flags & TDF_DETAILS) + { + fprintf (dump_file, "To scalar equivalent: "); + print_gimple_stmt (dump_file, stmt, 0); + fprintf (dump_file, "\n"); + } + } + } + } +} + /* Optimize the statement in block BB pointed to by iterator SI. We try to perform some simplistic global redundancy elimination and @@ -1966,11 +1990,16 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si, print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } + /* STMT may be a comparison of uniform vectors that we can simplify + down to a comparison of scalars. Do that transformation first + so that all the scalar optimizations from here onward apply. */ + reduce_vector_comparison_to_scalar_comparison (stmt); + update_stmt_if_modified (stmt); opt_stats.num_stmts++; /* Const/copy propagate into USES, VUSES and the RHS of VDEFs. */ - cprop_into_stmt (stmt, &evrp_range_analyzer); + cprop_into_stmt (stmt, m_evrp_range_analyzer); /* If the statement has been modified with constant replacements, fold its RHS before checking for redundant computations. */ @@ -2068,8 +2097,8 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si, SSA_NAMES. */ update_stmt_if_modified (stmt); edge taken_edge = NULL; - evrp_range_analyzer.vrp_visit_cond_stmt (as_a <gcond *> (stmt), - &taken_edge); + m_evrp_range_analyzer->vrp_visit_cond_stmt + (as_a <gcond *> (stmt), &taken_edge); if (taken_edge) { if (taken_edge->flags & EDGE_TRUE_VALUE) @@ -2136,7 +2165,7 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si, /* If this statement was not redundant, we may still be able to simplify it, which may in turn allow other part of DOM or other passes to do a better job. */ - test_for_singularity (stmt, m_dummy_cond, m_avail_exprs_stack); + test_for_singularity (stmt, m_avail_exprs_stack); } /* Record any additional equivalences created by this statement. */ |