xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-ssa-uncprop.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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