138fd1498Szrj /* Routines for discovering and unpropagating edge equivalences.
238fd1498Szrj Copyright (C) 2005-2018 Free Software Foundation, Inc.
338fd1498Szrj
438fd1498Szrj This file is part of GCC.
538fd1498Szrj
638fd1498Szrj GCC is free software; you can redistribute it and/or modify
738fd1498Szrj it under the terms of the GNU General Public License as published by
838fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj any later version.
1038fd1498Szrj
1138fd1498Szrj GCC is distributed in the hope that it will be useful,
1238fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1438fd1498Szrj GNU General Public License for more details.
1538fd1498Szrj
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3. If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>. */
1938fd1498Szrj
2038fd1498Szrj #include "config.h"
2138fd1498Szrj #include "system.h"
2238fd1498Szrj #include "coretypes.h"
2338fd1498Szrj #include "backend.h"
2438fd1498Szrj #include "tree.h"
2538fd1498Szrj #include "gimple.h"
2638fd1498Szrj #include "tree-pass.h"
2738fd1498Szrj #include "ssa.h"
2838fd1498Szrj #include "fold-const.h"
2938fd1498Szrj #include "cfganal.h"
3038fd1498Szrj #include "gimple-iterator.h"
3138fd1498Szrj #include "tree-cfg.h"
3238fd1498Szrj #include "domwalk.h"
3338fd1498Szrj #include "tree-hash-traits.h"
3438fd1498Szrj #include "tree-ssa-live.h"
3538fd1498Szrj #include "tree-ssa-coalesce.h"
3638fd1498Szrj
3738fd1498Szrj /* The basic structure describing an equivalency created by traversing
3838fd1498Szrj an edge. Traversing the edge effectively means that we can assume
3938fd1498Szrj that we've seen an assignment LHS = RHS. */
4038fd1498Szrj struct edge_equivalency
4138fd1498Szrj {
4238fd1498Szrj tree rhs;
4338fd1498Szrj tree lhs;
4438fd1498Szrj };
4538fd1498Szrj
4638fd1498Szrj /* This routine finds and records edge equivalences for every edge
4738fd1498Szrj in the CFG.
4838fd1498Szrj
4938fd1498Szrj When complete, each edge that creates an equivalency will have an
5038fd1498Szrj EDGE_EQUIVALENCY structure hanging off the edge's AUX field.
5138fd1498Szrj The caller is responsible for freeing the AUX fields. */
5238fd1498Szrj
5338fd1498Szrj static void
associate_equivalences_with_edges(void)5438fd1498Szrj associate_equivalences_with_edges (void)
5538fd1498Szrj {
5638fd1498Szrj basic_block bb;
5738fd1498Szrj
5838fd1498Szrj /* Walk over each block. If the block ends with a control statement,
5938fd1498Szrj then it might create a useful equivalence. */
6038fd1498Szrj FOR_EACH_BB_FN (bb, cfun)
6138fd1498Szrj {
6238fd1498Szrj gimple_stmt_iterator gsi = gsi_last_bb (bb);
6338fd1498Szrj gimple *stmt;
6438fd1498Szrj
6538fd1498Szrj /* If the block does not end with a COND_EXPR or SWITCH_EXPR
6638fd1498Szrj then there is nothing to do. */
6738fd1498Szrj if (gsi_end_p (gsi))
6838fd1498Szrj continue;
6938fd1498Szrj
7038fd1498Szrj stmt = gsi_stmt (gsi);
7138fd1498Szrj
7238fd1498Szrj if (!stmt)
7338fd1498Szrj continue;
7438fd1498Szrj
7538fd1498Szrj /* A COND_EXPR may create an equivalency in a variety of different
7638fd1498Szrj ways. */
7738fd1498Szrj if (gimple_code (stmt) == GIMPLE_COND)
7838fd1498Szrj {
7938fd1498Szrj edge true_edge;
8038fd1498Szrj edge false_edge;
8138fd1498Szrj struct edge_equivalency *equivalency;
8238fd1498Szrj enum tree_code code = gimple_cond_code (stmt);
8338fd1498Szrj
8438fd1498Szrj extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
8538fd1498Szrj
8638fd1498Szrj /* Equality tests may create one or two equivalences. */
8738fd1498Szrj if (code == EQ_EXPR || code == NE_EXPR)
8838fd1498Szrj {
8938fd1498Szrj tree op0 = gimple_cond_lhs (stmt);
9038fd1498Szrj tree op1 = gimple_cond_rhs (stmt);
9138fd1498Szrj
9238fd1498Szrj /* Special case comparing booleans against a constant as we
9338fd1498Szrj know the value of OP0 on both arms of the branch. i.e., we
9438fd1498Szrj can record an equivalence for OP0 rather than COND. */
9538fd1498Szrj if (TREE_CODE (op0) == SSA_NAME
9638fd1498Szrj && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
9738fd1498Szrj && ssa_name_has_boolean_range (op0)
9838fd1498Szrj && is_gimple_min_invariant (op1)
9938fd1498Szrj && (integer_zerop (op1) || integer_onep (op1)))
10038fd1498Szrj {
10138fd1498Szrj tree true_val = constant_boolean_node (true, TREE_TYPE (op0));
10238fd1498Szrj tree false_val = constant_boolean_node (false,
10338fd1498Szrj TREE_TYPE (op0));
10438fd1498Szrj if (code == EQ_EXPR)
10538fd1498Szrj {
10638fd1498Szrj equivalency = XNEW (struct edge_equivalency);
10738fd1498Szrj equivalency->lhs = op0;
10838fd1498Szrj equivalency->rhs = (integer_zerop (op1)
10938fd1498Szrj ? false_val
11038fd1498Szrj : true_val);
11138fd1498Szrj true_edge->aux = equivalency;
11238fd1498Szrj
11338fd1498Szrj equivalency = XNEW (struct edge_equivalency);
11438fd1498Szrj equivalency->lhs = op0;
11538fd1498Szrj equivalency->rhs = (integer_zerop (op1)
11638fd1498Szrj ? true_val
11738fd1498Szrj : false_val);
11838fd1498Szrj false_edge->aux = equivalency;
11938fd1498Szrj }
12038fd1498Szrj else
12138fd1498Szrj {
12238fd1498Szrj equivalency = XNEW (struct edge_equivalency);
12338fd1498Szrj equivalency->lhs = op0;
12438fd1498Szrj equivalency->rhs = (integer_zerop (op1)
12538fd1498Szrj ? true_val
12638fd1498Szrj : false_val);
12738fd1498Szrj true_edge->aux = equivalency;
12838fd1498Szrj
12938fd1498Szrj equivalency = XNEW (struct edge_equivalency);
13038fd1498Szrj equivalency->lhs = op0;
13138fd1498Szrj equivalency->rhs = (integer_zerop (op1)
13238fd1498Szrj ? false_val
13338fd1498Szrj : true_val);
13438fd1498Szrj false_edge->aux = equivalency;
13538fd1498Szrj }
13638fd1498Szrj }
13738fd1498Szrj
13838fd1498Szrj else if (TREE_CODE (op0) == SSA_NAME
13938fd1498Szrj && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
14038fd1498Szrj && (is_gimple_min_invariant (op1)
14138fd1498Szrj || (TREE_CODE (op1) == SSA_NAME
14238fd1498Szrj && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))))
14338fd1498Szrj {
14438fd1498Szrj /* For IEEE, -0.0 == 0.0, so we don't necessarily know
14538fd1498Szrj the sign of a variable compared against zero. If
14638fd1498Szrj we're honoring signed zeros, then we cannot record
14738fd1498Szrj this value unless we know that the value is nonzero. */
14838fd1498Szrj if (HONOR_SIGNED_ZEROS (op0)
14938fd1498Szrj && (TREE_CODE (op1) != REAL_CST
15038fd1498Szrj || real_equal (&dconst0, &TREE_REAL_CST (op1))))
15138fd1498Szrj continue;
15238fd1498Szrj
15338fd1498Szrj equivalency = XNEW (struct edge_equivalency);
15438fd1498Szrj equivalency->lhs = op0;
15538fd1498Szrj equivalency->rhs = op1;
15638fd1498Szrj if (code == EQ_EXPR)
15738fd1498Szrj true_edge->aux = equivalency;
15838fd1498Szrj else
15938fd1498Szrj false_edge->aux = equivalency;
16038fd1498Szrj
16138fd1498Szrj }
16238fd1498Szrj }
16338fd1498Szrj
16438fd1498Szrj /* ??? TRUTH_NOT_EXPR can create an equivalence too. */
16538fd1498Szrj }
16638fd1498Szrj
16738fd1498Szrj /* For a SWITCH_EXPR, a case label which represents a single
16838fd1498Szrj value and which is the only case label which reaches the
16938fd1498Szrj target block creates an equivalence. */
17038fd1498Szrj else if (gimple_code (stmt) == GIMPLE_SWITCH)
17138fd1498Szrj {
17238fd1498Szrj gswitch *switch_stmt = as_a <gswitch *> (stmt);
17338fd1498Szrj tree cond = gimple_switch_index (switch_stmt);
17438fd1498Szrj
17538fd1498Szrj if (TREE_CODE (cond) == SSA_NAME
17638fd1498Szrj && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
17738fd1498Szrj {
17838fd1498Szrj int i, n_labels = gimple_switch_num_labels (switch_stmt);
17938fd1498Szrj tree *info = XCNEWVEC (tree, last_basic_block_for_fn (cfun));
18038fd1498Szrj
18138fd1498Szrj /* Walk over the case label vector. Record blocks
18238fd1498Szrj which are reached by a single case label which represents
18338fd1498Szrj a single value. */
18438fd1498Szrj for (i = 0; i < n_labels; i++)
18538fd1498Szrj {
18638fd1498Szrj tree label = gimple_switch_label (switch_stmt, i);
18738fd1498Szrj basic_block bb = label_to_block (CASE_LABEL (label));
18838fd1498Szrj
18938fd1498Szrj if (CASE_HIGH (label)
19038fd1498Szrj || !CASE_LOW (label)
19138fd1498Szrj || info[bb->index])
19238fd1498Szrj info[bb->index] = error_mark_node;
19338fd1498Szrj else
19438fd1498Szrj info[bb->index] = label;
19538fd1498Szrj }
19638fd1498Szrj
19738fd1498Szrj /* Now walk over the blocks to determine which ones were
19838fd1498Szrj marked as being reached by a useful case label. */
19938fd1498Szrj for (i = 0; i < n_basic_blocks_for_fn (cfun); i++)
20038fd1498Szrj {
20138fd1498Szrj tree node = info[i];
20238fd1498Szrj
20338fd1498Szrj if (node != NULL
20438fd1498Szrj && node != error_mark_node)
20538fd1498Szrj {
20638fd1498Szrj tree x = fold_convert (TREE_TYPE (cond), CASE_LOW (node));
20738fd1498Szrj struct edge_equivalency *equivalency;
20838fd1498Szrj
20938fd1498Szrj /* Record an equivalency on the edge from BB to basic
21038fd1498Szrj block I. */
21138fd1498Szrj equivalency = XNEW (struct edge_equivalency);
21238fd1498Szrj equivalency->rhs = x;
21338fd1498Szrj equivalency->lhs = cond;
21438fd1498Szrj find_edge (bb, BASIC_BLOCK_FOR_FN (cfun, i))->aux =
21538fd1498Szrj equivalency;
21638fd1498Szrj }
21738fd1498Szrj }
21838fd1498Szrj free (info);
21938fd1498Szrj }
22038fd1498Szrj }
22138fd1498Szrj
22238fd1498Szrj }
22338fd1498Szrj }
22438fd1498Szrj
22538fd1498Szrj
22638fd1498Szrj /* Translating out of SSA sometimes requires inserting copies and
22738fd1498Szrj constant initializations on edges to eliminate PHI nodes.
22838fd1498Szrj
22938fd1498Szrj In some cases those copies and constant initializations are
23038fd1498Szrj redundant because the target already has the value on the
23138fd1498Szrj RHS of the assignment.
23238fd1498Szrj
23338fd1498Szrj We previously tried to catch these cases after translating
23438fd1498Szrj out of SSA form. However, that code often missed cases. Worse
23538fd1498Szrj yet, the cases it missed were also often missed by the RTL
23638fd1498Szrj optimizers. Thus the resulting code had redundant instructions.
23738fd1498Szrj
23838fd1498Szrj This pass attempts to detect these situations before translating
23938fd1498Szrj out of SSA form.
24038fd1498Szrj
24138fd1498Szrj The key concept that this pass is built upon is that these
24238fd1498Szrj redundant copies and constant initializations often occur
24338fd1498Szrj due to constant/copy propagating equivalences resulting from
24438fd1498Szrj COND_EXPRs and SWITCH_EXPRs.
24538fd1498Szrj
24638fd1498Szrj We want to do those propagations as they can sometimes allow
24738fd1498Szrj the SSA optimizers to do a better job. However, in the cases
24838fd1498Szrj where such propagations do not result in further optimization,
24938fd1498Szrj we would like to "undo" the propagation to avoid the redundant
25038fd1498Szrj copies and constant initializations.
25138fd1498Szrj
25238fd1498Szrj This pass works by first associating equivalences with edges in
25338fd1498Szrj the CFG. For example, the edge leading from a SWITCH_EXPR to
25438fd1498Szrj its associated CASE_LABEL will have an equivalency between
25538fd1498Szrj SWITCH_COND and the value in the case label.
25638fd1498Szrj
25738fd1498Szrj Once we have found the edge equivalences, we proceed to walk
25838fd1498Szrj the CFG in dominator order. As we traverse edges we record
25938fd1498Szrj equivalences associated with those edges we traverse.
26038fd1498Szrj
26138fd1498Szrj When we encounter a PHI node, we walk its arguments to see if we
26238fd1498Szrj have an equivalence for the PHI argument. If so, then we replace
26338fd1498Szrj the argument.
26438fd1498Szrj
26538fd1498Szrj Equivalences are looked up based on their value (think of it as
26638fd1498Szrj the RHS of an assignment). A value may be an SSA_NAME or an
26738fd1498Szrj invariant. We may have several SSA_NAMEs with the same value,
26838fd1498Szrj so with each value we have a list of SSA_NAMEs that have the
26938fd1498Szrj same value. */
27038fd1498Szrj
271*58e805e6Szrj /* Traits for the hash_map to record the value to SSA name equivalences
272*58e805e6Szrj mapping. */
273*58e805e6Szrj struct ssa_equip_hash_traits : default_hash_traits <tree>
27438fd1498Szrj {
hashssa_equip_hash_traits275*58e805e6Szrj static inline hashval_t hash (value_type value)
276*58e805e6Szrj { return iterative_hash_expr (value, 0); }
equalssa_equip_hash_traits277*58e805e6Szrj static inline bool equal (value_type existing, value_type candidate)
278*58e805e6Szrj { return operand_equal_p (existing, candidate, 0); }
27938fd1498Szrj };
28038fd1498Szrj
281*58e805e6Szrj typedef hash_map<tree, auto_vec<tree>,
282*58e805e6Szrj simple_hashmap_traits <ssa_equip_hash_traits,
283*58e805e6Szrj auto_vec <tree> > > val_ssa_equiv_t;
284*58e805e6Szrj
28538fd1498Szrj /* Global hash table implementing a mapping from invariant values
28638fd1498Szrj to a list of SSA_NAMEs which have the same value. We might be
28738fd1498Szrj able to reuse tree-vn for this code. */
288*58e805e6Szrj val_ssa_equiv_t *val_ssa_equiv;
28938fd1498Szrj
29038fd1498Szrj static void uncprop_into_successor_phis (basic_block);
29138fd1498Szrj
29238fd1498Szrj /* Remove the most recently recorded equivalency for VALUE. */
29338fd1498Szrj
29438fd1498Szrj static void
remove_equivalence(tree value)29538fd1498Szrj remove_equivalence (tree value)
29638fd1498Szrj {
29738fd1498Szrj val_ssa_equiv->get (value)->pop ();
29838fd1498Szrj }
29938fd1498Szrj
30038fd1498Szrj /* Record EQUIVALENCE = VALUE into our hash table. */
30138fd1498Szrj
30238fd1498Szrj static void
record_equiv(tree value,tree equivalence)30338fd1498Szrj record_equiv (tree value, tree equivalence)
30438fd1498Szrj {
30538fd1498Szrj val_ssa_equiv->get_or_insert (value).safe_push (equivalence);
30638fd1498Szrj }
30738fd1498Szrj
30838fd1498Szrj class uncprop_dom_walker : public dom_walker
30938fd1498Szrj {
31038fd1498Szrj public:
uncprop_dom_walker(cdi_direction direction)31138fd1498Szrj uncprop_dom_walker (cdi_direction direction) : dom_walker (direction) {}
31238fd1498Szrj
31338fd1498Szrj virtual edge before_dom_children (basic_block);
31438fd1498Szrj virtual void after_dom_children (basic_block);
31538fd1498Szrj
31638fd1498Szrj private:
31738fd1498Szrj
31838fd1498Szrj /* As we enter each block we record the value for any edge equivalency
31938fd1498Szrj leading to this block. If no such edge equivalency exists, then we
32038fd1498Szrj record NULL. These equivalences are live until we leave the dominator
32138fd1498Szrj subtree rooted at the block where we record the equivalency. */
32238fd1498Szrj auto_vec<tree, 2> m_equiv_stack;
32338fd1498Szrj };
32438fd1498Szrj
32538fd1498Szrj /* We have finished processing the dominator children of BB, perform
32638fd1498Szrj any finalization actions in preparation for leaving this node in
32738fd1498Szrj the dominator tree. */
32838fd1498Szrj
32938fd1498Szrj void
after_dom_children(basic_block bb ATTRIBUTE_UNUSED)33038fd1498Szrj uncprop_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
33138fd1498Szrj {
33238fd1498Szrj /* Pop the topmost value off the equiv stack. */
33338fd1498Szrj tree value = m_equiv_stack.pop ();
33438fd1498Szrj
33538fd1498Szrj /* If that value was non-null, then pop the topmost equivalency off
33638fd1498Szrj its equivalency stack. */
33738fd1498Szrj if (value != NULL)
33838fd1498Szrj remove_equivalence (value);
33938fd1498Szrj }
34038fd1498Szrj
34138fd1498Szrj /* Unpropagate values from PHI nodes in successor blocks of BB. */
34238fd1498Szrj
34338fd1498Szrj static void
uncprop_into_successor_phis(basic_block bb)34438fd1498Szrj uncprop_into_successor_phis (basic_block bb)
34538fd1498Szrj {
34638fd1498Szrj edge e;
34738fd1498Szrj edge_iterator ei;
34838fd1498Szrj
34938fd1498Szrj /* For each successor edge, first temporarily record any equivalence
35038fd1498Szrj on that edge. Then unpropagate values in any PHI nodes at the
35138fd1498Szrj destination of the edge. Then remove the temporary equivalence. */
35238fd1498Szrj FOR_EACH_EDGE (e, ei, bb->succs)
35338fd1498Szrj {
35438fd1498Szrj gimple_seq phis = phi_nodes (e->dest);
35538fd1498Szrj gimple_stmt_iterator gsi;
35638fd1498Szrj
35738fd1498Szrj /* If there are no PHI nodes in this destination, then there is
35838fd1498Szrj no sense in recording any equivalences. */
35938fd1498Szrj if (gimple_seq_empty_p (phis))
36038fd1498Szrj continue;
36138fd1498Szrj
36238fd1498Szrj /* Record any equivalency associated with E. */
36338fd1498Szrj if (e->aux)
36438fd1498Szrj {
36538fd1498Szrj struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
36638fd1498Szrj record_equiv (equiv->rhs, equiv->lhs);
36738fd1498Szrj }
36838fd1498Szrj
36938fd1498Szrj /* Walk over the PHI nodes, unpropagating values. */
37038fd1498Szrj for (gsi = gsi_start (phis) ; !gsi_end_p (gsi); gsi_next (&gsi))
37138fd1498Szrj {
37238fd1498Szrj gimple *phi = gsi_stmt (gsi);
37338fd1498Szrj tree arg = PHI_ARG_DEF (phi, e->dest_idx);
37438fd1498Szrj tree res = PHI_RESULT (phi);
37538fd1498Szrj
37638fd1498Szrj /* If the argument is not an invariant and can be potentially
37738fd1498Szrj coalesced with the result, then there's no point in
37838fd1498Szrj un-propagating the argument. */
37938fd1498Szrj if (!is_gimple_min_invariant (arg)
38038fd1498Szrj && gimple_can_coalesce_p (arg, res))
38138fd1498Szrj continue;
38238fd1498Szrj
38338fd1498Szrj /* Lookup this argument's value in the hash table. */
38438fd1498Szrj vec<tree> *equivalences = val_ssa_equiv->get (arg);
38538fd1498Szrj if (equivalences)
38638fd1498Szrj {
38738fd1498Szrj /* Walk every equivalence with the same value. If we find
38838fd1498Szrj one that can potentially coalesce with the PHI rsult,
38938fd1498Szrj then replace the value in the argument with its equivalent
39038fd1498Szrj SSA_NAME. Use the most recent equivalence as hopefully
39138fd1498Szrj that results in shortest lifetimes. */
39238fd1498Szrj for (int j = equivalences->length () - 1; j >= 0; j--)
39338fd1498Szrj {
39438fd1498Szrj tree equiv = (*equivalences)[j];
39538fd1498Szrj
39638fd1498Szrj if (gimple_can_coalesce_p (equiv, res))
39738fd1498Szrj {
39838fd1498Szrj SET_PHI_ARG_DEF (phi, e->dest_idx, equiv);
39938fd1498Szrj break;
40038fd1498Szrj }
40138fd1498Szrj }
40238fd1498Szrj }
40338fd1498Szrj }
40438fd1498Szrj
40538fd1498Szrj /* If we had an equivalence associated with this edge, remove it. */
40638fd1498Szrj if (e->aux)
40738fd1498Szrj {
40838fd1498Szrj struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
40938fd1498Szrj remove_equivalence (equiv->rhs);
41038fd1498Szrj }
41138fd1498Szrj }
41238fd1498Szrj }
41338fd1498Szrj
41438fd1498Szrj edge
before_dom_children(basic_block bb)41538fd1498Szrj uncprop_dom_walker::before_dom_children (basic_block bb)
41638fd1498Szrj {
41738fd1498Szrj basic_block parent;
41838fd1498Szrj bool recorded = false;
41938fd1498Szrj
42038fd1498Szrj /* If this block is dominated by a single incoming edge and that edge
42138fd1498Szrj has an equivalency, then record the equivalency and push the
42238fd1498Szrj VALUE onto EQUIV_STACK. Else push a NULL entry on EQUIV_STACK. */
42338fd1498Szrj parent = get_immediate_dominator (CDI_DOMINATORS, bb);
42438fd1498Szrj if (parent)
42538fd1498Szrj {
42638fd1498Szrj edge e = single_pred_edge_ignoring_loop_edges (bb, false);
42738fd1498Szrj
42838fd1498Szrj if (e && e->src == parent && e->aux)
42938fd1498Szrj {
43038fd1498Szrj struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
43138fd1498Szrj
43238fd1498Szrj record_equiv (equiv->rhs, equiv->lhs);
43338fd1498Szrj m_equiv_stack.safe_push (equiv->rhs);
43438fd1498Szrj recorded = true;
43538fd1498Szrj }
43638fd1498Szrj }
43738fd1498Szrj
43838fd1498Szrj if (!recorded)
43938fd1498Szrj m_equiv_stack.safe_push (NULL_TREE);
44038fd1498Szrj
44138fd1498Szrj uncprop_into_successor_phis (bb);
44238fd1498Szrj return NULL;
44338fd1498Szrj }
44438fd1498Szrj
44538fd1498Szrj namespace {
44638fd1498Szrj
44738fd1498Szrj const pass_data pass_data_uncprop =
44838fd1498Szrj {
44938fd1498Szrj GIMPLE_PASS, /* type */
45038fd1498Szrj "uncprop", /* name */
45138fd1498Szrj OPTGROUP_NONE, /* optinfo_flags */
45238fd1498Szrj TV_TREE_SSA_UNCPROP, /* tv_id */
45338fd1498Szrj ( PROP_cfg | PROP_ssa ), /* properties_required */
45438fd1498Szrj 0, /* properties_provided */
45538fd1498Szrj 0, /* properties_destroyed */
45638fd1498Szrj 0, /* todo_flags_start */
45738fd1498Szrj 0, /* todo_flags_finish */
45838fd1498Szrj };
45938fd1498Szrj
46038fd1498Szrj class pass_uncprop : public gimple_opt_pass
46138fd1498Szrj {
46238fd1498Szrj public:
pass_uncprop(gcc::context * ctxt)46338fd1498Szrj pass_uncprop (gcc::context *ctxt)
46438fd1498Szrj : gimple_opt_pass (pass_data_uncprop, ctxt)
46538fd1498Szrj {}
46638fd1498Szrj
46738fd1498Szrj /* opt_pass methods: */
clone()46838fd1498Szrj opt_pass * clone () { return new pass_uncprop (m_ctxt); }
gate(function *)46938fd1498Szrj virtual bool gate (function *) { return flag_tree_dom != 0; }
47038fd1498Szrj virtual unsigned int execute (function *);
47138fd1498Szrj
47238fd1498Szrj }; // class pass_uncprop
47338fd1498Szrj
47438fd1498Szrj unsigned int
execute(function * fun)47538fd1498Szrj pass_uncprop::execute (function *fun)
47638fd1498Szrj {
47738fd1498Szrj basic_block bb;
47838fd1498Szrj
47938fd1498Szrj associate_equivalences_with_edges ();
48038fd1498Szrj
48138fd1498Szrj /* Create our global data structures. */
482*58e805e6Szrj val_ssa_equiv = new val_ssa_equiv_t (1024);
48338fd1498Szrj
48438fd1498Szrj /* We're going to do a dominator walk, so ensure that we have
48538fd1498Szrj dominance information. */
48638fd1498Szrj calculate_dominance_info (CDI_DOMINATORS);
48738fd1498Szrj
48838fd1498Szrj /* Recursively walk the dominator tree undoing unprofitable
48938fd1498Szrj constant/copy propagations. */
49038fd1498Szrj uncprop_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr);
49138fd1498Szrj
49238fd1498Szrj /* we just need to empty elements out of the hash table, and cleanup the
49338fd1498Szrj AUX field on the edges. */
49438fd1498Szrj delete val_ssa_equiv;
49538fd1498Szrj val_ssa_equiv = NULL;
49638fd1498Szrj FOR_EACH_BB_FN (bb, fun)
49738fd1498Szrj {
49838fd1498Szrj edge e;
49938fd1498Szrj edge_iterator ei;
50038fd1498Szrj
50138fd1498Szrj FOR_EACH_EDGE (e, ei, bb->succs)
50238fd1498Szrj {
50338fd1498Szrj if (e->aux)
50438fd1498Szrj {
50538fd1498Szrj free (e->aux);
50638fd1498Szrj e->aux = NULL;
50738fd1498Szrj }
50838fd1498Szrj }
50938fd1498Szrj }
51038fd1498Szrj return 0;
51138fd1498Szrj }
51238fd1498Szrj
51338fd1498Szrj } // anon namespace
51438fd1498Szrj
51538fd1498Szrj gimple_opt_pass *
make_pass_uncprop(gcc::context * ctxt)51638fd1498Szrj make_pass_uncprop (gcc::context *ctxt)
51738fd1498Szrj {
51838fd1498Szrj return new pass_uncprop (ctxt);
51938fd1498Szrj }
520