11debfc3dSmrg /* Routines for discovering and unpropagating edge equivalences.
2*8feb0f0bSmrg Copyright (C) 2005-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify
71debfc3dSmrg it under the terms of the GNU General Public License as published by
81debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
91debfc3dSmrg any later version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful,
121debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141debfc3dSmrg GNU General Public License for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "backend.h"
241debfc3dSmrg #include "tree.h"
251debfc3dSmrg #include "gimple.h"
261debfc3dSmrg #include "tree-pass.h"
271debfc3dSmrg #include "ssa.h"
281debfc3dSmrg #include "fold-const.h"
291debfc3dSmrg #include "cfganal.h"
301debfc3dSmrg #include "gimple-iterator.h"
311debfc3dSmrg #include "tree-cfg.h"
321debfc3dSmrg #include "domwalk.h"
331debfc3dSmrg #include "tree-hash-traits.h"
341debfc3dSmrg #include "tree-ssa-live.h"
351debfc3dSmrg #include "tree-ssa-coalesce.h"
361debfc3dSmrg
371debfc3dSmrg /* The basic structure describing an equivalency created by traversing
381debfc3dSmrg an edge. Traversing the edge effectively means that we can assume
391debfc3dSmrg that we've seen an assignment LHS = RHS. */
401debfc3dSmrg struct edge_equivalency
411debfc3dSmrg {
421debfc3dSmrg tree rhs;
431debfc3dSmrg tree lhs;
441debfc3dSmrg };
451debfc3dSmrg
461debfc3dSmrg /* This routine finds and records edge equivalences for every edge
471debfc3dSmrg in the CFG.
481debfc3dSmrg
491debfc3dSmrg When complete, each edge that creates an equivalency will have an
501debfc3dSmrg EDGE_EQUIVALENCY structure hanging off the edge's AUX field.
511debfc3dSmrg The caller is responsible for freeing the AUX fields. */
521debfc3dSmrg
531debfc3dSmrg static void
associate_equivalences_with_edges(void)541debfc3dSmrg associate_equivalences_with_edges (void)
551debfc3dSmrg {
561debfc3dSmrg basic_block bb;
571debfc3dSmrg
581debfc3dSmrg /* Walk over each block. If the block ends with a control statement,
591debfc3dSmrg then it might create a useful equivalence. */
601debfc3dSmrg FOR_EACH_BB_FN (bb, cfun)
611debfc3dSmrg {
621debfc3dSmrg gimple_stmt_iterator gsi = gsi_last_bb (bb);
631debfc3dSmrg gimple *stmt;
641debfc3dSmrg
651debfc3dSmrg /* If the block does not end with a COND_EXPR or SWITCH_EXPR
661debfc3dSmrg then there is nothing to do. */
671debfc3dSmrg if (gsi_end_p (gsi))
681debfc3dSmrg continue;
691debfc3dSmrg
701debfc3dSmrg stmt = gsi_stmt (gsi);
711debfc3dSmrg
721debfc3dSmrg if (!stmt)
731debfc3dSmrg continue;
741debfc3dSmrg
751debfc3dSmrg /* A COND_EXPR may create an equivalency in a variety of different
761debfc3dSmrg ways. */
771debfc3dSmrg if (gimple_code (stmt) == GIMPLE_COND)
781debfc3dSmrg {
791debfc3dSmrg edge true_edge;
801debfc3dSmrg edge false_edge;
811debfc3dSmrg struct edge_equivalency *equivalency;
821debfc3dSmrg enum tree_code code = gimple_cond_code (stmt);
831debfc3dSmrg
841debfc3dSmrg extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
851debfc3dSmrg
861debfc3dSmrg /* Equality tests may create one or two equivalences. */
871debfc3dSmrg if (code == EQ_EXPR || code == NE_EXPR)
881debfc3dSmrg {
891debfc3dSmrg tree op0 = gimple_cond_lhs (stmt);
901debfc3dSmrg tree op1 = gimple_cond_rhs (stmt);
911debfc3dSmrg
921debfc3dSmrg /* Special case comparing booleans against a constant as we
931debfc3dSmrg know the value of OP0 on both arms of the branch. i.e., we
941debfc3dSmrg can record an equivalence for OP0 rather than COND. */
951debfc3dSmrg if (TREE_CODE (op0) == SSA_NAME
961debfc3dSmrg && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
971debfc3dSmrg && ssa_name_has_boolean_range (op0)
981debfc3dSmrg && is_gimple_min_invariant (op1)
991debfc3dSmrg && (integer_zerop (op1) || integer_onep (op1)))
1001debfc3dSmrg {
1011debfc3dSmrg tree true_val = constant_boolean_node (true, TREE_TYPE (op0));
1021debfc3dSmrg tree false_val = constant_boolean_node (false,
1031debfc3dSmrg TREE_TYPE (op0));
1041debfc3dSmrg if (code == EQ_EXPR)
1051debfc3dSmrg {
1061debfc3dSmrg equivalency = XNEW (struct edge_equivalency);
1071debfc3dSmrg equivalency->lhs = op0;
1081debfc3dSmrg equivalency->rhs = (integer_zerop (op1)
1091debfc3dSmrg ? false_val
1101debfc3dSmrg : true_val);
1111debfc3dSmrg true_edge->aux = equivalency;
1121debfc3dSmrg
1131debfc3dSmrg equivalency = XNEW (struct edge_equivalency);
1141debfc3dSmrg equivalency->lhs = op0;
1151debfc3dSmrg equivalency->rhs = (integer_zerop (op1)
1161debfc3dSmrg ? true_val
1171debfc3dSmrg : false_val);
1181debfc3dSmrg false_edge->aux = equivalency;
1191debfc3dSmrg }
1201debfc3dSmrg else
1211debfc3dSmrg {
1221debfc3dSmrg equivalency = XNEW (struct edge_equivalency);
1231debfc3dSmrg equivalency->lhs = op0;
1241debfc3dSmrg equivalency->rhs = (integer_zerop (op1)
1251debfc3dSmrg ? true_val
1261debfc3dSmrg : false_val);
1271debfc3dSmrg true_edge->aux = equivalency;
1281debfc3dSmrg
1291debfc3dSmrg equivalency = XNEW (struct edge_equivalency);
1301debfc3dSmrg equivalency->lhs = op0;
1311debfc3dSmrg equivalency->rhs = (integer_zerop (op1)
1321debfc3dSmrg ? false_val
1331debfc3dSmrg : true_val);
1341debfc3dSmrg false_edge->aux = equivalency;
1351debfc3dSmrg }
1361debfc3dSmrg }
1371debfc3dSmrg
1381debfc3dSmrg else if (TREE_CODE (op0) == SSA_NAME
1391debfc3dSmrg && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
1401debfc3dSmrg && (is_gimple_min_invariant (op1)
1411debfc3dSmrg || (TREE_CODE (op1) == SSA_NAME
1421debfc3dSmrg && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))))
1431debfc3dSmrg {
1441debfc3dSmrg /* For IEEE, -0.0 == 0.0, so we don't necessarily know
1451debfc3dSmrg the sign of a variable compared against zero. If
1461debfc3dSmrg we're honoring signed zeros, then we cannot record
1471debfc3dSmrg this value unless we know that the value is nonzero. */
1481debfc3dSmrg if (HONOR_SIGNED_ZEROS (op0)
1491debfc3dSmrg && (TREE_CODE (op1) != REAL_CST
1501debfc3dSmrg || real_equal (&dconst0, &TREE_REAL_CST (op1))))
1511debfc3dSmrg continue;
1521debfc3dSmrg
1531debfc3dSmrg equivalency = XNEW (struct edge_equivalency);
1541debfc3dSmrg equivalency->lhs = op0;
1551debfc3dSmrg equivalency->rhs = op1;
1561debfc3dSmrg if (code == EQ_EXPR)
1571debfc3dSmrg true_edge->aux = equivalency;
1581debfc3dSmrg else
1591debfc3dSmrg false_edge->aux = equivalency;
1601debfc3dSmrg
1611debfc3dSmrg }
1621debfc3dSmrg }
1631debfc3dSmrg
1641debfc3dSmrg /* ??? TRUTH_NOT_EXPR can create an equivalence too. */
1651debfc3dSmrg }
1661debfc3dSmrg
1671debfc3dSmrg /* For a SWITCH_EXPR, a case label which represents a single
1681debfc3dSmrg value and which is the only case label which reaches the
1691debfc3dSmrg target block creates an equivalence. */
1701debfc3dSmrg else if (gimple_code (stmt) == GIMPLE_SWITCH)
1711debfc3dSmrg {
1721debfc3dSmrg gswitch *switch_stmt = as_a <gswitch *> (stmt);
1731debfc3dSmrg tree cond = gimple_switch_index (switch_stmt);
1741debfc3dSmrg
1751debfc3dSmrg if (TREE_CODE (cond) == SSA_NAME
1761debfc3dSmrg && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
1771debfc3dSmrg {
1781debfc3dSmrg int i, n_labels = gimple_switch_num_labels (switch_stmt);
1791debfc3dSmrg tree *info = XCNEWVEC (tree, last_basic_block_for_fn (cfun));
1801debfc3dSmrg
1811debfc3dSmrg /* Walk over the case label vector. Record blocks
1821debfc3dSmrg which are reached by a single case label which represents
1831debfc3dSmrg a single value. */
1841debfc3dSmrg for (i = 0; i < n_labels; i++)
1851debfc3dSmrg {
1861debfc3dSmrg tree label = gimple_switch_label (switch_stmt, i);
187c0a68be4Smrg basic_block bb = label_to_block (cfun, CASE_LABEL (label));
1881debfc3dSmrg
1891debfc3dSmrg if (CASE_HIGH (label)
1901debfc3dSmrg || !CASE_LOW (label)
1911debfc3dSmrg || info[bb->index])
1921debfc3dSmrg info[bb->index] = error_mark_node;
1931debfc3dSmrg else
1941debfc3dSmrg info[bb->index] = label;
1951debfc3dSmrg }
1961debfc3dSmrg
1971debfc3dSmrg /* Now walk over the blocks to determine which ones were
1981debfc3dSmrg marked as being reached by a useful case label. */
1991debfc3dSmrg for (i = 0; i < n_basic_blocks_for_fn (cfun); i++)
2001debfc3dSmrg {
2011debfc3dSmrg tree node = info[i];
2021debfc3dSmrg
2031debfc3dSmrg if (node != NULL
2041debfc3dSmrg && node != error_mark_node)
2051debfc3dSmrg {
2061debfc3dSmrg tree x = fold_convert (TREE_TYPE (cond), CASE_LOW (node));
2071debfc3dSmrg struct edge_equivalency *equivalency;
2081debfc3dSmrg
2091debfc3dSmrg /* Record an equivalency on the edge from BB to basic
2101debfc3dSmrg block I. */
2111debfc3dSmrg equivalency = XNEW (struct edge_equivalency);
2121debfc3dSmrg equivalency->rhs = x;
2131debfc3dSmrg equivalency->lhs = cond;
2141debfc3dSmrg find_edge (bb, BASIC_BLOCK_FOR_FN (cfun, i))->aux =
2151debfc3dSmrg equivalency;
2161debfc3dSmrg }
2171debfc3dSmrg }
2181debfc3dSmrg free (info);
2191debfc3dSmrg }
2201debfc3dSmrg }
2211debfc3dSmrg
2221debfc3dSmrg }
2231debfc3dSmrg }
2241debfc3dSmrg
2251debfc3dSmrg
2261debfc3dSmrg /* Translating out of SSA sometimes requires inserting copies and
2271debfc3dSmrg constant initializations on edges to eliminate PHI nodes.
2281debfc3dSmrg
2291debfc3dSmrg In some cases those copies and constant initializations are
2301debfc3dSmrg redundant because the target already has the value on the
2311debfc3dSmrg RHS of the assignment.
2321debfc3dSmrg
2331debfc3dSmrg We previously tried to catch these cases after translating
2341debfc3dSmrg out of SSA form. However, that code often missed cases. Worse
2351debfc3dSmrg yet, the cases it missed were also often missed by the RTL
2361debfc3dSmrg optimizers. Thus the resulting code had redundant instructions.
2371debfc3dSmrg
2381debfc3dSmrg This pass attempts to detect these situations before translating
2391debfc3dSmrg out of SSA form.
2401debfc3dSmrg
2411debfc3dSmrg The key concept that this pass is built upon is that these
2421debfc3dSmrg redundant copies and constant initializations often occur
2431debfc3dSmrg due to constant/copy propagating equivalences resulting from
2441debfc3dSmrg COND_EXPRs and SWITCH_EXPRs.
2451debfc3dSmrg
2461debfc3dSmrg We want to do those propagations as they can sometimes allow
2471debfc3dSmrg the SSA optimizers to do a better job. However, in the cases
2481debfc3dSmrg where such propagations do not result in further optimization,
2491debfc3dSmrg we would like to "undo" the propagation to avoid the redundant
2501debfc3dSmrg copies and constant initializations.
2511debfc3dSmrg
2521debfc3dSmrg This pass works by first associating equivalences with edges in
2531debfc3dSmrg the CFG. For example, the edge leading from a SWITCH_EXPR to
2541debfc3dSmrg its associated CASE_LABEL will have an equivalency between
2551debfc3dSmrg SWITCH_COND and the value in the case label.
2561debfc3dSmrg
2571debfc3dSmrg Once we have found the edge equivalences, we proceed to walk
2581debfc3dSmrg the CFG in dominator order. As we traverse edges we record
2591debfc3dSmrg equivalences associated with those edges we traverse.
2601debfc3dSmrg
2611debfc3dSmrg When we encounter a PHI node, we walk its arguments to see if we
2621debfc3dSmrg have an equivalence for the PHI argument. If so, then we replace
2631debfc3dSmrg the argument.
2641debfc3dSmrg
2651debfc3dSmrg Equivalences are looked up based on their value (think of it as
2661debfc3dSmrg the RHS of an assignment). A value may be an SSA_NAME or an
2671debfc3dSmrg invariant. We may have several SSA_NAMEs with the same value,
2681debfc3dSmrg so with each value we have a list of SSA_NAMEs that have the
2691debfc3dSmrg same value. */
2701debfc3dSmrg
271c0a68be4Smrg typedef hash_map<tree_operand_hash, auto_vec<tree> > val_ssa_equiv_t;
272a2dc1f3fSmrg
2731debfc3dSmrg /* Global hash table implementing a mapping from invariant values
2741debfc3dSmrg to a list of SSA_NAMEs which have the same value. We might be
2751debfc3dSmrg able to reuse tree-vn for this code. */
276a2dc1f3fSmrg val_ssa_equiv_t *val_ssa_equiv;
2771debfc3dSmrg
2781debfc3dSmrg static void uncprop_into_successor_phis (basic_block);
2791debfc3dSmrg
2801debfc3dSmrg /* Remove the most recently recorded equivalency for VALUE. */
2811debfc3dSmrg
2821debfc3dSmrg static void
remove_equivalence(tree value)2831debfc3dSmrg remove_equivalence (tree value)
2841debfc3dSmrg {
2851debfc3dSmrg val_ssa_equiv->get (value)->pop ();
2861debfc3dSmrg }
2871debfc3dSmrg
2881debfc3dSmrg /* Record EQUIVALENCE = VALUE into our hash table. */
2891debfc3dSmrg
2901debfc3dSmrg static void
record_equiv(tree value,tree equivalence)2911debfc3dSmrg record_equiv (tree value, tree equivalence)
2921debfc3dSmrg {
2931debfc3dSmrg val_ssa_equiv->get_or_insert (value).safe_push (equivalence);
2941debfc3dSmrg }
2951debfc3dSmrg
2961debfc3dSmrg class uncprop_dom_walker : public dom_walker
2971debfc3dSmrg {
2981debfc3dSmrg public:
uncprop_dom_walker(cdi_direction direction)2991debfc3dSmrg uncprop_dom_walker (cdi_direction direction) : dom_walker (direction) {}
3001debfc3dSmrg
3011debfc3dSmrg virtual edge before_dom_children (basic_block);
3021debfc3dSmrg virtual void after_dom_children (basic_block);
3031debfc3dSmrg
3041debfc3dSmrg private:
3051debfc3dSmrg
3061debfc3dSmrg /* As we enter each block we record the value for any edge equivalency
3071debfc3dSmrg leading to this block. If no such edge equivalency exists, then we
3081debfc3dSmrg record NULL. These equivalences are live until we leave the dominator
3091debfc3dSmrg subtree rooted at the block where we record the equivalency. */
3101debfc3dSmrg auto_vec<tree, 2> m_equiv_stack;
3111debfc3dSmrg };
3121debfc3dSmrg
3131debfc3dSmrg /* We have finished processing the dominator children of BB, perform
3141debfc3dSmrg any finalization actions in preparation for leaving this node in
3151debfc3dSmrg the dominator tree. */
3161debfc3dSmrg
3171debfc3dSmrg void
after_dom_children(basic_block bb ATTRIBUTE_UNUSED)3181debfc3dSmrg uncprop_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
3191debfc3dSmrg {
3201debfc3dSmrg /* Pop the topmost value off the equiv stack. */
3211debfc3dSmrg tree value = m_equiv_stack.pop ();
3221debfc3dSmrg
3231debfc3dSmrg /* If that value was non-null, then pop the topmost equivalency off
3241debfc3dSmrg its equivalency stack. */
3251debfc3dSmrg if (value != NULL)
3261debfc3dSmrg remove_equivalence (value);
3271debfc3dSmrg }
3281debfc3dSmrg
3291debfc3dSmrg /* Unpropagate values from PHI nodes in successor blocks of BB. */
3301debfc3dSmrg
3311debfc3dSmrg static void
uncprop_into_successor_phis(basic_block bb)3321debfc3dSmrg uncprop_into_successor_phis (basic_block bb)
3331debfc3dSmrg {
3341debfc3dSmrg edge e;
3351debfc3dSmrg edge_iterator ei;
3361debfc3dSmrg
3371debfc3dSmrg /* For each successor edge, first temporarily record any equivalence
3381debfc3dSmrg on that edge. Then unpropagate values in any PHI nodes at the
3391debfc3dSmrg destination of the edge. Then remove the temporary equivalence. */
3401debfc3dSmrg FOR_EACH_EDGE (e, ei, bb->succs)
3411debfc3dSmrg {
3421debfc3dSmrg gimple_seq phis = phi_nodes (e->dest);
3431debfc3dSmrg gimple_stmt_iterator gsi;
3441debfc3dSmrg
3451debfc3dSmrg /* If there are no PHI nodes in this destination, then there is
3461debfc3dSmrg no sense in recording any equivalences. */
3471debfc3dSmrg if (gimple_seq_empty_p (phis))
3481debfc3dSmrg continue;
3491debfc3dSmrg
3501debfc3dSmrg /* Record any equivalency associated with E. */
3511debfc3dSmrg if (e->aux)
3521debfc3dSmrg {
3531debfc3dSmrg struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
3541debfc3dSmrg record_equiv (equiv->rhs, equiv->lhs);
3551debfc3dSmrg }
3561debfc3dSmrg
3571debfc3dSmrg /* Walk over the PHI nodes, unpropagating values. */
3581debfc3dSmrg for (gsi = gsi_start (phis) ; !gsi_end_p (gsi); gsi_next (&gsi))
3591debfc3dSmrg {
3601debfc3dSmrg gimple *phi = gsi_stmt (gsi);
3611debfc3dSmrg tree arg = PHI_ARG_DEF (phi, e->dest_idx);
3621debfc3dSmrg tree res = PHI_RESULT (phi);
3631debfc3dSmrg
3641debfc3dSmrg /* If the argument is not an invariant and can be potentially
3651debfc3dSmrg coalesced with the result, then there's no point in
3661debfc3dSmrg un-propagating the argument. */
3671debfc3dSmrg if (!is_gimple_min_invariant (arg)
3681debfc3dSmrg && gimple_can_coalesce_p (arg, res))
3691debfc3dSmrg continue;
3701debfc3dSmrg
3711debfc3dSmrg /* Lookup this argument's value in the hash table. */
3721debfc3dSmrg vec<tree> *equivalences = val_ssa_equiv->get (arg);
3731debfc3dSmrg if (equivalences)
3741debfc3dSmrg {
3751debfc3dSmrg /* Walk every equivalence with the same value. If we find
3761debfc3dSmrg one that can potentially coalesce with the PHI rsult,
3771debfc3dSmrg then replace the value in the argument with its equivalent
3781debfc3dSmrg SSA_NAME. Use the most recent equivalence as hopefully
3791debfc3dSmrg that results in shortest lifetimes. */
3801debfc3dSmrg for (int j = equivalences->length () - 1; j >= 0; j--)
3811debfc3dSmrg {
3821debfc3dSmrg tree equiv = (*equivalences)[j];
3831debfc3dSmrg
3841debfc3dSmrg if (gimple_can_coalesce_p (equiv, res))
3851debfc3dSmrg {
3861debfc3dSmrg SET_PHI_ARG_DEF (phi, e->dest_idx, equiv);
3871debfc3dSmrg break;
3881debfc3dSmrg }
3891debfc3dSmrg }
3901debfc3dSmrg }
3911debfc3dSmrg }
3921debfc3dSmrg
3931debfc3dSmrg /* If we had an equivalence associated with this edge, remove it. */
3941debfc3dSmrg if (e->aux)
3951debfc3dSmrg {
3961debfc3dSmrg struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
3971debfc3dSmrg remove_equivalence (equiv->rhs);
3981debfc3dSmrg }
3991debfc3dSmrg }
4001debfc3dSmrg }
4011debfc3dSmrg
4021debfc3dSmrg edge
before_dom_children(basic_block bb)4031debfc3dSmrg uncprop_dom_walker::before_dom_children (basic_block bb)
4041debfc3dSmrg {
4051debfc3dSmrg basic_block parent;
4061debfc3dSmrg bool recorded = false;
4071debfc3dSmrg
4081debfc3dSmrg /* If this block is dominated by a single incoming edge and that edge
4091debfc3dSmrg has an equivalency, then record the equivalency and push the
4101debfc3dSmrg VALUE onto EQUIV_STACK. Else push a NULL entry on EQUIV_STACK. */
4111debfc3dSmrg parent = get_immediate_dominator (CDI_DOMINATORS, bb);
4121debfc3dSmrg if (parent)
4131debfc3dSmrg {
414a2dc1f3fSmrg edge e = single_pred_edge_ignoring_loop_edges (bb, false);
4151debfc3dSmrg
4161debfc3dSmrg if (e && e->src == parent && e->aux)
4171debfc3dSmrg {
4181debfc3dSmrg struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
4191debfc3dSmrg
4201debfc3dSmrg record_equiv (equiv->rhs, equiv->lhs);
4211debfc3dSmrg m_equiv_stack.safe_push (equiv->rhs);
4221debfc3dSmrg recorded = true;
4231debfc3dSmrg }
4241debfc3dSmrg }
4251debfc3dSmrg
4261debfc3dSmrg if (!recorded)
4271debfc3dSmrg m_equiv_stack.safe_push (NULL_TREE);
4281debfc3dSmrg
4291debfc3dSmrg uncprop_into_successor_phis (bb);
4301debfc3dSmrg return NULL;
4311debfc3dSmrg }
4321debfc3dSmrg
4331debfc3dSmrg namespace {
4341debfc3dSmrg
4351debfc3dSmrg const pass_data pass_data_uncprop =
4361debfc3dSmrg {
4371debfc3dSmrg GIMPLE_PASS, /* type */
4381debfc3dSmrg "uncprop", /* name */
4391debfc3dSmrg OPTGROUP_NONE, /* optinfo_flags */
4401debfc3dSmrg TV_TREE_SSA_UNCPROP, /* tv_id */
4411debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
4421debfc3dSmrg 0, /* properties_provided */
4431debfc3dSmrg 0, /* properties_destroyed */
4441debfc3dSmrg 0, /* todo_flags_start */
4451debfc3dSmrg 0, /* todo_flags_finish */
4461debfc3dSmrg };
4471debfc3dSmrg
4481debfc3dSmrg class pass_uncprop : public gimple_opt_pass
4491debfc3dSmrg {
4501debfc3dSmrg public:
pass_uncprop(gcc::context * ctxt)4511debfc3dSmrg pass_uncprop (gcc::context *ctxt)
4521debfc3dSmrg : gimple_opt_pass (pass_data_uncprop, ctxt)
4531debfc3dSmrg {}
4541debfc3dSmrg
4551debfc3dSmrg /* opt_pass methods: */
clone()4561debfc3dSmrg opt_pass * clone () { return new pass_uncprop (m_ctxt); }
gate(function *)4571debfc3dSmrg virtual bool gate (function *) { return flag_tree_dom != 0; }
4581debfc3dSmrg virtual unsigned int execute (function *);
4591debfc3dSmrg
4601debfc3dSmrg }; // class pass_uncprop
4611debfc3dSmrg
4621debfc3dSmrg unsigned int
execute(function * fun)4631debfc3dSmrg pass_uncprop::execute (function *fun)
4641debfc3dSmrg {
4651debfc3dSmrg basic_block bb;
4661debfc3dSmrg
4671debfc3dSmrg associate_equivalences_with_edges ();
4681debfc3dSmrg
4691debfc3dSmrg /* Create our global data structures. */
470a2dc1f3fSmrg val_ssa_equiv = new val_ssa_equiv_t (1024);
4711debfc3dSmrg
4721debfc3dSmrg /* We're going to do a dominator walk, so ensure that we have
4731debfc3dSmrg dominance information. */
4741debfc3dSmrg calculate_dominance_info (CDI_DOMINATORS);
4751debfc3dSmrg
4761debfc3dSmrg /* Recursively walk the dominator tree undoing unprofitable
4771debfc3dSmrg constant/copy propagations. */
4781debfc3dSmrg uncprop_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr);
4791debfc3dSmrg
4801debfc3dSmrg /* we just need to empty elements out of the hash table, and cleanup the
4811debfc3dSmrg AUX field on the edges. */
4821debfc3dSmrg delete val_ssa_equiv;
4831debfc3dSmrg val_ssa_equiv = NULL;
4841debfc3dSmrg FOR_EACH_BB_FN (bb, fun)
4851debfc3dSmrg {
4861debfc3dSmrg edge e;
4871debfc3dSmrg edge_iterator ei;
4881debfc3dSmrg
4891debfc3dSmrg FOR_EACH_EDGE (e, ei, bb->succs)
4901debfc3dSmrg {
4911debfc3dSmrg if (e->aux)
4921debfc3dSmrg {
4931debfc3dSmrg free (e->aux);
4941debfc3dSmrg e->aux = NULL;
4951debfc3dSmrg }
4961debfc3dSmrg }
4971debfc3dSmrg }
4981debfc3dSmrg return 0;
4991debfc3dSmrg }
5001debfc3dSmrg
5011debfc3dSmrg } // anon namespace
5021debfc3dSmrg
5031debfc3dSmrg gimple_opt_pass *
make_pass_uncprop(gcc::context * ctxt)5041debfc3dSmrg make_pass_uncprop (gcc::context *ctxt)
5051debfc3dSmrg {
5061debfc3dSmrg return new pass_uncprop (ctxt);
5071debfc3dSmrg }
508