diff options
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r-- | gcc/tree-ssa-structalias.c | 251 |
1 files changed, 126 insertions, 125 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index e5f4a292855..74dc6d2c1ba 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -2825,7 +2825,7 @@ static void get_constraint_for_ptr_offset (tree ptr, tree offset, VEC (ce_s, heap) **results) { - struct constraint_expr *c; + struct constraint_expr c; unsigned int j, n; HOST_WIDE_INT rhsunitoffset, rhsoffset; @@ -2863,14 +2863,14 @@ get_constraint_for_ptr_offset (tree ptr, tree offset, for (j = 0; j < n; j++) { varinfo_t curr; - c = VEC_index (ce_s, *results, j); - curr = get_varinfo (c->var); + c = *VEC_index (ce_s, *results, j); + curr = get_varinfo (c.var); - if (c->type == ADDRESSOF + if (c.type == ADDRESSOF /* If this varinfo represents a full variable just use it. */ && curr->is_full_var) - c->offset = 0; - else if (c->type == ADDRESSOF + c.offset = 0; + else if (c.type == ADDRESSOF /* If we do not know the offset add all subfields. */ && rhsoffset == UNKNOWN_OFFSET) { @@ -2881,13 +2881,13 @@ get_constraint_for_ptr_offset (tree ptr, tree offset, c2.var = temp->id; c2.type = ADDRESSOF; c2.offset = 0; - if (c2.var != c->var) + if (c2.var != c.var) VEC_safe_push (ce_s, heap, *results, &c2); temp = temp->next; } while (temp); } - else if (c->type == ADDRESSOF) + else if (c.type == ADDRESSOF) { varinfo_t temp; unsigned HOST_WIDE_INT offset = curr->offset + rhsoffset; @@ -2919,11 +2919,13 @@ get_constraint_for_ptr_offset (tree ptr, tree offset, c2.offset = 0; VEC_safe_push (ce_s, heap, *results, &c2); } - c->var = temp->id; - c->offset = 0; + c.var = temp->id; + c.offset = 0; } else - c->offset = rhsoffset; + c.offset = rhsoffset; + + VEC_replace (ce_s, *results, j, &c); } } @@ -3661,8 +3663,8 @@ find_func_aliases (gimple origt) pointer passed by address. */ else if (is_gimple_call (t)) { - tree fndecl; - if ((fndecl = gimple_call_fndecl (t)) != NULL_TREE + tree fndecl = gimple_call_fndecl (t); + if (fndecl != NULL_TREE && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) /* ??? All builtins that are handled here need to be handled in the alias-oracle query functions explicitly! */ @@ -3685,8 +3687,10 @@ find_func_aliases (gimple origt) case BUILT_IN_STRNCAT: { tree res = gimple_call_lhs (t); - tree dest = gimple_call_arg (t, 0); - tree src = gimple_call_arg (t, 1); + tree dest = gimple_call_arg (t, (DECL_FUNCTION_CODE (fndecl) + == BUILT_IN_BCOPY ? 1 : 0)); + tree src = gimple_call_arg (t, (DECL_FUNCTION_CODE (fndecl) + == BUILT_IN_BCOPY ? 0 : 1)); if (res != NULL_TREE) { get_constraint_for (res, &lhsc); @@ -3772,7 +3776,9 @@ find_func_aliases (gimple origt) default: /* Fallthru to general call handling. */; } - if (!in_ipa_mode) + if (!in_ipa_mode + || (fndecl + && !lookup_vi_for_tree (fndecl))) { VEC(ce_s, heap) *rhsc = NULL; int flags = gimple_call_flags (t); @@ -4423,9 +4429,6 @@ create_variable_info_for (tree decl, const char *name) tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type); VEC (fieldoff_s,heap) *fieldstack = NULL; - if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode) - return create_function_info_for (decl, name); - if (var_can_have_subvars (decl) && use_field_sensitive) push_fields_onto_fieldstack (decl_type, &fieldstack, 0); @@ -4771,8 +4774,6 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt) } -static bool have_alias_info = false; - /* Compute the points-to solution *PT for the variable VI. */ static void @@ -5397,44 +5398,12 @@ delete_alias_heapvars (void) heapvar_for_stmt = NULL; } -/* Create points-to sets for the current function. See the comments - at the start of the file for an algorithmic overview. */ +/* Solve the constraint set. */ static void -compute_points_to_sets (void) +solve_constraints (void) { struct scc_info *si; - basic_block bb; - unsigned i; - varinfo_t vi; - - timevar_push (TV_TREE_PTA); - - init_alias_vars (); - init_alias_heapvars (); - - intra_create_variable_infos (); - - /* Now walk all statements and derive aliases. */ - FOR_EACH_BB (bb) - { - gimple_stmt_iterator gsi; - - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple phi = gsi_stmt (gsi); - - if (is_gimple_reg (gimple_phi_result (phi))) - find_func_aliases (phi); - } - - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple stmt = gsi_stmt (gsi); - - find_func_aliases (stmt); - } - } if (dump_file) { @@ -5491,6 +5460,48 @@ compute_points_to_sets (void) if (dump_file) dump_sa_points_to_info (dump_file); +} + +/* Create points-to sets for the current function. See the comments + at the start of the file for an algorithmic overview. */ + +static void +compute_points_to_sets (void) +{ + basic_block bb; + unsigned i; + varinfo_t vi; + + timevar_push (TV_TREE_PTA); + + init_alias_vars (); + init_alias_heapvars (); + + intra_create_variable_infos (); + + /* Now walk all statements and derive aliases. */ + FOR_EACH_BB (bb) + { + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple phi = gsi_stmt (gsi); + + if (is_gimple_reg (gimple_phi_result (phi))) + find_func_aliases (phi); + } + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + + find_func_aliases (stmt); + } + } + + /* From the constraints compute the points-to sets. */ + solve_constraints (); /* Compute the points-to sets for ESCAPED and CALLUSED used for call-clobber analysis. */ @@ -5522,8 +5533,6 @@ compute_points_to_sets (void) } timevar_pop (TV_TREE_PTA); - - have_alias_info = true; } @@ -5557,7 +5566,6 @@ delete_points_to_sets (void) VEC_free (varinfo_t, heap, varmap); free_alloc_pool (variable_info_pool); free_alloc_pool (constraint_pool); - have_alias_info = false; } @@ -5656,101 +5664,94 @@ static unsigned int ipa_pta_execute (void) { struct cgraph_node *node; - struct scc_info *si; in_ipa_mode = 1; + init_alias_heapvars (); init_alias_vars (); + /* Build the constraints. */ for (node = cgraph_nodes; node; node = node->next) { unsigned int varid; + /* Nodes without a body are not interesting. Especially do not + visit clones at this point for now - we get duplicate decls + there for inline clones at least. */ + if (!gimple_has_body_p (node->decl) + || node->clone_of) + continue; + + /* It does not make sense to have graph edges into or out of + externally visible functions. There is no extra information + we can gather from them. */ + if (node->local.externally_visible) + continue; + varid = create_function_info_for (node->decl, cgraph_node_name (node)); - if (node->local.externally_visible) - { - varinfo_t fi = get_varinfo (varid); - for (; fi; fi = fi->next) - make_constraint_from (fi, anything_id); - } } + for (node = cgraph_nodes; node; node = node->next) { - if (node->analyzed) - { - struct function *func = DECL_STRUCT_FUNCTION (node->decl); - basic_block bb; - tree old_func_decl = current_function_decl; - if (dump_file) - fprintf (dump_file, - "Generating constraints for %s\n", - cgraph_node_name (node)); - push_cfun (func); - current_function_decl = node->decl; + struct function *func; + basic_block bb; + tree old_func_decl; - FOR_EACH_BB_FN (bb, func) - { - gimple_stmt_iterator gsi; + /* Nodes without a body are not interesting. */ + if (!gimple_has_body_p (node->decl) + || node->clone_of) + continue; - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); - gsi_next (&gsi)) - { - gimple phi = gsi_stmt (gsi); + if (dump_file) + fprintf (dump_file, + "Generating constraints for %s\n", + cgraph_node_name (node)); - if (is_gimple_reg (gimple_phi_result (phi))) - find_func_aliases (phi); - } + func = DECL_STRUCT_FUNCTION (node->decl); + old_func_decl = current_function_decl; + push_cfun (func); + current_function_decl = node->decl; - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - find_func_aliases (gsi_stmt (gsi)); - } - current_function_decl = old_func_decl; - pop_cfun (); - } - else - { - /* Make point to anything. */ - } - } + /* For externally visible functions use local constraints for + their arguments. For local functions we see all callers + and thus do not need initial constraints for parameters. */ + if (node->local.externally_visible) + intra_create_variable_infos (); - if (dump_file) - { - fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n"); - dump_constraints (dump_file); - } + /* Build constriants for the function body. */ + FOR_EACH_BB_FN (bb, func) + { + gimple_stmt_iterator gsi; - if (dump_file) - fprintf (dump_file, - "\nCollapsing static cycles and doing variable " - "substitution:\n"); + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); + gsi_next (&gsi)) + { + gimple phi = gsi_stmt (gsi); - init_graph (VEC_length (varinfo_t, varmap) * 2); - build_pred_graph (); - si = perform_var_substitution (graph); - rewrite_constraints (graph, si); + if (is_gimple_reg (gimple_phi_result (phi))) + find_func_aliases (phi); + } - build_succ_graph (); - free_var_substitution_info (si); - move_complex_constraints (graph); - unite_pointer_equivalences (graph); - find_indirect_cycles (graph); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); - /* Implicit nodes and predecessors are no longer necessary at this - point. */ - remove_preds_and_fake_succs (graph); + find_func_aliases (stmt); + } + } - if (dump_file) - fprintf (dump_file, "\nSolving graph\n"); + current_function_decl = old_func_decl; + pop_cfun (); + } - solve_graph (graph); + /* From the constraints compute the points-to sets. */ + solve_constraints (); - if (dump_file) - dump_sa_points_to_info (dump_file); + delete_points_to_sets (); in_ipa_mode = 0; - delete_alias_heapvars (); - delete_points_to_sets (); + return 0; } |