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