+
+
+/* Deallocate memory used in copy propagation and do final
+ substitution. */
+
+static void
+fini_copy_prop (void)
+{
+ size_t i;
+ prop_value_t *tmp;
+
+ /* Set the final copy-of value for each variable by traversing the
+ copy-of chains. */
+ tmp = XCNEWVEC (prop_value_t, num_ssa_names);
+ for (i = 1; i < num_ssa_names; i++)
+ {
+ tree var = ssa_name (i);
+ if (!var
+ || !copy_of[i].value
+ || copy_of[i].value == var)
+ continue;
+
+ tmp[i].value = get_last_copy_of (var);
+
+ /* In theory the points-to solution of all members of the
+ copy chain is their intersection. For now we do not bother
+ to compute this but only make sure we do not lose points-to
+ information completely by setting the points-to solution
+ of the representative to the first solution we find if
+ it doesn't have one already. */
+ if (tmp[i].value != var
+ && POINTER_TYPE_P (TREE_TYPE (var))
+ && SSA_NAME_PTR_INFO (var)
+ && !SSA_NAME_PTR_INFO (tmp[i].value))
+ duplicate_ssa_name_ptr_info (tmp[i].value, SSA_NAME_PTR_INFO (var));
+ }
+
+ substitute_and_fold (tmp, NULL, true);
+
+ free (cached_last_copy_of);
+ free (copy_of);
+ free (tmp);
+}
+
+
+/* Main entry point to the copy propagator.
+
+ PHIS_ONLY is true if we should only consider PHI nodes as generating
+ copy propagation opportunities.
+
+ The algorithm propagates the value COPY-OF using ssa_propagate. For
+ every variable X_i, COPY-OF(X_i) indicates which variable is X_i created
+ from. The following example shows how the algorithm proceeds at a
+ high level:
+
+ 1 a_24 = x_1
+ 2 a_2 = PHI <a_24, x_1>
+ 3 a_5 = PHI <a_2>
+ 4 x_1 = PHI <x_298, a_5, a_2>
+
+ The end result should be that a_2, a_5, a_24 and x_1 are a copy of
+ x_298. Propagation proceeds as follows.
+
+ Visit #1: a_24 is copy-of x_1. Value changed.
+ Visit #2: a_2 is copy-of x_1. Value changed.
+ Visit #3: a_5 is copy-of x_1. Value changed.
+ Visit #4: x_1 is copy-of x_298. Value changed.
+ Visit #1: a_24 is copy-of x_298. Value changed.
+ Visit #2: a_2 is copy-of x_298. Value changed.
+ Visit #3: a_5 is copy-of x_298. Value changed.
+ Visit #4: x_1 is copy-of x_298. Stable state reached.
+
+ When visiting PHI nodes, we only consider arguments that flow
+ through edges marked executable by the propagation engine. So,
+ when visiting statement #2 for the first time, we will only look at
+ the first argument (a_24) and optimistically assume that its value
+ is the copy of a_24 (x_1).
+
+ The problem with this approach is that it may fail to discover copy
+ relations in PHI cycles. Instead of propagating copy-of
+ values, we actually propagate copy-of chains. For instance:
+
+ A_3 = B_1;
+ C_9 = A_3;
+ D_4 = C_9;
+ X_i = D_4;
+
+ In this code fragment, COPY-OF (X_i) = { D_4, C_9, A_3, B_1 }.
+ Obviously, we are only really interested in the last value of the
+ chain, however the propagator needs to access the copy-of chain
+ when visiting PHI nodes.
+
+ To represent the copy-of chain, we use the array COPY_CHAINS, which
+ holds the first link in the copy-of chain for every variable.
+ If variable X_i is a copy of X_j, which in turn is a copy of X_k,
+ the array will contain:
+
+ COPY_CHAINS[i] = X_j
+ COPY_CHAINS[j] = X_k
+ COPY_CHAINS[k] = X_k
+
+ Keeping copy-of chains instead of copy-of values directly becomes
+ important when visiting PHI nodes. Suppose that we had the
+ following PHI cycle, such that x_52 is already considered a copy of
+ x_53:
+
+ 1 x_54 = PHI <x_53, x_52>
+ 2 x_53 = PHI <x_898, x_54>
+
+ Visit #1: x_54 is copy-of x_53 (because x_52 is copy-of x_53)
+ Visit #2: x_53 is copy-of x_898 (because x_54 is a copy of x_53,
+ so it is considered irrelevant
+ as a copy).
+ Visit #1: x_54 is copy-of nothing (x_53 is a copy-of x_898 and
+ x_52 is a copy of x_53, so
+ they don't match)
+ Visit #2: x_53 is copy-of nothing
+
+ This problem is avoided by keeping a chain of copies, instead of
+ the final copy-of value. Propagation will now only keep the first
+ element of a variable's copy-of chain. When visiting PHI nodes,
+ arguments are considered equal if their copy-of chains end in the
+ same variable. So, as long as their copy-of chains overlap, we
+ know that they will be a copy of the same variable, regardless of
+ which variable that may be).
+
+ Propagation would then proceed as follows (the notation a -> b
+ means that a is a copy-of b):
+
+ Visit #1: x_54 = PHI <x_53, x_52>
+ x_53 -> x_53
+ x_52 -> x_53
+ Result: x_54 -> x_53. Value changed. Add SSA edges.
+
+ Visit #1: x_53 = PHI <x_898, x_54>
+ x_898 -> x_898
+ x_54 -> x_53
+ Result: x_53 -> x_898. Value changed. Add SSA edges.
+
+ Visit #2: x_54 = PHI <x_53, x_52>
+ x_53 -> x_898
+ x_52 -> x_53 -> x_898
+ Result: x_54 -> x_898. Value changed. Add SSA edges.
+
+ Visit #2: x_53 = PHI <x_898, x_54>
+ x_898 -> x_898
+ x_54 -> x_898
+ Result: x_53 -> x_898. Value didn't change. Stable state
+
+ Once the propagator stabilizes, we end up with the desired result
+ x_53 and x_54 are both copies of x_898. */
+
+static unsigned int
+execute_copy_prop (void)
+{
+ init_copy_prop ();
+ ssa_propagate (copy_prop_visit_stmt, copy_prop_visit_phi_node);
+ fini_copy_prop ();
+ return 0;
+}
+
+static bool
+gate_copy_prop (void)
+{
+ return flag_tree_copy_prop != 0;
+}
+
+struct gimple_opt_pass pass_copy_prop =
+{
+ {
+ GIMPLE_PASS,
+ "copyprop", /* name */
+ gate_copy_prop, /* gate */
+ execute_copy_prop, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_TREE_COPY_PROP, /* tv_id */
+ PROP_ssa | PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_cleanup_cfg
+ | TODO_dump_func
+ | TODO_ggc_collect
+ | TODO_verify_ssa
+ | TODO_update_ssa /* todo_flags_finish */
+ }
+};