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 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 * 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 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 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 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 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 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 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 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 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