xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-ssa-copy.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Copy propagation and SSA_NAME replacement support routines.
2*8feb0f0bSmrg    Copyright (C) 2004-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 "gimple-pretty-print.h"
291debfc3dSmrg #include "fold-const.h"
301debfc3dSmrg #include "gimple-iterator.h"
311debfc3dSmrg #include "tree-cfg.h"
321debfc3dSmrg #include "tree-ssa-propagate.h"
331debfc3dSmrg #include "cfgloop.h"
341debfc3dSmrg #include "tree-scalar-evolution.h"
351debfc3dSmrg #include "tree-ssa-loop-niter.h"
361debfc3dSmrg 
371debfc3dSmrg 
381debfc3dSmrg /* This file implements the copy propagation pass and provides a
391debfc3dSmrg    handful of interfaces for performing const/copy propagation and
401debfc3dSmrg    simple expression replacement which keep variable annotations
411debfc3dSmrg    up-to-date.
421debfc3dSmrg 
431debfc3dSmrg    We require that for any copy operation where the RHS and LHS have
441debfc3dSmrg    a non-null memory tag the memory tag be the same.   It is OK
451debfc3dSmrg    for one or both of the memory tags to be NULL.
461debfc3dSmrg 
471debfc3dSmrg    We also require tracking if a variable is dereferenced in a load or
481debfc3dSmrg    store operation.
491debfc3dSmrg 
501debfc3dSmrg    We enforce these requirements by having all copy propagation and
511debfc3dSmrg    replacements of one SSA_NAME with a different SSA_NAME to use the
521debfc3dSmrg    APIs defined in this file.  */
531debfc3dSmrg 
541debfc3dSmrg /*---------------------------------------------------------------------------
551debfc3dSmrg 				Copy propagation
561debfc3dSmrg ---------------------------------------------------------------------------*/
571debfc3dSmrg /* Lattice for copy-propagation.  The lattice is initialized to
581debfc3dSmrg    UNDEFINED (value == NULL) for SSA names that can become a copy
591debfc3dSmrg    of something or VARYING (value == self) if not (see get_copy_of_val
601debfc3dSmrg    and stmt_may_generate_copy).  Other values make the name a COPY
611debfc3dSmrg    of that value.
621debfc3dSmrg 
631debfc3dSmrg    When visiting a statement or PHI node the lattice value for an
641debfc3dSmrg    SSA name can transition from UNDEFINED to COPY to VARYING.  */
651debfc3dSmrg 
661debfc3dSmrg struct prop_value_t {
671debfc3dSmrg     /* Copy-of value.  */
681debfc3dSmrg     tree value;
691debfc3dSmrg };
701debfc3dSmrg 
71a2dc1f3fSmrg class copy_prop : public ssa_propagation_engine
72a2dc1f3fSmrg {
73a2dc1f3fSmrg  public:
74a2dc1f3fSmrg   enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
75a2dc1f3fSmrg   enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
76a2dc1f3fSmrg };
77a2dc1f3fSmrg 
781debfc3dSmrg static prop_value_t *copy_of;
791debfc3dSmrg static unsigned n_copy_of;
801debfc3dSmrg 
811debfc3dSmrg 
821debfc3dSmrg /* Return true if this statement may generate a useful copy.  */
831debfc3dSmrg 
841debfc3dSmrg static bool
stmt_may_generate_copy(gimple * stmt)851debfc3dSmrg stmt_may_generate_copy (gimple *stmt)
861debfc3dSmrg {
871debfc3dSmrg   if (gimple_code (stmt) == GIMPLE_PHI)
881debfc3dSmrg     return !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (stmt));
891debfc3dSmrg 
901debfc3dSmrg   if (gimple_code (stmt) != GIMPLE_ASSIGN)
911debfc3dSmrg     return false;
921debfc3dSmrg 
931debfc3dSmrg   /* If the statement has volatile operands, it won't generate a
941debfc3dSmrg      useful copy.  */
951debfc3dSmrg   if (gimple_has_volatile_ops (stmt))
961debfc3dSmrg     return false;
971debfc3dSmrg 
981debfc3dSmrg   /* Statements with loads and/or stores will never generate a useful copy.  */
991debfc3dSmrg   if (gimple_vuse (stmt))
1001debfc3dSmrg     return false;
1011debfc3dSmrg 
1021debfc3dSmrg   /* Otherwise, the only statements that generate useful copies are
1031debfc3dSmrg      assignments whose RHS is just an SSA name that doesn't flow
1041debfc3dSmrg      through abnormal edges.  */
1051debfc3dSmrg   return ((gimple_assign_rhs_code (stmt) == SSA_NAME
1061debfc3dSmrg 	   && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt)))
1071debfc3dSmrg 	  || is_gimple_min_invariant (gimple_assign_rhs1 (stmt)));
1081debfc3dSmrg }
1091debfc3dSmrg 
1101debfc3dSmrg 
1111debfc3dSmrg /* Return the copy-of value for VAR.  */
1121debfc3dSmrg 
1131debfc3dSmrg static inline prop_value_t *
get_copy_of_val(tree var)1141debfc3dSmrg get_copy_of_val (tree var)
1151debfc3dSmrg {
1161debfc3dSmrg   prop_value_t *val = &copy_of[SSA_NAME_VERSION (var)];
1171debfc3dSmrg 
1181debfc3dSmrg   if (val->value == NULL_TREE
1191debfc3dSmrg       && !stmt_may_generate_copy (SSA_NAME_DEF_STMT (var)))
1201debfc3dSmrg     {
1211debfc3dSmrg       /* If the variable will never generate a useful copy relation,
1221debfc3dSmrg 	 make it its own copy.  */
1231debfc3dSmrg       val->value = var;
1241debfc3dSmrg     }
1251debfc3dSmrg 
1261debfc3dSmrg   return val;
1271debfc3dSmrg }
1281debfc3dSmrg 
1291debfc3dSmrg /* Return the variable VAR is a copy of or VAR if VAR isn't the result
1301debfc3dSmrg    of a copy.  */
1311debfc3dSmrg 
1321debfc3dSmrg static inline tree
valueize_val(tree var)1331debfc3dSmrg valueize_val (tree var)
1341debfc3dSmrg {
1351debfc3dSmrg   if (TREE_CODE (var) == SSA_NAME)
1361debfc3dSmrg     {
1371debfc3dSmrg       tree val = get_copy_of_val (var)->value;
1381debfc3dSmrg       if (val)
1391debfc3dSmrg 	return val;
1401debfc3dSmrg     }
1411debfc3dSmrg   return var;
1421debfc3dSmrg }
1431debfc3dSmrg 
1441debfc3dSmrg /* Set VAL to be the copy of VAR.  If that changed return true.  */
1451debfc3dSmrg 
1461debfc3dSmrg static inline bool
set_copy_of_val(tree var,tree val)1471debfc3dSmrg set_copy_of_val (tree var, tree val)
1481debfc3dSmrg {
1491debfc3dSmrg   unsigned int ver = SSA_NAME_VERSION (var);
1501debfc3dSmrg   tree old;
1511debfc3dSmrg 
1521debfc3dSmrg   /* Set FIRST to be the first link in COPY_OF[DEST].  If that
1531debfc3dSmrg      changed, return true.  */
1541debfc3dSmrg   old = copy_of[ver].value;
1551debfc3dSmrg   copy_of[ver].value = val;
1561debfc3dSmrg 
1571debfc3dSmrg   if (old != val
158a2dc1f3fSmrg       && (!old || !operand_equal_p (old, val, 0)))
1591debfc3dSmrg     return true;
1601debfc3dSmrg 
1611debfc3dSmrg   return false;
1621debfc3dSmrg }
1631debfc3dSmrg 
1641debfc3dSmrg 
1651debfc3dSmrg /* Dump the copy-of value for variable VAR to FILE.  */
1661debfc3dSmrg 
1671debfc3dSmrg static void
dump_copy_of(FILE * file,tree var)1681debfc3dSmrg dump_copy_of (FILE *file, tree var)
1691debfc3dSmrg {
1701debfc3dSmrg   tree val;
1711debfc3dSmrg 
1721debfc3dSmrg   print_generic_expr (file, var, dump_flags);
1731debfc3dSmrg   if (TREE_CODE (var) != SSA_NAME)
1741debfc3dSmrg     return;
1751debfc3dSmrg 
1761debfc3dSmrg   val = copy_of[SSA_NAME_VERSION (var)].value;
1771debfc3dSmrg   fprintf (file, " copy-of chain: ");
178a2dc1f3fSmrg   print_generic_expr (file, var);
1791debfc3dSmrg   fprintf (file, " ");
1801debfc3dSmrg   if (!val)
1811debfc3dSmrg     fprintf (file, "[UNDEFINED]");
1821debfc3dSmrg   else if (val == var)
1831debfc3dSmrg     fprintf (file, "[NOT A COPY]");
1841debfc3dSmrg   else
1851debfc3dSmrg     {
1861debfc3dSmrg       fprintf (file, "-> ");
187a2dc1f3fSmrg       print_generic_expr (file, val);
1881debfc3dSmrg       fprintf (file, " ");
1891debfc3dSmrg       fprintf (file, "[COPY]");
1901debfc3dSmrg     }
1911debfc3dSmrg }
1921debfc3dSmrg 
1931debfc3dSmrg 
1941debfc3dSmrg /* Evaluate the RHS of STMT.  If it produces a valid copy, set the LHS
1951debfc3dSmrg    value and store the LHS into *RESULT_P.  */
1961debfc3dSmrg 
1971debfc3dSmrg static enum ssa_prop_result
copy_prop_visit_assignment(gimple * stmt,tree * result_p)1981debfc3dSmrg copy_prop_visit_assignment (gimple *stmt, tree *result_p)
1991debfc3dSmrg {
2001debfc3dSmrg   tree lhs, rhs;
2011debfc3dSmrg 
2021debfc3dSmrg   lhs = gimple_assign_lhs (stmt);
2031debfc3dSmrg   rhs = valueize_val (gimple_assign_rhs1 (stmt));
2041debfc3dSmrg 
2051debfc3dSmrg   if (TREE_CODE (lhs) == SSA_NAME)
2061debfc3dSmrg     {
2071debfc3dSmrg       /* Straight copy between two SSA names.  First, make sure that
2081debfc3dSmrg 	 we can propagate the RHS into uses of LHS.  */
2091debfc3dSmrg       if (!may_propagate_copy (lhs, rhs))
2101debfc3dSmrg 	return SSA_PROP_VARYING;
2111debfc3dSmrg 
2121debfc3dSmrg       *result_p = lhs;
2131debfc3dSmrg       if (set_copy_of_val (*result_p, rhs))
2141debfc3dSmrg 	return SSA_PROP_INTERESTING;
2151debfc3dSmrg       else
2161debfc3dSmrg 	return SSA_PROP_NOT_INTERESTING;
2171debfc3dSmrg     }
2181debfc3dSmrg 
2191debfc3dSmrg   return SSA_PROP_VARYING;
2201debfc3dSmrg }
2211debfc3dSmrg 
2221debfc3dSmrg 
2231debfc3dSmrg /* Visit the GIMPLE_COND STMT.  Return SSA_PROP_INTERESTING
2241debfc3dSmrg    if it can determine which edge will be taken.  Otherwise, return
2251debfc3dSmrg    SSA_PROP_VARYING.  */
2261debfc3dSmrg 
2271debfc3dSmrg static enum ssa_prop_result
copy_prop_visit_cond_stmt(gimple * stmt,edge * taken_edge_p)2281debfc3dSmrg copy_prop_visit_cond_stmt (gimple *stmt, edge *taken_edge_p)
2291debfc3dSmrg {
2301debfc3dSmrg   enum ssa_prop_result retval = SSA_PROP_VARYING;
2311debfc3dSmrg   location_t loc = gimple_location (stmt);
2321debfc3dSmrg 
2331debfc3dSmrg   tree op0 = valueize_val (gimple_cond_lhs (stmt));
2341debfc3dSmrg   tree op1 = valueize_val (gimple_cond_rhs (stmt));
2351debfc3dSmrg 
2361debfc3dSmrg   /* See if we can determine the predicate's value.  */
2371debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
2381debfc3dSmrg     {
2391debfc3dSmrg       fprintf (dump_file, "Trying to determine truth value of ");
2401debfc3dSmrg       fprintf (dump_file, "predicate ");
241a2dc1f3fSmrg       print_gimple_stmt (dump_file, stmt, 0);
2421debfc3dSmrg     }
2431debfc3dSmrg 
2441debfc3dSmrg   /* Fold COND and see whether we get a useful result.  */
2451debfc3dSmrg   tree folded_cond = fold_binary_loc (loc, gimple_cond_code (stmt),
2461debfc3dSmrg 				      boolean_type_node, op0, op1);
2471debfc3dSmrg   if (folded_cond)
2481debfc3dSmrg     {
2491debfc3dSmrg       basic_block bb = gimple_bb (stmt);
2501debfc3dSmrg       *taken_edge_p = find_taken_edge (bb, folded_cond);
2511debfc3dSmrg       if (*taken_edge_p)
2521debfc3dSmrg 	retval = SSA_PROP_INTERESTING;
2531debfc3dSmrg     }
2541debfc3dSmrg 
2551debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS) && *taken_edge_p)
2561debfc3dSmrg     fprintf (dump_file, "\nConditional will always take edge %d->%d\n",
2571debfc3dSmrg 	     (*taken_edge_p)->src->index, (*taken_edge_p)->dest->index);
2581debfc3dSmrg 
2591debfc3dSmrg   return retval;
2601debfc3dSmrg }
2611debfc3dSmrg 
2621debfc3dSmrg 
2631debfc3dSmrg /* Evaluate statement STMT.  If the statement produces a new output
2641debfc3dSmrg    value, return SSA_PROP_INTERESTING and store the SSA_NAME holding
2651debfc3dSmrg    the new value in *RESULT_P.
2661debfc3dSmrg 
2671debfc3dSmrg    If STMT is a conditional branch and we can determine its truth
2681debfc3dSmrg    value, set *TAKEN_EDGE_P accordingly.
2691debfc3dSmrg 
2701debfc3dSmrg    If the new value produced by STMT is varying, return
2711debfc3dSmrg    SSA_PROP_VARYING.  */
2721debfc3dSmrg 
273a2dc1f3fSmrg enum ssa_prop_result
visit_stmt(gimple * stmt,edge * taken_edge_p,tree * result_p)274a2dc1f3fSmrg copy_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *result_p)
2751debfc3dSmrg {
2761debfc3dSmrg   enum ssa_prop_result retval;
2771debfc3dSmrg 
2781debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
2791debfc3dSmrg     {
2801debfc3dSmrg       fprintf (dump_file, "\nVisiting statement:\n");
2811debfc3dSmrg       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
2821debfc3dSmrg       fprintf (dump_file, "\n");
2831debfc3dSmrg     }
2841debfc3dSmrg 
2851debfc3dSmrg   if (gimple_assign_single_p (stmt)
2861debfc3dSmrg       && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
2871debfc3dSmrg       && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
2881debfc3dSmrg 	  || is_gimple_min_invariant (gimple_assign_rhs1 (stmt))))
2891debfc3dSmrg     {
2901debfc3dSmrg       /* If the statement is a copy assignment, evaluate its RHS to
2911debfc3dSmrg 	 see if the lattice value of its output has changed.  */
2921debfc3dSmrg       retval = copy_prop_visit_assignment (stmt, result_p);
2931debfc3dSmrg     }
2941debfc3dSmrg   else if (gimple_code (stmt) == GIMPLE_COND)
2951debfc3dSmrg     {
2961debfc3dSmrg       /* See if we can determine which edge goes out of a conditional
2971debfc3dSmrg 	 jump.  */
2981debfc3dSmrg       retval = copy_prop_visit_cond_stmt (stmt, taken_edge_p);
2991debfc3dSmrg     }
3001debfc3dSmrg   else
3011debfc3dSmrg     retval = SSA_PROP_VARYING;
3021debfc3dSmrg 
3031debfc3dSmrg   if (retval == SSA_PROP_VARYING)
3041debfc3dSmrg     {
3051debfc3dSmrg       tree def;
3061debfc3dSmrg       ssa_op_iter i;
3071debfc3dSmrg 
3081debfc3dSmrg       /* Any other kind of statement is not interesting for constant
3091debfc3dSmrg 	 propagation and, therefore, not worth simulating.  */
3101debfc3dSmrg       if (dump_file && (dump_flags & TDF_DETAILS))
3111debfc3dSmrg 	fprintf (dump_file, "No interesting values produced.\n");
3121debfc3dSmrg 
3131debfc3dSmrg       /* The assignment is not a copy operation.  Don't visit this
3141debfc3dSmrg 	 statement again and mark all the definitions in the statement
3151debfc3dSmrg 	 to be copies of nothing.  */
3161debfc3dSmrg       FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_ALL_DEFS)
3171debfc3dSmrg 	set_copy_of_val (def, def);
3181debfc3dSmrg     }
3191debfc3dSmrg 
3201debfc3dSmrg   return retval;
3211debfc3dSmrg }
3221debfc3dSmrg 
3231debfc3dSmrg 
3241debfc3dSmrg /* Visit PHI node PHI.  If all the arguments produce the same value,
3251debfc3dSmrg    set it to be the value of the LHS of PHI.  */
3261debfc3dSmrg 
327a2dc1f3fSmrg enum ssa_prop_result
visit_phi(gphi * phi)328a2dc1f3fSmrg copy_prop::visit_phi (gphi *phi)
3291debfc3dSmrg {
3301debfc3dSmrg   enum ssa_prop_result retval;
3311debfc3dSmrg   unsigned i;
3321debfc3dSmrg   prop_value_t phi_val = { NULL_TREE };
3331debfc3dSmrg 
3341debfc3dSmrg   tree lhs = gimple_phi_result (phi);
3351debfc3dSmrg 
3361debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
3371debfc3dSmrg     {
3381debfc3dSmrg       fprintf (dump_file, "\nVisiting PHI node: ");
3391debfc3dSmrg       print_gimple_stmt (dump_file, phi, 0, dump_flags);
3401debfc3dSmrg     }
3411debfc3dSmrg 
3421debfc3dSmrg   for (i = 0; i < gimple_phi_num_args (phi); i++)
3431debfc3dSmrg     {
3441debfc3dSmrg       prop_value_t *arg_val;
3451debfc3dSmrg       tree arg_value;
3461debfc3dSmrg       tree arg = gimple_phi_arg_def (phi, i);
3471debfc3dSmrg       edge e = gimple_phi_arg_edge (phi, i);
3481debfc3dSmrg 
3491debfc3dSmrg       /* We don't care about values flowing through non-executable
3501debfc3dSmrg 	 edges.  */
3511debfc3dSmrg       if (!(e->flags & EDGE_EXECUTABLE))
3521debfc3dSmrg 	continue;
3531debfc3dSmrg 
3541debfc3dSmrg       /* Names that flow through abnormal edges cannot be used to
3551debfc3dSmrg 	 derive copies.  */
3561debfc3dSmrg       if (TREE_CODE (arg) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg))
3571debfc3dSmrg 	{
3581debfc3dSmrg 	  phi_val.value = lhs;
3591debfc3dSmrg 	  break;
3601debfc3dSmrg 	}
3611debfc3dSmrg 
3621debfc3dSmrg       if (dump_file && (dump_flags & TDF_DETAILS))
3631debfc3dSmrg 	{
3641debfc3dSmrg 	  fprintf (dump_file, "\tArgument #%d: ", i);
3651debfc3dSmrg 	  dump_copy_of (dump_file, arg);
3661debfc3dSmrg 	  fprintf (dump_file, "\n");
3671debfc3dSmrg 	}
3681debfc3dSmrg 
3691debfc3dSmrg       if (TREE_CODE (arg) == SSA_NAME)
3701debfc3dSmrg 	{
3711debfc3dSmrg 	  arg_val = get_copy_of_val (arg);
3721debfc3dSmrg 
3731debfc3dSmrg 	  /* If we didn't visit the definition of arg yet treat it as
3741debfc3dSmrg 	     UNDEFINED.  This also handles PHI arguments that are the
3751debfc3dSmrg 	     same as lhs.  We'll come here again.  */
3761debfc3dSmrg 	  if (!arg_val->value)
3771debfc3dSmrg 	    continue;
3781debfc3dSmrg 
3791debfc3dSmrg 	  arg_value = arg_val->value;
3801debfc3dSmrg 	}
3811debfc3dSmrg       else
3821debfc3dSmrg 	arg_value = valueize_val (arg);
3831debfc3dSmrg 
3841debfc3dSmrg       /* In loop-closed SSA form do not copy-propagate SSA-names across
3851debfc3dSmrg 	 loop exit edges.  */
3861debfc3dSmrg       if (loops_state_satisfies_p (LOOP_CLOSED_SSA)
3871debfc3dSmrg 	  && TREE_CODE (arg_value) == SSA_NAME
3881debfc3dSmrg 	  && loop_exit_edge_p (e->src->loop_father, e))
3891debfc3dSmrg 	{
3901debfc3dSmrg 	  phi_val.value = lhs;
3911debfc3dSmrg 	  break;
3921debfc3dSmrg 	}
3931debfc3dSmrg 
3941debfc3dSmrg       /* If the LHS didn't have a value yet, make it a copy of the
3951debfc3dSmrg 	 first argument we find.   */
3961debfc3dSmrg       if (phi_val.value == NULL_TREE)
3971debfc3dSmrg 	{
3981debfc3dSmrg 	  phi_val.value = arg_value;
3991debfc3dSmrg 	  continue;
4001debfc3dSmrg 	}
4011debfc3dSmrg 
4021debfc3dSmrg       /* If PHI_VAL and ARG don't have a common copy-of chain, then
4031debfc3dSmrg 	 this PHI node cannot be a copy operation.  */
4041debfc3dSmrg       if (phi_val.value != arg_value
4051debfc3dSmrg 	  && !operand_equal_p (phi_val.value, arg_value, 0))
4061debfc3dSmrg 	{
4071debfc3dSmrg 	  phi_val.value = lhs;
4081debfc3dSmrg 	  break;
4091debfc3dSmrg 	}
4101debfc3dSmrg     }
4111debfc3dSmrg 
4121debfc3dSmrg   if (phi_val.value
4131debfc3dSmrg       && may_propagate_copy (lhs, phi_val.value)
4141debfc3dSmrg       && set_copy_of_val (lhs, phi_val.value))
4151debfc3dSmrg     retval = (phi_val.value != lhs) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING;
4161debfc3dSmrg   else
4171debfc3dSmrg     retval = SSA_PROP_NOT_INTERESTING;
4181debfc3dSmrg 
4191debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
4201debfc3dSmrg     {
4211debfc3dSmrg       fprintf (dump_file, "PHI node ");
4221debfc3dSmrg       dump_copy_of (dump_file, lhs);
4231debfc3dSmrg       fprintf (dump_file, "\nTelling the propagator to ");
4241debfc3dSmrg       if (retval == SSA_PROP_INTERESTING)
4251debfc3dSmrg 	fprintf (dump_file, "add SSA edges out of this PHI and continue.");
4261debfc3dSmrg       else if (retval == SSA_PROP_VARYING)
4271debfc3dSmrg 	fprintf (dump_file, "add SSA edges out of this PHI and never visit again.");
4281debfc3dSmrg       else
4291debfc3dSmrg 	fprintf (dump_file, "do nothing with SSA edges and keep iterating.");
4301debfc3dSmrg       fprintf (dump_file, "\n\n");
4311debfc3dSmrg     }
4321debfc3dSmrg 
4331debfc3dSmrg   return retval;
4341debfc3dSmrg }
4351debfc3dSmrg 
4361debfc3dSmrg 
4371debfc3dSmrg /* Initialize structures used for copy propagation.  */
4381debfc3dSmrg 
4391debfc3dSmrg static void
init_copy_prop(void)4401debfc3dSmrg init_copy_prop (void)
4411debfc3dSmrg {
4421debfc3dSmrg   basic_block bb;
4431debfc3dSmrg 
4441debfc3dSmrg   n_copy_of = num_ssa_names;
4451debfc3dSmrg   copy_of = XCNEWVEC (prop_value_t, n_copy_of);
4461debfc3dSmrg 
4471debfc3dSmrg   FOR_EACH_BB_FN (bb, cfun)
4481debfc3dSmrg     {
4491debfc3dSmrg       for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
4501debfc3dSmrg 	   gsi_next (&si))
4511debfc3dSmrg 	{
4521debfc3dSmrg 	  gimple *stmt = gsi_stmt (si);
4531debfc3dSmrg 	  ssa_op_iter iter;
4541debfc3dSmrg           tree def;
4551debfc3dSmrg 
4561debfc3dSmrg 	  /* The only statements that we care about are those that may
4571debfc3dSmrg 	     generate useful copies.  We also need to mark conditional
4581debfc3dSmrg 	     jumps so that their outgoing edges are added to the work
4591debfc3dSmrg 	     lists of the propagator.  */
4601debfc3dSmrg 	  if (stmt_ends_bb_p (stmt))
4611debfc3dSmrg             prop_set_simulate_again (stmt, true);
4621debfc3dSmrg 	  else if (stmt_may_generate_copy (stmt))
4631debfc3dSmrg             prop_set_simulate_again (stmt, true);
4641debfc3dSmrg 	  else
4651debfc3dSmrg             prop_set_simulate_again (stmt, false);
4661debfc3dSmrg 
4671debfc3dSmrg 	  /* Mark all the outputs of this statement as not being
4681debfc3dSmrg 	     the copy of anything.  */
4691debfc3dSmrg 	  FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
4701debfc3dSmrg             if (!prop_simulate_again_p (stmt))
4711debfc3dSmrg 	      set_copy_of_val (def, def);
4721debfc3dSmrg 	}
4731debfc3dSmrg 
4741debfc3dSmrg       for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
4751debfc3dSmrg 	   gsi_next (&si))
4761debfc3dSmrg 	{
4771debfc3dSmrg           gphi *phi = si.phi ();
4781debfc3dSmrg           tree def;
4791debfc3dSmrg 
4801debfc3dSmrg 	  def = gimple_phi_result (phi);
4811debfc3dSmrg 	  if (virtual_operand_p (def))
4821debfc3dSmrg             prop_set_simulate_again (phi, false);
4831debfc3dSmrg 	  else
4841debfc3dSmrg             prop_set_simulate_again (phi, true);
4851debfc3dSmrg 
4861debfc3dSmrg 	  if (!prop_simulate_again_p (phi))
4871debfc3dSmrg 	    set_copy_of_val (def, def);
4881debfc3dSmrg 	}
4891debfc3dSmrg     }
4901debfc3dSmrg }
4911debfc3dSmrg 
492a2dc1f3fSmrg class copy_folder : public substitute_and_fold_engine
493a2dc1f3fSmrg {
494a2dc1f3fSmrg  public:
495a2dc1f3fSmrg   tree get_value (tree) FINAL OVERRIDE;
496a2dc1f3fSmrg };
497a2dc1f3fSmrg 
4981debfc3dSmrg /* Callback for substitute_and_fold to get at the final copy-of values.  */
4991debfc3dSmrg 
500a2dc1f3fSmrg tree
501a2dc1f3fSmrg copy_folder::get_value (tree name)
5021debfc3dSmrg {
5031debfc3dSmrg   tree val;
5041debfc3dSmrg   if (SSA_NAME_VERSION (name) >= n_copy_of)
5051debfc3dSmrg     return NULL_TREE;
5061debfc3dSmrg   val = copy_of[SSA_NAME_VERSION (name)].value;
5071debfc3dSmrg   if (val && val != name)
5081debfc3dSmrg     return val;
5091debfc3dSmrg   return NULL_TREE;
5101debfc3dSmrg }
5111debfc3dSmrg 
5121debfc3dSmrg /* Deallocate memory used in copy propagation and do final
5131debfc3dSmrg    substitution.  */
5141debfc3dSmrg 
5151debfc3dSmrg static bool
5161debfc3dSmrg fini_copy_prop (void)
5171debfc3dSmrg {
5181debfc3dSmrg   unsigned i;
5191debfc3dSmrg   tree var;
5201debfc3dSmrg 
5211debfc3dSmrg   /* Set the final copy-of value for each variable by traversing the
5221debfc3dSmrg      copy-of chains.  */
5231debfc3dSmrg   FOR_EACH_SSA_NAME (i, var, cfun)
5241debfc3dSmrg     {
5251debfc3dSmrg       if (!copy_of[i].value
5261debfc3dSmrg 	  || copy_of[i].value == var)
5271debfc3dSmrg 	continue;
5281debfc3dSmrg 
5291debfc3dSmrg       /* In theory the points-to solution of all members of the
5301debfc3dSmrg          copy chain is their intersection.  For now we do not bother
5311debfc3dSmrg 	 to compute this but only make sure we do not lose points-to
5321debfc3dSmrg 	 information completely by setting the points-to solution
5331debfc3dSmrg 	 of the representative to the first solution we find if
5341debfc3dSmrg 	 it doesn't have one already.  */
5351debfc3dSmrg       if (copy_of[i].value != var
5361debfc3dSmrg 	  && TREE_CODE (copy_of[i].value) == SSA_NAME)
5371debfc3dSmrg 	{
5381debfc3dSmrg 	  basic_block copy_of_bb
5391debfc3dSmrg 	    = gimple_bb (SSA_NAME_DEF_STMT (copy_of[i].value));
5401debfc3dSmrg 	  basic_block var_bb = gimple_bb (SSA_NAME_DEF_STMT (var));
5411debfc3dSmrg 	  if (POINTER_TYPE_P (TREE_TYPE (var))
5421debfc3dSmrg 	      && SSA_NAME_PTR_INFO (var)
5431debfc3dSmrg 	      && !SSA_NAME_PTR_INFO (copy_of[i].value))
5441debfc3dSmrg 	    {
5451debfc3dSmrg 	      duplicate_ssa_name_ptr_info (copy_of[i].value,
5461debfc3dSmrg 					   SSA_NAME_PTR_INFO (var));
5471debfc3dSmrg 	      /* Points-to information is cfg insensitive,
548a05ac97eSmrg 		 but [E]VRP might record context sensitive alignment
549a05ac97eSmrg 		 info, non-nullness, etc.  So reset context sensitive
550a05ac97eSmrg 		 info if the two SSA_NAMEs aren't defined in the same
551a05ac97eSmrg 		 basic block.  */
5521debfc3dSmrg 	      if (var_bb != copy_of_bb)
553a05ac97eSmrg 		reset_flow_sensitive_info (copy_of[i].value);
5541debfc3dSmrg 	    }
5551debfc3dSmrg 	  else if (!POINTER_TYPE_P (TREE_TYPE (var))
5561debfc3dSmrg 		   && SSA_NAME_RANGE_INFO (var)
5571debfc3dSmrg 		   && !SSA_NAME_RANGE_INFO (copy_of[i].value)
5581debfc3dSmrg 		   && var_bb == copy_of_bb)
5591debfc3dSmrg 	    duplicate_ssa_name_range_info (copy_of[i].value,
5601debfc3dSmrg 					   SSA_NAME_RANGE_TYPE (var),
5611debfc3dSmrg 					   SSA_NAME_RANGE_INFO (var));
5621debfc3dSmrg 	}
5631debfc3dSmrg     }
5641debfc3dSmrg 
565a2dc1f3fSmrg   class copy_folder copy_folder;
566a2dc1f3fSmrg   bool changed = copy_folder.substitute_and_fold ();
5671debfc3dSmrg   if (changed)
5681debfc3dSmrg     {
5691debfc3dSmrg       free_numbers_of_iterations_estimates (cfun);
5701debfc3dSmrg       if (scev_initialized_p ())
5711debfc3dSmrg 	scev_reset ();
5721debfc3dSmrg     }
5731debfc3dSmrg 
5741debfc3dSmrg   free (copy_of);
5751debfc3dSmrg 
5761debfc3dSmrg   return changed;
5771debfc3dSmrg }
5781debfc3dSmrg 
5791debfc3dSmrg 
5801debfc3dSmrg /* Main entry point to the copy propagator.
5811debfc3dSmrg 
5821debfc3dSmrg    PHIS_ONLY is true if we should only consider PHI nodes as generating
5831debfc3dSmrg    copy propagation opportunities.
5841debfc3dSmrg 
5851debfc3dSmrg    The algorithm propagates the value COPY-OF using ssa_propagate.  For
5861debfc3dSmrg    every variable X_i, COPY-OF(X_i) indicates which variable is X_i created
5871debfc3dSmrg    from.  The following example shows how the algorithm proceeds at a
5881debfc3dSmrg    high level:
5891debfc3dSmrg 
5901debfc3dSmrg 	    1	a_24 = x_1
5911debfc3dSmrg 	    2	a_2 = PHI <a_24, x_1>
5921debfc3dSmrg 	    3	a_5 = PHI <a_2>
5931debfc3dSmrg 	    4	x_1 = PHI <x_298, a_5, a_2>
5941debfc3dSmrg 
5951debfc3dSmrg    The end result should be that a_2, a_5, a_24 and x_1 are a copy of
5961debfc3dSmrg    x_298.  Propagation proceeds as follows.
5971debfc3dSmrg 
5981debfc3dSmrg    Visit #1: a_24 is copy-of x_1.  Value changed.
5991debfc3dSmrg    Visit #2: a_2 is copy-of x_1.  Value changed.
6001debfc3dSmrg    Visit #3: a_5 is copy-of x_1.  Value changed.
6011debfc3dSmrg    Visit #4: x_1 is copy-of x_298.  Value changed.
6021debfc3dSmrg    Visit #1: a_24 is copy-of x_298.  Value changed.
6031debfc3dSmrg    Visit #2: a_2 is copy-of x_298.  Value changed.
6041debfc3dSmrg    Visit #3: a_5 is copy-of x_298.  Value changed.
6051debfc3dSmrg    Visit #4: x_1 is copy-of x_298.  Stable state reached.
6061debfc3dSmrg 
6071debfc3dSmrg    When visiting PHI nodes, we only consider arguments that flow
6081debfc3dSmrg    through edges marked executable by the propagation engine.  So,
6091debfc3dSmrg    when visiting statement #2 for the first time, we will only look at
6101debfc3dSmrg    the first argument (a_24) and optimistically assume that its value
6111debfc3dSmrg    is the copy of a_24 (x_1).  */
6121debfc3dSmrg 
6131debfc3dSmrg static unsigned int
6141debfc3dSmrg execute_copy_prop (void)
6151debfc3dSmrg {
6161debfc3dSmrg   init_copy_prop ();
617a2dc1f3fSmrg   class copy_prop copy_prop;
618a2dc1f3fSmrg   copy_prop.ssa_propagate ();
6191debfc3dSmrg   if (fini_copy_prop ())
6201debfc3dSmrg     return TODO_cleanup_cfg;
6211debfc3dSmrg   return 0;
6221debfc3dSmrg }
6231debfc3dSmrg 
6241debfc3dSmrg namespace {
6251debfc3dSmrg 
6261debfc3dSmrg const pass_data pass_data_copy_prop =
6271debfc3dSmrg {
6281debfc3dSmrg   GIMPLE_PASS, /* type */
6291debfc3dSmrg   "copyprop", /* name */
6301debfc3dSmrg   OPTGROUP_NONE, /* optinfo_flags */
6311debfc3dSmrg   TV_TREE_COPY_PROP, /* tv_id */
6321debfc3dSmrg   ( PROP_ssa | PROP_cfg ), /* properties_required */
6331debfc3dSmrg   0, /* properties_provided */
6341debfc3dSmrg   0, /* properties_destroyed */
6351debfc3dSmrg   0, /* todo_flags_start */
6361debfc3dSmrg   0, /* todo_flags_finish */
6371debfc3dSmrg };
6381debfc3dSmrg 
6391debfc3dSmrg class pass_copy_prop : public gimple_opt_pass
6401debfc3dSmrg {
6411debfc3dSmrg public:
6421debfc3dSmrg   pass_copy_prop (gcc::context *ctxt)
6431debfc3dSmrg     : gimple_opt_pass (pass_data_copy_prop, ctxt)
6441debfc3dSmrg   {}
6451debfc3dSmrg 
6461debfc3dSmrg   /* opt_pass methods: */
6471debfc3dSmrg   opt_pass * clone () { return new pass_copy_prop (m_ctxt); }
6481debfc3dSmrg   virtual bool gate (function *) { return flag_tree_copy_prop != 0; }
6491debfc3dSmrg   virtual unsigned int execute (function *) { return execute_copy_prop (); }
6501debfc3dSmrg 
6511debfc3dSmrg }; // class pass_copy_prop
6521debfc3dSmrg 
6531debfc3dSmrg } // anon namespace
6541debfc3dSmrg 
6551debfc3dSmrg gimple_opt_pass *
6561debfc3dSmrg make_pass_copy_prop (gcc::context *ctxt)
6571debfc3dSmrg {
6581debfc3dSmrg   return new pass_copy_prop (ctxt);
6591debfc3dSmrg }
660