static bool forward_propagate_addr_expr (tree name, tree rhs) { int stmt_loop_depth = gimple_bb (SSA_NAME_DEF_STMT (name))->loop_depth; imm_use_iterator iter; gimple use_stmt; bool all = true; bool single_use_p = has_single_use (name); FOR_EACH_IMM_USE_STMT (use_stmt, iter, name) { bool result; tree use_rhs; /* If the use is not in a simple assignment statement, then there is nothing we can do. */ if (gimple_code (use_stmt) != GIMPLE_ASSIGN) { if (!is_gimple_debug (use_stmt)) all = false; continue; } /* If the use is in a deeper loop nest, then we do not want to propagate the ADDR_EXPR into the loop as that is likely adding expression evaluations into the loop. */ if (gimple_bb (use_stmt)->loop_depth > stmt_loop_depth) { all = false; continue; } { gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); result = forward_propagate_addr_expr_1 (name, rhs, &gsi, single_use_p); /* If the use has moved to a different statement adjust the update machinery for the old statement too. */ if (use_stmt != gsi_stmt (gsi)) { update_stmt (use_stmt); use_stmt = gsi_stmt (gsi); } update_stmt (use_stmt); } all &= result; /* Remove intermediate now unused copy and conversion chains. */ use_rhs = gimple_assign_rhs1 (use_stmt); if (result && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME && TREE_CODE (use_rhs) == SSA_NAME && has_zero_uses (gimple_assign_lhs (use_stmt))) { gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); release_defs (use_stmt); gsi_remove (&gsi, true); } }
void dump_immediate_uses_for (FILE *file, tree var) { imm_use_iterator iter; use_operand_p use_p; gcc_assert (var && TREE_CODE (var) == SSA_NAME); print_generic_expr (file, var, TDF_SLIM); fprintf (file, " : -->"); if (has_zero_uses (var)) fprintf (file, " no uses.\n"); else if (has_single_use (var)) fprintf (file, " single use.\n"); else fprintf (file, "%d uses.\n", num_imm_uses (var)); FOR_EACH_IMM_USE_FAST (use_p, iter, var) { if (use_p->loc.stmt == NULL && use_p->use == NULL) fprintf (file, "***end of stmt iterator marker***\n"); else if (!is_gimple_reg (USE_FROM_PTR (use_p))) print_gimple_stmt (file, USE_STMT (use_p), 0, TDF_VOPS|TDF_MEMSYMS); else print_gimple_stmt (file, USE_STMT (use_p), 0, TDF_SLIM); } fprintf(file, "\n"); }
void backprop::process_var (tree var) { if (has_zero_uses (var)) return; usage_info info; intersect_uses (var, &info); gimple *stmt = SSA_NAME_DEF_STMT (var); if (info.is_useful ()) { bool existed; usage_info *&map_info = m_info_map.get_or_insert (var, &existed); if (!existed) { /* Recording information about VAR for the first time. */ map_info = m_info_pool.allocate (); *map_info = info; m_vars.safe_push (var_info_pair (var, map_info)); if (dump_file && (dump_flags & TDF_DETAILS)) dump_var_info (var, map_info, "Recording new information"); /* If STMT is a phi, reprocess any backedge uses. This is a no-op for other uses, which won't have any information associated with them. */ if (is_a <gphi *> (stmt)) reprocess_inputs (stmt); } else if (info != *map_info) { /* Recording information that is less optimistic than before. */ gcc_checking_assert ((info & *map_info) == info); *map_info = info; if (dump_file && (dump_flags & TDF_DETAILS)) dump_var_info (var, map_info, "Updating information"); reprocess_inputs (stmt); } } else { if (usage_info **slot = m_info_map.get (var)) { /* Removing previously-recorded information. */ **slot = info; m_info_map.remove (var); if (dump_file && (dump_flags & TDF_DETAILS)) dump_var_info (var, NULL, "Deleting information"); reprocess_inputs (stmt); } else { /* If STMT is a phi, remove any information recorded for its arguments. */ if (is_a <gphi *> (stmt)) reprocess_inputs (stmt); } } }
static bool remove_prop_source_from_use (tree name, gimple up_to_stmt) { gimple_stmt_iterator gsi; gimple stmt; do { if (!has_zero_uses (name)) return false; stmt = SSA_NAME_DEF_STMT (name); if (stmt == up_to_stmt) return true; gsi = gsi_for_stmt (stmt); release_defs (stmt); gsi_remove (&gsi, true); name = (gimple_assign_copy_p (stmt)) ? gimple_assign_rhs1 (stmt) : NULL; } while (name && TREE_CODE (name) == SSA_NAME); return false; }
static void forward_propagate_into_cond (tree cond_expr) { gcc_assert (TREE_CODE (cond_expr) == COND_EXPR); while (1) { tree test_var = NULL_TREE; tree cond = COND_EXPR_COND (cond_expr); tree new_cond = forward_propagate_into_cond_1 (cond, &test_var); /* Return if unsuccessful. */ if (new_cond == NULL_TREE) break; /* Dump details. */ if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, " Replaced '"); print_generic_expr (dump_file, cond, dump_flags); fprintf (dump_file, "' with '"); print_generic_expr (dump_file, new_cond, dump_flags); fprintf (dump_file, "'\n"); } COND_EXPR_COND (cond_expr) = new_cond; update_stmt (cond_expr); if (has_zero_uses (test_var)) { tree def = SSA_NAME_DEF_STMT (test_var); block_stmt_iterator bsi = bsi_for_stmt (def); bsi_remove (&bsi); } } }
static inline bool single_use (tree t) { return TREE_CODE (t) != SSA_NAME || has_zero_uses (t) || has_single_use (t); }