xref: /dflybsd-src/contrib/gcc-8.0/gcc/tree-ssa-copy.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Copy propagation and SSA_NAME replacement support routines.
238fd1498Szrj    Copyright (C) 2004-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 "gimple-pretty-print.h"
2938fd1498Szrj #include "fold-const.h"
3038fd1498Szrj #include "gimple-iterator.h"
3138fd1498Szrj #include "tree-cfg.h"
3238fd1498Szrj #include "tree-ssa-propagate.h"
3338fd1498Szrj #include "cfgloop.h"
3438fd1498Szrj #include "tree-scalar-evolution.h"
3538fd1498Szrj #include "tree-ssa-loop-niter.h"
3638fd1498Szrj 
3738fd1498Szrj 
3838fd1498Szrj /* This file implements the copy propagation pass and provides a
3938fd1498Szrj    handful of interfaces for performing const/copy propagation and
4038fd1498Szrj    simple expression replacement which keep variable annotations
4138fd1498Szrj    up-to-date.
4238fd1498Szrj 
4338fd1498Szrj    We require that for any copy operation where the RHS and LHS have
4438fd1498Szrj    a non-null memory tag the memory tag be the same.   It is OK
4538fd1498Szrj    for one or both of the memory tags to be NULL.
4638fd1498Szrj 
4738fd1498Szrj    We also require tracking if a variable is dereferenced in a load or
4838fd1498Szrj    store operation.
4938fd1498Szrj 
5038fd1498Szrj    We enforce these requirements by having all copy propagation and
5138fd1498Szrj    replacements of one SSA_NAME with a different SSA_NAME to use the
5238fd1498Szrj    APIs defined in this file.  */
5338fd1498Szrj 
5438fd1498Szrj /*---------------------------------------------------------------------------
5538fd1498Szrj 				Copy propagation
5638fd1498Szrj ---------------------------------------------------------------------------*/
5738fd1498Szrj /* Lattice for copy-propagation.  The lattice is initialized to
5838fd1498Szrj    UNDEFINED (value == NULL) for SSA names that can become a copy
5938fd1498Szrj    of something or VARYING (value == self) if not (see get_copy_of_val
6038fd1498Szrj    and stmt_may_generate_copy).  Other values make the name a COPY
6138fd1498Szrj    of that value.
6238fd1498Szrj 
6338fd1498Szrj    When visiting a statement or PHI node the lattice value for an
6438fd1498Szrj    SSA name can transition from UNDEFINED to COPY to VARYING.  */
6538fd1498Szrj 
6638fd1498Szrj struct prop_value_t {
6738fd1498Szrj     /* Copy-of value.  */
6838fd1498Szrj     tree value;
6938fd1498Szrj };
7038fd1498Szrj 
7138fd1498Szrj class copy_prop : public ssa_propagation_engine
7238fd1498Szrj {
7338fd1498Szrj  public:
7438fd1498Szrj   enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
7538fd1498Szrj   enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
7638fd1498Szrj };
7738fd1498Szrj 
7838fd1498Szrj static prop_value_t *copy_of;
7938fd1498Szrj static unsigned n_copy_of;
8038fd1498Szrj 
8138fd1498Szrj 
8238fd1498Szrj /* Return true if this statement may generate a useful copy.  */
8338fd1498Szrj 
8438fd1498Szrj static bool
stmt_may_generate_copy(gimple * stmt)8538fd1498Szrj stmt_may_generate_copy (gimple *stmt)
8638fd1498Szrj {
8738fd1498Szrj   if (gimple_code (stmt) == GIMPLE_PHI)
8838fd1498Szrj     return !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (stmt));
8938fd1498Szrj 
9038fd1498Szrj   if (gimple_code (stmt) != GIMPLE_ASSIGN)
9138fd1498Szrj     return false;
9238fd1498Szrj 
9338fd1498Szrj   /* If the statement has volatile operands, it won't generate a
9438fd1498Szrj      useful copy.  */
9538fd1498Szrj   if (gimple_has_volatile_ops (stmt))
9638fd1498Szrj     return false;
9738fd1498Szrj 
9838fd1498Szrj   /* Statements with loads and/or stores will never generate a useful copy.  */
9938fd1498Szrj   if (gimple_vuse (stmt))
10038fd1498Szrj     return false;
10138fd1498Szrj 
10238fd1498Szrj   /* Otherwise, the only statements that generate useful copies are
10338fd1498Szrj      assignments whose RHS is just an SSA name that doesn't flow
10438fd1498Szrj      through abnormal edges.  */
10538fd1498Szrj   return ((gimple_assign_rhs_code (stmt) == SSA_NAME
10638fd1498Szrj 	   && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt)))
10738fd1498Szrj 	  || is_gimple_min_invariant (gimple_assign_rhs1 (stmt)));
10838fd1498Szrj }
10938fd1498Szrj 
11038fd1498Szrj 
11138fd1498Szrj /* Return the copy-of value for VAR.  */
11238fd1498Szrj 
11338fd1498Szrj static inline prop_value_t *
get_copy_of_val(tree var)11438fd1498Szrj get_copy_of_val (tree var)
11538fd1498Szrj {
11638fd1498Szrj   prop_value_t *val = &copy_of[SSA_NAME_VERSION (var)];
11738fd1498Szrj 
11838fd1498Szrj   if (val->value == NULL_TREE
11938fd1498Szrj       && !stmt_may_generate_copy (SSA_NAME_DEF_STMT (var)))
12038fd1498Szrj     {
12138fd1498Szrj       /* If the variable will never generate a useful copy relation,
12238fd1498Szrj 	 make it its own copy.  */
12338fd1498Szrj       val->value = var;
12438fd1498Szrj     }
12538fd1498Szrj 
12638fd1498Szrj   return val;
12738fd1498Szrj }
12838fd1498Szrj 
12938fd1498Szrj /* Return the variable VAR is a copy of or VAR if VAR isn't the result
13038fd1498Szrj    of a copy.  */
13138fd1498Szrj 
13238fd1498Szrj static inline tree
valueize_val(tree var)13338fd1498Szrj valueize_val (tree var)
13438fd1498Szrj {
13538fd1498Szrj   if (TREE_CODE (var) == SSA_NAME)
13638fd1498Szrj     {
13738fd1498Szrj       tree val = get_copy_of_val (var)->value;
13838fd1498Szrj       if (val)
13938fd1498Szrj 	return val;
14038fd1498Szrj     }
14138fd1498Szrj   return var;
14238fd1498Szrj }
14338fd1498Szrj 
14438fd1498Szrj /* Set VAL to be the copy of VAR.  If that changed return true.  */
14538fd1498Szrj 
14638fd1498Szrj static inline bool
set_copy_of_val(tree var,tree val)14738fd1498Szrj set_copy_of_val (tree var, tree val)
14838fd1498Szrj {
14938fd1498Szrj   unsigned int ver = SSA_NAME_VERSION (var);
15038fd1498Szrj   tree old;
15138fd1498Szrj 
15238fd1498Szrj   /* Set FIRST to be the first link in COPY_OF[DEST].  If that
15338fd1498Szrj      changed, return true.  */
15438fd1498Szrj   old = copy_of[ver].value;
15538fd1498Szrj   copy_of[ver].value = val;
15638fd1498Szrj 
15738fd1498Szrj   if (old != val
158*58e805e6Szrj       && (!old || !operand_equal_p (old, val, 0)))
15938fd1498Szrj     return true;
16038fd1498Szrj 
16138fd1498Szrj   return false;
16238fd1498Szrj }
16338fd1498Szrj 
16438fd1498Szrj 
16538fd1498Szrj /* Dump the copy-of value for variable VAR to FILE.  */
16638fd1498Szrj 
16738fd1498Szrj static void
dump_copy_of(FILE * file,tree var)16838fd1498Szrj dump_copy_of (FILE *file, tree var)
16938fd1498Szrj {
17038fd1498Szrj   tree val;
17138fd1498Szrj 
17238fd1498Szrj   print_generic_expr (file, var, dump_flags);
17338fd1498Szrj   if (TREE_CODE (var) != SSA_NAME)
17438fd1498Szrj     return;
17538fd1498Szrj 
17638fd1498Szrj   val = copy_of[SSA_NAME_VERSION (var)].value;
17738fd1498Szrj   fprintf (file, " copy-of chain: ");
17838fd1498Szrj   print_generic_expr (file, var);
17938fd1498Szrj   fprintf (file, " ");
18038fd1498Szrj   if (!val)
18138fd1498Szrj     fprintf (file, "[UNDEFINED]");
18238fd1498Szrj   else if (val == var)
18338fd1498Szrj     fprintf (file, "[NOT A COPY]");
18438fd1498Szrj   else
18538fd1498Szrj     {
18638fd1498Szrj       fprintf (file, "-> ");
18738fd1498Szrj       print_generic_expr (file, val);
18838fd1498Szrj       fprintf (file, " ");
18938fd1498Szrj       fprintf (file, "[COPY]");
19038fd1498Szrj     }
19138fd1498Szrj }
19238fd1498Szrj 
19338fd1498Szrj 
19438fd1498Szrj /* Evaluate the RHS of STMT.  If it produces a valid copy, set the LHS
19538fd1498Szrj    value and store the LHS into *RESULT_P.  */
19638fd1498Szrj 
19738fd1498Szrj static enum ssa_prop_result
copy_prop_visit_assignment(gimple * stmt,tree * result_p)19838fd1498Szrj copy_prop_visit_assignment (gimple *stmt, tree *result_p)
19938fd1498Szrj {
20038fd1498Szrj   tree lhs, rhs;
20138fd1498Szrj 
20238fd1498Szrj   lhs = gimple_assign_lhs (stmt);
20338fd1498Szrj   rhs = valueize_val (gimple_assign_rhs1 (stmt));
20438fd1498Szrj 
20538fd1498Szrj   if (TREE_CODE (lhs) == SSA_NAME)
20638fd1498Szrj     {
20738fd1498Szrj       /* Straight copy between two SSA names.  First, make sure that
20838fd1498Szrj 	 we can propagate the RHS into uses of LHS.  */
20938fd1498Szrj       if (!may_propagate_copy (lhs, rhs))
21038fd1498Szrj 	return SSA_PROP_VARYING;
21138fd1498Szrj 
21238fd1498Szrj       *result_p = lhs;
21338fd1498Szrj       if (set_copy_of_val (*result_p, rhs))
21438fd1498Szrj 	return SSA_PROP_INTERESTING;
21538fd1498Szrj       else
21638fd1498Szrj 	return SSA_PROP_NOT_INTERESTING;
21738fd1498Szrj     }
21838fd1498Szrj 
21938fd1498Szrj   return SSA_PROP_VARYING;
22038fd1498Szrj }
22138fd1498Szrj 
22238fd1498Szrj 
22338fd1498Szrj /* Visit the GIMPLE_COND STMT.  Return SSA_PROP_INTERESTING
22438fd1498Szrj    if it can determine which edge will be taken.  Otherwise, return
22538fd1498Szrj    SSA_PROP_VARYING.  */
22638fd1498Szrj 
22738fd1498Szrj static enum ssa_prop_result
copy_prop_visit_cond_stmt(gimple * stmt,edge * taken_edge_p)22838fd1498Szrj copy_prop_visit_cond_stmt (gimple *stmt, edge *taken_edge_p)
22938fd1498Szrj {
23038fd1498Szrj   enum ssa_prop_result retval = SSA_PROP_VARYING;
23138fd1498Szrj   location_t loc = gimple_location (stmt);
23238fd1498Szrj 
23338fd1498Szrj   tree op0 = valueize_val (gimple_cond_lhs (stmt));
23438fd1498Szrj   tree op1 = valueize_val (gimple_cond_rhs (stmt));
23538fd1498Szrj 
23638fd1498Szrj   /* See if we can determine the predicate's value.  */
23738fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
23838fd1498Szrj     {
23938fd1498Szrj       fprintf (dump_file, "Trying to determine truth value of ");
24038fd1498Szrj       fprintf (dump_file, "predicate ");
24138fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0);
24238fd1498Szrj     }
24338fd1498Szrj 
24438fd1498Szrj   /* Fold COND and see whether we get a useful result.  */
24538fd1498Szrj   tree folded_cond = fold_binary_loc (loc, gimple_cond_code (stmt),
24638fd1498Szrj 				      boolean_type_node, op0, op1);
24738fd1498Szrj   if (folded_cond)
24838fd1498Szrj     {
24938fd1498Szrj       basic_block bb = gimple_bb (stmt);
25038fd1498Szrj       *taken_edge_p = find_taken_edge (bb, folded_cond);
25138fd1498Szrj       if (*taken_edge_p)
25238fd1498Szrj 	retval = SSA_PROP_INTERESTING;
25338fd1498Szrj     }
25438fd1498Szrj 
25538fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS) && *taken_edge_p)
25638fd1498Szrj     fprintf (dump_file, "\nConditional will always take edge %d->%d\n",
25738fd1498Szrj 	     (*taken_edge_p)->src->index, (*taken_edge_p)->dest->index);
25838fd1498Szrj 
25938fd1498Szrj   return retval;
26038fd1498Szrj }
26138fd1498Szrj 
26238fd1498Szrj 
26338fd1498Szrj /* Evaluate statement STMT.  If the statement produces a new output
26438fd1498Szrj    value, return SSA_PROP_INTERESTING and store the SSA_NAME holding
26538fd1498Szrj    the new value in *RESULT_P.
26638fd1498Szrj 
26738fd1498Szrj    If STMT is a conditional branch and we can determine its truth
26838fd1498Szrj    value, set *TAKEN_EDGE_P accordingly.
26938fd1498Szrj 
27038fd1498Szrj    If the new value produced by STMT is varying, return
27138fd1498Szrj    SSA_PROP_VARYING.  */
27238fd1498Szrj 
27338fd1498Szrj enum ssa_prop_result
visit_stmt(gimple * stmt,edge * taken_edge_p,tree * result_p)27438fd1498Szrj copy_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *result_p)
27538fd1498Szrj {
27638fd1498Szrj   enum ssa_prop_result retval;
27738fd1498Szrj 
27838fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
27938fd1498Szrj     {
28038fd1498Szrj       fprintf (dump_file, "\nVisiting statement:\n");
28138fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
28238fd1498Szrj       fprintf (dump_file, "\n");
28338fd1498Szrj     }
28438fd1498Szrj 
28538fd1498Szrj   if (gimple_assign_single_p (stmt)
28638fd1498Szrj       && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
28738fd1498Szrj       && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
28838fd1498Szrj 	  || is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
28938fd1498Szrj     {
29038fd1498Szrj       /* If the statement is a copy assignment, evaluate its RHS to
29138fd1498Szrj 	 see if the lattice value of its output has changed.  */
29238fd1498Szrj       retval = copy_prop_visit_assignment (stmt, result_p);
29338fd1498Szrj     }
29438fd1498Szrj   else if (gimple_code (stmt) == GIMPLE_COND)
29538fd1498Szrj     {
29638fd1498Szrj       /* See if we can determine which edge goes out of a conditional
29738fd1498Szrj 	 jump.  */
29838fd1498Szrj       retval = copy_prop_visit_cond_stmt (stmt, taken_edge_p);
29938fd1498Szrj     }
30038fd1498Szrj   else
30138fd1498Szrj     retval = SSA_PROP_VARYING;
30238fd1498Szrj 
30338fd1498Szrj   if (retval == SSA_PROP_VARYING)
30438fd1498Szrj     {
30538fd1498Szrj       tree def;
30638fd1498Szrj       ssa_op_iter i;
30738fd1498Szrj 
30838fd1498Szrj       /* Any other kind of statement is not interesting for constant
30938fd1498Szrj 	 propagation and, therefore, not worth simulating.  */
31038fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
31138fd1498Szrj 	fprintf (dump_file, "No interesting values produced.\n");
31238fd1498Szrj 
31338fd1498Szrj       /* The assignment is not a copy operation.  Don't visit this
31438fd1498Szrj 	 statement again and mark all the definitions in the statement
31538fd1498Szrj 	 to be copies of nothing.  */
31638fd1498Szrj       FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_ALL_DEFS)
31738fd1498Szrj 	set_copy_of_val (def, def);
31838fd1498Szrj     }
31938fd1498Szrj 
32038fd1498Szrj   return retval;
32138fd1498Szrj }
32238fd1498Szrj 
32338fd1498Szrj 
32438fd1498Szrj /* Visit PHI node PHI.  If all the arguments produce the same value,
32538fd1498Szrj    set it to be the value of the LHS of PHI.  */
32638fd1498Szrj 
32738fd1498Szrj enum ssa_prop_result
visit_phi(gphi * phi)32838fd1498Szrj copy_prop::visit_phi (gphi *phi)
32938fd1498Szrj {
33038fd1498Szrj   enum ssa_prop_result retval;
33138fd1498Szrj   unsigned i;
33238fd1498Szrj   prop_value_t phi_val = { NULL_TREE };
33338fd1498Szrj 
33438fd1498Szrj   tree lhs = gimple_phi_result (phi);
33538fd1498Szrj 
33638fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
33738fd1498Szrj     {
33838fd1498Szrj       fprintf (dump_file, "\nVisiting PHI node: ");
33938fd1498Szrj       print_gimple_stmt (dump_file, phi, 0, dump_flags);
34038fd1498Szrj     }
34138fd1498Szrj 
34238fd1498Szrj   for (i = 0; i < gimple_phi_num_args (phi); i++)
34338fd1498Szrj     {
34438fd1498Szrj       prop_value_t *arg_val;
34538fd1498Szrj       tree arg_value;
34638fd1498Szrj       tree arg = gimple_phi_arg_def (phi, i);
34738fd1498Szrj       edge e = gimple_phi_arg_edge (phi, i);
34838fd1498Szrj 
34938fd1498Szrj       /* We don't care about values flowing through non-executable
35038fd1498Szrj 	 edges.  */
35138fd1498Szrj       if (!(e->flags & EDGE_EXECUTABLE))
35238fd1498Szrj 	continue;
35338fd1498Szrj 
35438fd1498Szrj       /* Names that flow through abnormal edges cannot be used to
35538fd1498Szrj 	 derive copies.  */
35638fd1498Szrj       if (TREE_CODE (arg) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg))
35738fd1498Szrj 	{
35838fd1498Szrj 	  phi_val.value = lhs;
35938fd1498Szrj 	  break;
36038fd1498Szrj 	}
36138fd1498Szrj 
36238fd1498Szrj       if (dump_file && (dump_flags & TDF_DETAILS))
36338fd1498Szrj 	{
36438fd1498Szrj 	  fprintf (dump_file, "\tArgument #%d: ", i);
36538fd1498Szrj 	  dump_copy_of (dump_file, arg);
36638fd1498Szrj 	  fprintf (dump_file, "\n");
36738fd1498Szrj 	}
36838fd1498Szrj 
36938fd1498Szrj       if (TREE_CODE (arg) == SSA_NAME)
37038fd1498Szrj 	{
37138fd1498Szrj 	  arg_val = get_copy_of_val (arg);
37238fd1498Szrj 
37338fd1498Szrj 	  /* If we didn't visit the definition of arg yet treat it as
37438fd1498Szrj 	     UNDEFINED.  This also handles PHI arguments that are the
37538fd1498Szrj 	     same as lhs.  We'll come here again.  */
37638fd1498Szrj 	  if (!arg_val->value)
37738fd1498Szrj 	    continue;
37838fd1498Szrj 
37938fd1498Szrj 	  arg_value = arg_val->value;
38038fd1498Szrj 	}
38138fd1498Szrj       else
38238fd1498Szrj 	arg_value = valueize_val (arg);
38338fd1498Szrj 
38438fd1498Szrj       /* In loop-closed SSA form do not copy-propagate SSA-names across
38538fd1498Szrj 	 loop exit edges.  */
38638fd1498Szrj       if (loops_state_satisfies_p (LOOP_CLOSED_SSA)
38738fd1498Szrj 	  && TREE_CODE (arg_value) == SSA_NAME
38838fd1498Szrj 	  && loop_exit_edge_p (e->src->loop_father, e))
38938fd1498Szrj 	{
39038fd1498Szrj 	  phi_val.value = lhs;
39138fd1498Szrj 	  break;
39238fd1498Szrj 	}
39338fd1498Szrj 
39438fd1498Szrj       /* If the LHS didn't have a value yet, make it a copy of the
39538fd1498Szrj 	 first argument we find.   */
39638fd1498Szrj       if (phi_val.value == NULL_TREE)
39738fd1498Szrj 	{
39838fd1498Szrj 	  phi_val.value = arg_value;
39938fd1498Szrj 	  continue;
40038fd1498Szrj 	}
40138fd1498Szrj 
40238fd1498Szrj       /* If PHI_VAL and ARG don't have a common copy-of chain, then
40338fd1498Szrj 	 this PHI node cannot be a copy operation.  */
40438fd1498Szrj       if (phi_val.value != arg_value
40538fd1498Szrj 	  && !operand_equal_p (phi_val.value, arg_value, 0))
40638fd1498Szrj 	{
40738fd1498Szrj 	  phi_val.value = lhs;
40838fd1498Szrj 	  break;
40938fd1498Szrj 	}
41038fd1498Szrj     }
41138fd1498Szrj 
41238fd1498Szrj   if (phi_val.value
41338fd1498Szrj       && may_propagate_copy (lhs, phi_val.value)
41438fd1498Szrj       && set_copy_of_val (lhs, phi_val.value))
41538fd1498Szrj     retval = (phi_val.value != lhs) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING;
41638fd1498Szrj   else
41738fd1498Szrj     retval = SSA_PROP_NOT_INTERESTING;
41838fd1498Szrj 
41938fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
42038fd1498Szrj     {
42138fd1498Szrj       fprintf (dump_file, "PHI node ");
42238fd1498Szrj       dump_copy_of (dump_file, lhs);
42338fd1498Szrj       fprintf (dump_file, "\nTelling the propagator to ");
42438fd1498Szrj       if (retval == SSA_PROP_INTERESTING)
42538fd1498Szrj 	fprintf (dump_file, "add SSA edges out of this PHI and continue.");
42638fd1498Szrj       else if (retval == SSA_PROP_VARYING)
42738fd1498Szrj 	fprintf (dump_file, "add SSA edges out of this PHI and never visit again.");
42838fd1498Szrj       else
42938fd1498Szrj 	fprintf (dump_file, "do nothing with SSA edges and keep iterating.");
43038fd1498Szrj       fprintf (dump_file, "\n\n");
43138fd1498Szrj     }
43238fd1498Szrj 
43338fd1498Szrj   return retval;
43438fd1498Szrj }
43538fd1498Szrj 
43638fd1498Szrj 
43738fd1498Szrj /* Initialize structures used for copy propagation.  */
43838fd1498Szrj 
43938fd1498Szrj static void
init_copy_prop(void)44038fd1498Szrj init_copy_prop (void)
44138fd1498Szrj {
44238fd1498Szrj   basic_block bb;
44338fd1498Szrj 
44438fd1498Szrj   n_copy_of = num_ssa_names;
44538fd1498Szrj   copy_of = XCNEWVEC (prop_value_t, n_copy_of);
44638fd1498Szrj 
44738fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
44838fd1498Szrj     {
44938fd1498Szrj       for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
45038fd1498Szrj 	   gsi_next (&si))
45138fd1498Szrj 	{
45238fd1498Szrj 	  gimple *stmt = gsi_stmt (si);
45338fd1498Szrj 	  ssa_op_iter iter;
45438fd1498Szrj           tree def;
45538fd1498Szrj 
45638fd1498Szrj 	  /* The only statements that we care about are those that may
45738fd1498Szrj 	     generate useful copies.  We also need to mark conditional
45838fd1498Szrj 	     jumps so that their outgoing edges are added to the work
45938fd1498Szrj 	     lists of the propagator.  */
46038fd1498Szrj 	  if (stmt_ends_bb_p (stmt))
46138fd1498Szrj             prop_set_simulate_again (stmt, true);
46238fd1498Szrj 	  else if (stmt_may_generate_copy (stmt))
46338fd1498Szrj             prop_set_simulate_again (stmt, true);
46438fd1498Szrj 	  else
46538fd1498Szrj             prop_set_simulate_again (stmt, false);
46638fd1498Szrj 
46738fd1498Szrj 	  /* Mark all the outputs of this statement as not being
46838fd1498Szrj 	     the copy of anything.  */
46938fd1498Szrj 	  FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
47038fd1498Szrj             if (!prop_simulate_again_p (stmt))
47138fd1498Szrj 	      set_copy_of_val (def, def);
47238fd1498Szrj 	}
47338fd1498Szrj 
47438fd1498Szrj       for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
47538fd1498Szrj 	   gsi_next (&si))
47638fd1498Szrj 	{
47738fd1498Szrj           gphi *phi = si.phi ();
47838fd1498Szrj           tree def;
47938fd1498Szrj 
48038fd1498Szrj 	  def = gimple_phi_result (phi);
48138fd1498Szrj 	  if (virtual_operand_p (def))
48238fd1498Szrj             prop_set_simulate_again (phi, false);
48338fd1498Szrj 	  else
48438fd1498Szrj             prop_set_simulate_again (phi, true);
48538fd1498Szrj 
48638fd1498Szrj 	  if (!prop_simulate_again_p (phi))
48738fd1498Szrj 	    set_copy_of_val (def, def);
48838fd1498Szrj 	}
48938fd1498Szrj     }
49038fd1498Szrj }
49138fd1498Szrj 
49238fd1498Szrj class copy_folder : public substitute_and_fold_engine
49338fd1498Szrj {
49438fd1498Szrj  public:
49538fd1498Szrj   tree get_value (tree) FINAL OVERRIDE;
49638fd1498Szrj };
49738fd1498Szrj 
49838fd1498Szrj /* Callback for substitute_and_fold to get at the final copy-of values.  */
49938fd1498Szrj 
50038fd1498Szrj tree
50138fd1498Szrj copy_folder::get_value (tree name)
50238fd1498Szrj {
50338fd1498Szrj   tree val;
50438fd1498Szrj   if (SSA_NAME_VERSION (name) >= n_copy_of)
50538fd1498Szrj     return NULL_TREE;
50638fd1498Szrj   val = copy_of[SSA_NAME_VERSION (name)].value;
50738fd1498Szrj   if (val && val != name)
50838fd1498Szrj     return val;
50938fd1498Szrj   return NULL_TREE;
51038fd1498Szrj }
51138fd1498Szrj 
51238fd1498Szrj /* Deallocate memory used in copy propagation and do final
51338fd1498Szrj    substitution.  */
51438fd1498Szrj 
51538fd1498Szrj static bool
51638fd1498Szrj fini_copy_prop (void)
51738fd1498Szrj {
51838fd1498Szrj   unsigned i;
51938fd1498Szrj   tree var;
52038fd1498Szrj 
52138fd1498Szrj   /* Set the final copy-of value for each variable by traversing the
52238fd1498Szrj      copy-of chains.  */
52338fd1498Szrj   FOR_EACH_SSA_NAME (i, var, cfun)
52438fd1498Szrj     {
52538fd1498Szrj       if (!copy_of[i].value
52638fd1498Szrj 	  || copy_of[i].value == var)
52738fd1498Szrj 	continue;
52838fd1498Szrj 
52938fd1498Szrj       /* In theory the points-to solution of all members of the
53038fd1498Szrj          copy chain is their intersection.  For now we do not bother
53138fd1498Szrj 	 to compute this but only make sure we do not lose points-to
53238fd1498Szrj 	 information completely by setting the points-to solution
53338fd1498Szrj 	 of the representative to the first solution we find if
53438fd1498Szrj 	 it doesn't have one already.  */
53538fd1498Szrj       if (copy_of[i].value != var
53638fd1498Szrj 	  && TREE_CODE (copy_of[i].value) == SSA_NAME)
53738fd1498Szrj 	{
53838fd1498Szrj 	  basic_block copy_of_bb
53938fd1498Szrj 	    = gimple_bb (SSA_NAME_DEF_STMT (copy_of[i].value));
54038fd1498Szrj 	  basic_block var_bb = gimple_bb (SSA_NAME_DEF_STMT (var));
54138fd1498Szrj 	  if (POINTER_TYPE_P (TREE_TYPE (var))
54238fd1498Szrj 	      && SSA_NAME_PTR_INFO (var)
54338fd1498Szrj 	      && !SSA_NAME_PTR_INFO (copy_of[i].value))
54438fd1498Szrj 	    {
54538fd1498Szrj 	      duplicate_ssa_name_ptr_info (copy_of[i].value,
54638fd1498Szrj 					   SSA_NAME_PTR_INFO (var));
54738fd1498Szrj 	      /* Points-to information is cfg insensitive,
54838fd1498Szrj 		 but alignment info might be cfg sensitive, if it
54938fd1498Szrj 		 e.g. is derived from VRP derived non-zero bits.
55038fd1498Szrj 		 So, do not copy alignment info if the two SSA_NAMEs
55138fd1498Szrj 		 aren't defined in the same basic block.  */
55238fd1498Szrj 	      if (var_bb != copy_of_bb)
55338fd1498Szrj 		mark_ptr_info_alignment_unknown
55438fd1498Szrj 				(SSA_NAME_PTR_INFO (copy_of[i].value));
55538fd1498Szrj 	    }
55638fd1498Szrj 	  else if (!POINTER_TYPE_P (TREE_TYPE (var))
55738fd1498Szrj 		   && SSA_NAME_RANGE_INFO (var)
55838fd1498Szrj 		   && !SSA_NAME_RANGE_INFO (copy_of[i].value)
55938fd1498Szrj 		   && var_bb == copy_of_bb)
56038fd1498Szrj 	    duplicate_ssa_name_range_info (copy_of[i].value,
56138fd1498Szrj 					   SSA_NAME_RANGE_TYPE (var),
56238fd1498Szrj 					   SSA_NAME_RANGE_INFO (var));
56338fd1498Szrj 	}
56438fd1498Szrj     }
56538fd1498Szrj 
56638fd1498Szrj   class copy_folder copy_folder;
56738fd1498Szrj   bool changed = copy_folder.substitute_and_fold ();
56838fd1498Szrj   if (changed)
56938fd1498Szrj     {
57038fd1498Szrj       free_numbers_of_iterations_estimates (cfun);
57138fd1498Szrj       if (scev_initialized_p ())
57238fd1498Szrj 	scev_reset ();
57338fd1498Szrj     }
57438fd1498Szrj 
57538fd1498Szrj   free (copy_of);
57638fd1498Szrj 
57738fd1498Szrj   return changed;
57838fd1498Szrj }
57938fd1498Szrj 
58038fd1498Szrj 
58138fd1498Szrj /* Main entry point to the copy propagator.
58238fd1498Szrj 
58338fd1498Szrj    PHIS_ONLY is true if we should only consider PHI nodes as generating
58438fd1498Szrj    copy propagation opportunities.
58538fd1498Szrj 
58638fd1498Szrj    The algorithm propagates the value COPY-OF using ssa_propagate.  For
58738fd1498Szrj    every variable X_i, COPY-OF(X_i) indicates which variable is X_i created
58838fd1498Szrj    from.  The following example shows how the algorithm proceeds at a
58938fd1498Szrj    high level:
59038fd1498Szrj 
59138fd1498Szrj 	    1	a_24 = x_1
59238fd1498Szrj 	    2	a_2 = PHI <a_24, x_1>
59338fd1498Szrj 	    3	a_5 = PHI <a_2>
59438fd1498Szrj 	    4	x_1 = PHI <x_298, a_5, a_2>
59538fd1498Szrj 
59638fd1498Szrj    The end result should be that a_2, a_5, a_24 and x_1 are a copy of
59738fd1498Szrj    x_298.  Propagation proceeds as follows.
59838fd1498Szrj 
59938fd1498Szrj    Visit #1: a_24 is copy-of x_1.  Value changed.
60038fd1498Szrj    Visit #2: a_2 is copy-of x_1.  Value changed.
60138fd1498Szrj    Visit #3: a_5 is copy-of x_1.  Value changed.
60238fd1498Szrj    Visit #4: x_1 is copy-of x_298.  Value changed.
60338fd1498Szrj    Visit #1: a_24 is copy-of x_298.  Value changed.
60438fd1498Szrj    Visit #2: a_2 is copy-of x_298.  Value changed.
60538fd1498Szrj    Visit #3: a_5 is copy-of x_298.  Value changed.
60638fd1498Szrj    Visit #4: x_1 is copy-of x_298.  Stable state reached.
60738fd1498Szrj 
60838fd1498Szrj    When visiting PHI nodes, we only consider arguments that flow
60938fd1498Szrj    through edges marked executable by the propagation engine.  So,
61038fd1498Szrj    when visiting statement #2 for the first time, we will only look at
61138fd1498Szrj    the first argument (a_24) and optimistically assume that its value
61238fd1498Szrj    is the copy of a_24 (x_1).  */
61338fd1498Szrj 
61438fd1498Szrj static unsigned int
61538fd1498Szrj execute_copy_prop (void)
61638fd1498Szrj {
61738fd1498Szrj   init_copy_prop ();
61838fd1498Szrj   class copy_prop copy_prop;
61938fd1498Szrj   copy_prop.ssa_propagate ();
62038fd1498Szrj   if (fini_copy_prop ())
62138fd1498Szrj     return TODO_cleanup_cfg;
62238fd1498Szrj   return 0;
62338fd1498Szrj }
62438fd1498Szrj 
62538fd1498Szrj namespace {
62638fd1498Szrj 
62738fd1498Szrj const pass_data pass_data_copy_prop =
62838fd1498Szrj {
62938fd1498Szrj   GIMPLE_PASS, /* type */
63038fd1498Szrj   "copyprop", /* name */
63138fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
63238fd1498Szrj   TV_TREE_COPY_PROP, /* tv_id */
63338fd1498Szrj   ( PROP_ssa | PROP_cfg ), /* properties_required */
63438fd1498Szrj   0, /* properties_provided */
63538fd1498Szrj   0, /* properties_destroyed */
63638fd1498Szrj   0, /* todo_flags_start */
63738fd1498Szrj   0, /* todo_flags_finish */
63838fd1498Szrj };
63938fd1498Szrj 
64038fd1498Szrj class pass_copy_prop : public gimple_opt_pass
64138fd1498Szrj {
64238fd1498Szrj public:
64338fd1498Szrj   pass_copy_prop (gcc::context *ctxt)
64438fd1498Szrj     : gimple_opt_pass (pass_data_copy_prop, ctxt)
64538fd1498Szrj   {}
64638fd1498Szrj 
64738fd1498Szrj   /* opt_pass methods: */
64838fd1498Szrj   opt_pass * clone () { return new pass_copy_prop (m_ctxt); }
64938fd1498Szrj   virtual bool gate (function *) { return flag_tree_copy_prop != 0; }
65038fd1498Szrj   virtual unsigned int execute (function *) { return execute_copy_prop (); }
65138fd1498Szrj 
65238fd1498Szrj }; // class pass_copy_prop
65338fd1498Szrj 
65438fd1498Szrj } // anon namespace
65538fd1498Szrj 
65638fd1498Szrj gimple_opt_pass *
65738fd1498Szrj make_pass_copy_prop (gcc::context *ctxt)
65838fd1498Szrj {
65938fd1498Szrj   return new pass_copy_prop (ctxt);
66038fd1498Szrj }
661