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 = ©_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