diff options
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/tree-ssa-dom.c | 272 |
2 files changed, 163 insertions, 126 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index abe7d85..258d424 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2017-08-28 Jeff Law <law@redhat.com> + + * tree-ssa-dom.c (class edge_info): Changed from a struct + to a class. Add ctor/dtor, methods and data members. + (edge_info::edge_info): Renamed from allocate_edge_info. + Initialize additional members. + (edge_info::~edge_info): New. + (free_dom_edge_info): Delete the edge info. + (record_edge_info): Use new class & associated member functions. + Tighten forms for testing for edge equivalences. + (record_temporary_equivalences): Iterate over the simple + equivalences rather than assuming there's only one per edge. + (cprop_into_successor_phis): Iterate over the simple + equivalences rather than assuming there's only one per edge. + (optimize_stmt): Use operand_equal_p rather than pointer + equality for mini-DSE code. + 2017-08-28 Nathan Sidwell <nathan@acm.org> * gcc.c (execute): Fold SIGPIPE handling into switch diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 407a4ef..403485b 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -58,17 +58,28 @@ along with GCC; see the file COPYING3. If not see These structures live for a single iteration of the dominator optimizer in the edge's AUX field. At the end of an iteration we free each of these structures. */ - -struct edge_info +class edge_info { - /* If this edge creates a simple equivalence, the LHS and RHS of - the equivalence will be stored here. */ - tree lhs; - tree rhs; + public: + typedef std::pair <tree, tree> equiv_pair; + edge_info (edge); + ~edge_info (); + + /* Record a simple LHS = RHS equivalence. This may trigger + calls to derive_equivalences. */ + void record_simple_equiv (tree, tree); + + /* If traversing this edge creates simple equivalences, we store + them as LHS/RHS pairs within this vector. */ + vec<equiv_pair> simple_equivalences; /* Traversing an edge may also indicate one or more particular conditions are true or false. */ vec<cond_equivalence> cond_equivalences; + + private: + /* Derive equivalences by walking the use-def chains. */ + void derive_equivalences (tree, tree, int); }; /* Track whether or not we have changed the control flow graph. */ @@ -109,36 +120,46 @@ static edge single_incoming_edge_ignoring_loop_edges (basic_block); static void dump_dominator_optimization_stats (FILE *file, hash_table<expr_elt_hasher> *); +/* Constructor for EDGE_INFO. An EDGE_INFO instance is always + associated with an edge E. */ -/* Free the edge_info data attached to E, if it exists. */ - -void -free_dom_edge_info (edge e) +edge_info::edge_info (edge e) { - struct edge_info *edge_info = (struct edge_info *)e->aux; + /* Free the old one associated with E, if it exists and + associate our new object with E. */ + free_dom_edge_info (e); + e->aux = this; - if (edge_info) - { - edge_info->cond_equivalences.release (); - free (edge_info); - } + /* And initialize the embedded vectors. */ + simple_equivalences = vNULL; + cond_equivalences = vNULL; } -/* Allocate an EDGE_INFO for edge E and attach it to E. - Return the new EDGE_INFO structure. */ +/* Destructor just needs to release the vectors. */ +edge_info::~edge_info (void) +{ + this->cond_equivalences.release (); + this->simple_equivalences.release (); +} + +/* Record that LHS is known to be equal to RHS at runtime when the + edge associated with THIS is traversed. */ -static struct edge_info * -allocate_edge_info (edge e) +void +edge_info::record_simple_equiv (tree lhs, tree rhs) { - struct edge_info *edge_info; + simple_equivalences.safe_push (equiv_pair (lhs, rhs)); +} - /* Free the old one, if it exists. */ - free_dom_edge_info (e); +/* Free the edge_info data attached to E, if it exists. */ - edge_info = XCNEW (struct edge_info); +void +free_dom_edge_info (edge e) +{ + class edge_info *edge_info = (struct edge_info *)e->aux; - e->aux = edge_info; - return edge_info; + if (edge_info) + delete edge_info; } /* Free all EDGE_INFO structures associated with edges in the CFG. @@ -171,7 +192,7 @@ static void record_edge_info (basic_block bb) { gimple_stmt_iterator gsi = gsi_last_bb (bb); - struct edge_info *edge_info; + class edge_info *edge_info; if (! gsi_end_p (gsi)) { @@ -212,9 +233,8 @@ record_edge_info (basic_block bb) { tree x = fold_convert_loc (loc, TREE_TYPE (index), CASE_LOW (label)); - edge_info = allocate_edge_info (e); - edge_info->lhs = index; - edge_info->rhs = x; + edge_info = new class edge_info (e); + edge_info->record_simple_equiv (index, x); } } free (info); @@ -251,28 +271,32 @@ record_edge_info (basic_block bb) if (code == EQ_EXPR) { - edge_info = allocate_edge_info (true_edge); - edge_info->lhs = op0; - edge_info->rhs = (integer_zerop (op1) ? false_val : true_val); - - edge_info = allocate_edge_info (false_edge); - edge_info->lhs = op0; - edge_info->rhs = (integer_zerop (op1) ? true_val : false_val); + edge_info = new class edge_info (true_edge); + edge_info->record_simple_equiv (op0, + (integer_zerop (op1) + ? false_val : true_val)); + edge_info = new class edge_info (false_edge); + edge_info->record_simple_equiv (op0, + (integer_zerop (op1) + ? true_val : false_val)); } else { - edge_info = allocate_edge_info (true_edge); - edge_info->lhs = op0; - edge_info->rhs = (integer_zerop (op1) ? true_val : false_val); - - edge_info = allocate_edge_info (false_edge); - edge_info->lhs = op0; - edge_info->rhs = (integer_zerop (op1) ? false_val : true_val); + edge_info = new class edge_info (true_edge); + edge_info->record_simple_equiv (op0, + (integer_zerop (op1) + ? true_val : false_val)); + edge_info = new class edge_info (false_edge); + edge_info->record_simple_equiv (op0, + (integer_zerop (op1) + ? false_val : true_val)); } } + /* This can show up in the IL as a result of copy propagation + it will eventually be canonicalized, but we have to cope + with this case within the pass. */ else if (is_gimple_min_invariant (op0) - && (TREE_CODE (op1) == SSA_NAME - || is_gimple_min_invariant (op1))) + && TREE_CODE (op1) == SSA_NAME) { tree cond = build2 (code, boolean_type_node, op0, op1); tree inverted = invert_truthvalue_loc (loc, cond); @@ -281,23 +305,17 @@ record_edge_info (basic_block bb) && real_zerop (op0)); struct edge_info *edge_info; - edge_info = allocate_edge_info (true_edge); + edge_info = new class edge_info (true_edge); record_conditions (&edge_info->cond_equivalences, cond, inverted); if (can_infer_simple_equiv && code == EQ_EXPR) - { - edge_info->lhs = op1; - edge_info->rhs = op0; - } + edge_info->record_simple_equiv (op1, op0); - edge_info = allocate_edge_info (false_edge); + edge_info = new class edge_info (false_edge); record_conditions (&edge_info->cond_equivalences, inverted, cond); if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR) - { - edge_info->lhs = op1; - edge_info->rhs = op0; - } + edge_info->record_simple_equiv (op1, op0); } else if (TREE_CODE (op0) == SSA_NAME @@ -311,27 +329,19 @@ record_edge_info (basic_block bb) && (TREE_CODE (op1) == SSA_NAME || real_zerop (op1))); struct edge_info *edge_info; - edge_info = allocate_edge_info (true_edge); + edge_info = new class edge_info (true_edge); record_conditions (&edge_info->cond_equivalences, cond, inverted); if (can_infer_simple_equiv && code == EQ_EXPR) - { - edge_info->lhs = op0; - edge_info->rhs = op1; - } + edge_info->record_simple_equiv (op0, op1); - edge_info = allocate_edge_info (false_edge); + edge_info = new class edge_info (false_edge); record_conditions (&edge_info->cond_equivalences, inverted, cond); if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR) - { - edge_info->lhs = op0; - edge_info->rhs = op1; - } + edge_info->record_simple_equiv (op0, op1); } } - - /* ??? TRUTH_NOT_EXPR can create an equivalence too. */ } } @@ -738,7 +748,7 @@ record_temporary_equivalences (edge e, class avail_exprs_stack *avail_exprs_stack) { int i; - struct edge_info *edge_info = (struct edge_info *) e->aux; + class edge_info *edge_info = (class edge_info *) e->aux; /* If we have info associated with this edge, record it into our equivalence tables. */ @@ -771,68 +781,73 @@ record_temporary_equivalences (edge e, } } - tree lhs = edge_info->lhs; - if (!lhs || TREE_CODE (lhs) != SSA_NAME) - return; + edge_info::equiv_pair *seq; + for (i = 0; edge_info->simple_equivalences.iterate (i, &seq); ++i) + { + tree lhs = seq->first; + if (!lhs || TREE_CODE (lhs) != SSA_NAME) + continue; - /* Record the simple NAME = VALUE equivalence. */ - tree rhs = edge_info->rhs; + /* Record the simple NAME = VALUE equivalence. */ + tree rhs = seq->second; - /* If this is a SSA_NAME = SSA_NAME equivalence and one operand is - cheaper to compute than the other, then set up the equivalence - such that we replace the expensive one with the cheap one. + /* If this is a SSA_NAME = SSA_NAME equivalence and one operand is + cheaper to compute than the other, then set up the equivalence + such that we replace the expensive one with the cheap one. - If they are the same cost to compute, then do not record anything. */ - if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs) == SSA_NAME) - { - gimple *rhs_def = SSA_NAME_DEF_STMT (rhs); - int rhs_cost = estimate_num_insns (rhs_def, &eni_size_weights); + If they are the same cost to compute, then do not record + anything. */ + if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs) == SSA_NAME) + { + gimple *rhs_def = SSA_NAME_DEF_STMT (rhs); + int rhs_cost = estimate_num_insns (rhs_def, &eni_size_weights); - gimple *lhs_def = SSA_NAME_DEF_STMT (lhs); - int lhs_cost = estimate_num_insns (lhs_def, &eni_size_weights); + gimple *lhs_def = SSA_NAME_DEF_STMT (lhs); + int lhs_cost = estimate_num_insns (lhs_def, &eni_size_weights); - if (rhs_cost > lhs_cost) - record_equality (rhs, lhs, const_and_copies); - else if (rhs_cost < lhs_cost) + if (rhs_cost > lhs_cost) + record_equality (rhs, lhs, const_and_copies); + else if (rhs_cost < lhs_cost) + record_equality (lhs, rhs, const_and_copies); + } + else record_equality (lhs, rhs, const_and_copies); - } - else - record_equality (lhs, rhs, const_and_copies); - /* If LHS is an SSA_NAME and RHS is a constant integer and LHS was - set via a widening type conversion, then we may be able to record - additional equivalences. */ - if (TREE_CODE (rhs) == INTEGER_CST) - { - gimple *defstmt = SSA_NAME_DEF_STMT (lhs); - - if (defstmt - && is_gimple_assign (defstmt) - && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (defstmt))) + /* If LHS is an SSA_NAME and RHS is a constant integer and LHS was + set via a widening type conversion, then we may be able to record + additional equivalences. */ + if (TREE_CODE (rhs) == INTEGER_CST) { - tree old_rhs = gimple_assign_rhs1 (defstmt); - - /* If the conversion widens the original value and - the constant is in the range of the type of OLD_RHS, - then convert the constant and record the equivalence. - - Note that int_fits_type_p does not check the precision - if the upper and lower bounds are OK. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (old_rhs)) - && (TYPE_PRECISION (TREE_TYPE (lhs)) - > TYPE_PRECISION (TREE_TYPE (old_rhs))) - && int_fits_type_p (rhs, TREE_TYPE (old_rhs))) + gimple *defstmt = SSA_NAME_DEF_STMT (lhs); + + if (defstmt + && is_gimple_assign (defstmt) + && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (defstmt))) { - tree newval = fold_convert (TREE_TYPE (old_rhs), rhs); - record_equality (old_rhs, newval, const_and_copies); + tree old_rhs = gimple_assign_rhs1 (defstmt); + + /* If the conversion widens the original value and + the constant is in the range of the type of OLD_RHS, + then convert the constant and record the equivalence. + + Note that int_fits_type_p does not check the precision + if the upper and lower bounds are OK. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (old_rhs)) + && (TYPE_PRECISION (TREE_TYPE (lhs)) + > TYPE_PRECISION (TREE_TYPE (old_rhs))) + && int_fits_type_p (rhs, TREE_TYPE (old_rhs))) + { + tree newval = fold_convert (TREE_TYPE (old_rhs), rhs); + record_equality (old_rhs, newval, const_and_copies); + } } } - } - /* Any equivalence found for LHS may result in additional - equivalences for other uses of LHS that we have already - processed. */ - back_propagate_equivalences (lhs, e, const_and_copies); + /* Any equivalence found for LHS may result in additional + equivalences for other uses of LHS that we have already + processed. */ + back_propagate_equivalences (lhs, e, const_and_copies); + } } } @@ -1124,14 +1139,20 @@ cprop_into_successor_phis (basic_block bb, Don't bother with [01] = COND equivalences, they're not useful here. */ - struct edge_info *edge_info = (struct edge_info *) e->aux; + class edge_info *edge_info = (class edge_info *) e->aux; + if (edge_info) { - tree lhs = edge_info->lhs; - tree rhs = edge_info->rhs; + edge_info::equiv_pair *seq; + for (int i = 0; edge_info->simple_equivalences.iterate (i, &seq); ++i) + { + tree lhs = seq->first; + tree rhs = seq->second; + + if (lhs && TREE_CODE (lhs) == SSA_NAME) + const_and_copies->record_const_or_copy (lhs, rhs); + } - if (lhs && TREE_CODE (lhs) == SSA_NAME) - const_and_copies->record_const_or_copy (lhs, rhs); } indx = e->dest_idx; @@ -1701,8 +1722,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si, gimple_set_vuse (new_stmt, gimple_vuse (stmt)); cached_lhs = avail_exprs_stack->lookup_avail_expr (new_stmt, false, false); - if (cached_lhs - && rhs == cached_lhs) + if (cached_lhs && operand_equal_p (rhs, cached_lhs, 0)) { basic_block bb = gimple_bb (stmt); unlink_stmt_vdef (stmt); |