xref: /dflybsd-src/contrib/gcc-8.0/gcc/tree-ssa-uncprop.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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