diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ipa-modref-tree.c | 2 | ||||
-rw-r--r-- | gcc/ipa-modref-tree.h | 71 | ||||
-rw-r--r-- | gcc/ipa-modref.c | 152 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/modref-12.c | 16 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 12 |
5 files changed, 158 insertions, 95 deletions
diff --git a/gcc/ipa-modref-tree.c b/gcc/ipa-modref-tree.c index 8d147a1..d0ee487 100644 --- a/gcc/ipa-modref-tree.c +++ b/gcc/ipa-modref-tree.c @@ -138,7 +138,7 @@ test_merge () t2->insert (3, 4, a, false); t2->insert (3, 5, a, false); - t1->merge (t2, NULL, false); + t1->merge (t2, NULL, NULL, false); ASSERT_FALSE (t1->every_base); ASSERT_NE (t1->bases, NULL); diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h index 54ae9e1..be5efcb 100644 --- a/gcc/ipa-modref-tree.h +++ b/gcc/ipa-modref-tree.h @@ -42,6 +42,18 @@ along with GCC; see the file COPYING3. If not see struct ipa_modref_summary; +/* parm indexes greater than 0 are normal parms. + Some negative values have special meaning. */ +enum modref_special_parms { + MODREF_UNKNOWN_PARM = -1, + MODREF_STATIC_CHAIN_PARM = -2, + MODREF_RETSLOT_PARM = -3, + /* Used in modref_parm_map to tak references which can be removed + from the summary during summary update since they now points to loca + memory. */ + MODREF_LOCAL_MEMORY_PARM = -4 +}; + /* Memory access. */ struct GTY(()) modref_access_node { @@ -65,12 +77,12 @@ struct GTY(()) modref_access_node /* Return true if access node holds no useful info. */ bool useful_p () const { - return parm_index != -1; + return parm_index != MODREF_UNKNOWN_PARM; } /* Return true if range info is useful. */ bool range_info_useful_p () const { - return parm_index != -1 && parm_offset_known + return parm_index != MODREF_UNKNOWN_PARM && parm_offset_known && (known_size_p (size) || known_size_p (max_size) || known_ge (offset, 0)); @@ -80,7 +92,7 @@ struct GTY(()) modref_access_node { if (parm_index != a.parm_index) return false; - if (parm_index >= 0) + if (parm_index != MODREF_UNKNOWN_PARM) { if (parm_offset_known != a.parm_offset_known) return false; @@ -101,7 +113,7 @@ struct GTY(()) modref_access_node bool contains (const modref_access_node &a) const { poly_int64 aoffset_adj = 0; - if (parm_index >= 0) + if (parm_index != MODREF_UNKNOWN_PARM) { if (parm_index != a.parm_index) return false; @@ -211,7 +223,7 @@ struct GTY(()) modref_access_node /* We assume that containment was tested earlier. */ gcc_checking_assert (!contains (a) && !a.contains (*this)); - if (parm_index >= 0) + if (parm_index != MODREF_UNKNOWN_PARM) { if (parm_index != a.parm_index) return false; @@ -350,8 +362,8 @@ struct GTY(()) modref_access_node { if (parm_index != a.parm_index) { - gcc_checking_assert (parm_index != -1); - parm_index = -1; + gcc_checking_assert (parm_index != MODREF_UNKNOWN_PARM); + parm_index = MODREF_UNKNOWN_PARM; return; } @@ -454,7 +466,7 @@ private: /* Access node specifying no useful info. */ const modref_access_node unspecified_modref_access_node - = {0, -1, -1, 0, -1, false, 0}; + = {0, -1, -1, 0, MODREF_UNKNOWN_PARM, false, 0}; template <typename T> struct GTY((user)) modref_ref_node @@ -506,6 +518,12 @@ struct GTY((user)) modref_ref_node size_t i, j; modref_access_node *a2; + /* Only the following kind of paramters needs to be tracked. + We do not track return slots because they are seen as a direct store + in the caller. */ + gcc_checking_assert (a.parm_index >= 0 + || a.parm_index == MODREF_STATIC_CHAIN_PARM + || a.parm_index == MODREF_UNKNOWN_PARM); if (flag_checking) verify (); @@ -734,9 +752,7 @@ struct GTY((user)) modref_base_node struct modref_parm_map { /* Index of parameter we translate to. - -1 indicates that parameter is unknown - -2 indicates that parameter points to local memory and access can be - discarded. */ + Values from special_params enum are permitted too. */ int parm_index; bool parm_offset_known; poly_int64 parm_offset; @@ -946,10 +962,11 @@ struct GTY((user)) modref_tree } /* Merge OTHER into the tree. - PARM_MAP, if non-NULL, maps parm indexes of callee to caller. -2 is used - to signalize that parameter is local and does not need to be tracked. + PARM_MAP, if non-NULL, maps parm indexes of callee to caller. + Similar CHAIN_MAP, if non-NULL, maps static chain of callee to caller. Return true if something has changed. */ bool merge (modref_tree <T> *other, vec <modref_parm_map> *parm_map, + modref_parm_map *static_chain_map, bool record_accesses) { if (!other || every_base) @@ -1003,21 +1020,21 @@ struct GTY((user)) modref_tree { modref_access_node a = *access_node; - if (a.parm_index != -1 && parm_map) + if (a.parm_index != MODREF_UNKNOWN_PARM && parm_map) { if (a.parm_index >= (int)parm_map->length ()) - a.parm_index = -1; - else if ((*parm_map) [a.parm_index].parm_index == -2) - continue; + a.parm_index = MODREF_UNKNOWN_PARM; else { - a.parm_offset - += (*parm_map) [a.parm_index].parm_offset; - a.parm_offset_known - &= (*parm_map) - [a.parm_index].parm_offset_known; - a.parm_index - = (*parm_map) [a.parm_index].parm_index; + modref_parm_map &m + = a.parm_index == MODREF_STATIC_CHAIN_PARM + ? *static_chain_map + : (*parm_map) [a.parm_index]; + if (m.parm_index == MODREF_LOCAL_MEMORY_PARM) + continue; + a.parm_offset += m.parm_offset; + a.parm_offset_known &= m.parm_offset_known; + a.parm_index = m.parm_index; } } changed |= insert (base_node->base, ref_node->ref, a, @@ -1033,7 +1050,7 @@ struct GTY((user)) modref_tree /* Copy OTHER to THIS. */ void copy_from (modref_tree <T> *other) { - merge (other, NULL, false); + merge (other, NULL, NULL, false); } /* Search BASE in tree; return NULL if failed. */ @@ -1065,7 +1082,7 @@ struct GTY((user)) modref_tree if (ref_node->every_access) return true; FOR_EACH_VEC_SAFE_ELT (ref_node->accesses, k, access_node) - if (access_node->parm_index < 0) + if (access_node->parm_index == MODREF_UNKNOWN_PARM) return true; } } @@ -1127,7 +1144,7 @@ struct GTY((user)) modref_tree if (access_node->parm_index < (int)map->length ()) access_node->parm_index = (*map)[access_node->parm_index]; else - access_node->parm_index = -1; + access_node->parm_index = MODREF_UNKNOWN_PARM; } } } diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 4e64ee5..4429bce 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -426,9 +426,14 @@ static void dump_access (modref_access_node *a, FILE *out) { fprintf (out, " access:"); - if (a->parm_index != -1) + if (a->parm_index != MODREF_UNKNOWN_PARM) { - fprintf (out, " Parm %i", a->parm_index); + if (a->parm_index >= 0) + fprintf (out, " Parm %i", a->parm_index); + else if (a->parm_index == MODREF_STATIC_CHAIN_PARM) + fprintf (out, " Static chain"); + else + gcc_unreachable (); if (a->parm_offset_known) { fprintf (out, " param offset:"); @@ -697,40 +702,40 @@ get_access (ao_ref *ref) base = ao_ref_base (ref); modref_access_node a = {ref->offset, ref->size, ref->max_size, - 0, -1, false, 0}; + 0, MODREF_UNKNOWN_PARM, false, 0}; if (TREE_CODE (base) == MEM_REF || TREE_CODE (base) == TARGET_MEM_REF) { tree memref = base; base = TREE_OPERAND (base, 0); + if (TREE_CODE (base) == SSA_NAME && SSA_NAME_IS_DEFAULT_DEF (base) && TREE_CODE (SSA_NAME_VAR (base)) == PARM_DECL) { a.parm_index = 0; - for (tree t = DECL_ARGUMENTS (current_function_decl); - t != SSA_NAME_VAR (base); t = DECL_CHAIN (t)) - { - if (!t) - { - a.parm_index = -1; - break; - } - a.parm_index++; - } - if (TREE_CODE (memref) == MEM_REF) - { - a.parm_offset_known - = wi::to_poly_wide (TREE_OPERAND - (memref, 1)).to_shwi (&a.parm_offset); - } + if (cfun->static_chain_decl + && base == ssa_default_def (cfun, cfun->static_chain_decl)) + a.parm_index = MODREF_STATIC_CHAIN_PARM; else - a.parm_offset_known = false; + for (tree t = DECL_ARGUMENTS (current_function_decl); + t != SSA_NAME_VAR (base); t = DECL_CHAIN (t)) + a.parm_index++; + } + else + a.parm_index = MODREF_UNKNOWN_PARM; + + if (a.parm_index != MODREF_UNKNOWN_PARM + && TREE_CODE (memref) == MEM_REF) + { + a.parm_offset_known + = wi::to_poly_wide (TREE_OPERAND + (memref, 1)).to_shwi (&a.parm_offset); } else - a.parm_index = -1; + a.parm_offset_known = false; } else - a.parm_index = -1; + a.parm_index = MODREF_UNKNOWN_PARM; return a; } @@ -858,12 +863,11 @@ ignore_stores_p (tree caller, int flags) return false; } -/* Determine parm_map for argument I of STMT. */ +/* Determine parm_map for argument OP. */ modref_parm_map -parm_map_for_arg (gimple *stmt, int i) +parm_map_for_arg (tree op) { - tree op = gimple_call_arg (stmt, i); bool offset_known; poly_int64 offset; struct modref_parm_map parm_map; @@ -882,7 +886,7 @@ parm_map_for_arg (gimple *stmt, int i) { if (!t) { - index = -1; + index = MODREF_UNKNOWN_PARM; break; } index++; @@ -892,9 +896,9 @@ parm_map_for_arg (gimple *stmt, int i) parm_map.parm_offset = offset; } else if (points_to_local_or_readonly_memory_p (op)) - parm_map.parm_index = -2; + parm_map.parm_index = MODREF_LOCAL_MEMORY_PARM; else - parm_map.parm_index = -1; + parm_map.parm_index = MODREF_UNKNOWN_PARM; return parm_map; } @@ -911,6 +915,7 @@ merge_call_side_effects (modref_summary *cur_summary, bool record_adjustments) { auto_vec <modref_parm_map, 32> parm_map; + modref_parm_map chain_map; bool changed = false; /* We can not safely optimize based on summary of callee if it does @@ -931,7 +936,7 @@ merge_call_side_effects (modref_summary *cur_summary, parm_map.safe_grow_cleared (gimple_call_num_args (stmt), true); for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) { - parm_map[i] = parm_map_for_arg (stmt, i); + parm_map[i] = parm_map_for_arg (gimple_call_arg (stmt, i)); if (dump_file) { fprintf (dump_file, " %i", parm_map[i].parm_index); @@ -943,16 +948,30 @@ merge_call_side_effects (modref_summary *cur_summary, } } } + if (gimple_call_chain (stmt)) + { + chain_map = parm_map_for_arg (gimple_call_chain (stmt)); + if (dump_file) + { + fprintf (dump_file, "static chain %i", chain_map.parm_index); + if (chain_map.parm_offset_known) + { + fprintf (dump_file, " offset:"); + print_dec ((poly_int64_pod)chain_map.parm_offset, + dump_file, SIGNED); + } + } + } if (dump_file) fprintf (dump_file, "\n"); /* Merge with callee's summary. */ changed |= cur_summary->loads->merge (callee_summary->loads, &parm_map, - record_adjustments); + &chain_map, record_adjustments); if (!ignore_stores) { changed |= cur_summary->stores->merge (callee_summary->stores, - &parm_map, + &parm_map, &chain_map, record_adjustments); if (!cur_summary->writes_errno && callee_summary->writes_errno) @@ -1078,11 +1097,12 @@ process_fnspec (modref_summary *cur_summary, else if (!fnspec.arg_specified_p (i) || fnspec.arg_maybe_read_p (i)) { - modref_parm_map map = parm_map_for_arg (call, i); + modref_parm_map map = parm_map_for_arg + (gimple_call_arg (call, i)); - if (map.parm_index == -2) + if (map.parm_index == MODREF_LOCAL_MEMORY_PARM) continue; - if (map.parm_index == -1) + if (map.parm_index == MODREF_UNKNOWN_PARM) { collapse_loads (cur_summary, cur_summary_lto); break; @@ -1113,11 +1133,12 @@ process_fnspec (modref_summary *cur_summary, else if (!fnspec.arg_specified_p (i) || fnspec.arg_maybe_written_p (i)) { - modref_parm_map map = parm_map_for_arg (call, i); + modref_parm_map map = parm_map_for_arg + (gimple_call_arg (call, i)); - if (map.parm_index == -2) + if (map.parm_index == MODREF_LOCAL_MEMORY_PARM) continue; - if (map.parm_index == -1) + if (map.parm_index == MODREF_UNKNOWN_PARM) { collapse_stores (cur_summary, cur_summary_lto); break; @@ -1429,12 +1450,6 @@ deref_flags (int flags, bool ignore_stores) struct escape_point { - /* Extra hidden args we keep track of. */ - enum hidden_args - { - retslot_arg = -1, - static_chain_arg = -2 - }; /* Value escapes to this call. */ gcall *call; /* Argument it escapes to. */ @@ -2410,7 +2425,7 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto, if (summary_lto) summary_lto->retslot_flags = flags; eaf_analysis.record_escape_points (retslot, - escape_point::retslot_arg, flags); + MODREF_RETSLOT_PARM, flags); } } if (static_chain) @@ -2425,7 +2440,7 @@ analyze_parms (modref_summary *summary, modref_summary_lto *summary_lto, if (summary_lto) summary_lto->static_chain_flags = flags; eaf_analysis.record_escape_points (static_chain, - escape_point::static_chain_arg, + MODREF_STATIC_CHAIN_PARM, flags); } } @@ -3586,7 +3601,7 @@ compute_parm_map (cgraph_edge *callee_edge, vec<modref_parm_map> *parm_map) { if (es && es->param[i].points_to_local_or_readonly_memory) { - (*parm_map)[i].parm_index = -2; + (*parm_map)[i].parm_index = MODREF_LOCAL_MEMORY_PARM; continue; } @@ -3600,7 +3615,7 @@ compute_parm_map (cgraph_edge *callee_edge, vec<modref_parm_map> *parm_map) (callee_pi, i)); if (cst && points_to_local_or_readonly_memory_p (cst)) { - (*parm_map)[i].parm_index = -2; + (*parm_map)[i].parm_index = MODREF_LOCAL_MEMORY_PARM; continue; } } @@ -3798,9 +3813,9 @@ propagate_unknown_call (cgraph_node *node, || fnspec.arg_maybe_read_p (i)) { modref_parm_map map = parm_map[i]; - if (map.parm_index == -2) + if (map.parm_index == MODREF_LOCAL_MEMORY_PARM) continue; - if (map.parm_index == -1) + if (map.parm_index == MODREF_UNKNOWN_PARM) { collapse_loads (cur_summary, cur_summary_lto); break; @@ -3828,9 +3843,9 @@ propagate_unknown_call (cgraph_node *node, || fnspec.arg_maybe_written_p (i)) { modref_parm_map map = parm_map[i]; - if (map.parm_index == -2) + if (map.parm_index == MODREF_LOCAL_MEMORY_PARM) continue; - if (map.parm_index == -1) + if (map.parm_index == MODREF_UNKNOWN_PARM) { collapse_stores (cur_summary, cur_summary_lto); break; @@ -4030,6 +4045,10 @@ modref_propagate_in_scc (cgraph_node *component_node) auto_vec <modref_parm_map, 32> parm_map; + modref_parm_map chain_map; + /* TODO: Once we get jump functions for static chains we could + compute this. */ + chain_map.parm_index = MODREF_UNKNOWN_PARM; compute_parm_map (callee_edge, &parm_map); @@ -4037,12 +4056,13 @@ modref_propagate_in_scc (cgraph_node *component_node) if (callee_summary) { changed |= cur_summary->loads->merge - (callee_summary->loads, &parm_map, !first); + (callee_summary->loads, &parm_map, + &chain_map, !first); if (!ignore_stores) { changed |= cur_summary->stores->merge (callee_summary->stores, &parm_map, - !first); + &chain_map, !first); if (!cur_summary->writes_errno && callee_summary->writes_errno) { @@ -4055,12 +4075,12 @@ modref_propagate_in_scc (cgraph_node *component_node) { changed |= cur_summary_lto->loads->merge (callee_summary_lto->loads, &parm_map, - !first); + &chain_map, !first); if (!ignore_stores) { changed |= cur_summary_lto->stores->merge (callee_summary_lto->stores, &parm_map, - !first); + &chain_map, !first); if (!cur_summary_lto->writes_errno && callee_summary_lto->writes_errno) { @@ -4223,9 +4243,9 @@ modref_merge_call_site_flags (escape_summary *sum, if (!(flags & EAF_UNUSED) && cur_summary && ee->parm_index < (int)cur_summary->arg_flags.length ()) { - eaf_flags_t &f = ee->parm_index == escape_point::retslot_arg + eaf_flags_t &f = ee->parm_index == MODREF_RETSLOT_PARM ? cur_summary->retslot_flags - : ee->parm_index == escape_point::static_chain_arg + : ee->parm_index == MODREF_STATIC_CHAIN_PARM ? cur_summary->static_chain_flags : cur_summary->arg_flags[ee->parm_index]; if ((f & flags) != f) @@ -4240,9 +4260,9 @@ modref_merge_call_site_flags (escape_summary *sum, && cur_summary_lto && ee->parm_index < (int)cur_summary_lto->arg_flags.length ()) { - eaf_flags_t &f = ee->parm_index == escape_point::retslot_arg + eaf_flags_t &f = ee->parm_index == MODREF_RETSLOT_PARM ? cur_summary_lto->retslot_flags - : ee->parm_index == escape_point::static_chain_arg + : ee->parm_index == MODREF_STATIC_CHAIN_PARM ? cur_summary_lto->static_chain_flags : cur_summary_lto->arg_flags[ee->parm_index]; if ((f & flags_lto) != f) @@ -4428,24 +4448,30 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge) if (callee_info || callee_info_lto) { auto_vec <modref_parm_map, 32> parm_map; + modref_parm_map chain_map; + /* TODO: Once we get jump functions for static chains we could + compute this. */ + chain_map.parm_index = MODREF_UNKNOWN_PARM; compute_parm_map (edge, &parm_map); if (!ignore_stores) { if (to_info && callee_info) - to_info->stores->merge (callee_info->stores, &parm_map, false); + to_info->stores->merge (callee_info->stores, &parm_map, + &chain_map, false); if (to_info_lto && callee_info_lto) to_info_lto->stores->merge (callee_info_lto->stores, &parm_map, - false); + &chain_map, false); } if (!(flags & (ECF_CONST | ECF_NOVOPS))) { if (to_info && callee_info) - to_info->loads->merge (callee_info->loads, &parm_map, false); + to_info->loads->merge (callee_info->loads, &parm_map, + &chain_map, false); if (to_info_lto && callee_info_lto) to_info_lto->loads->merge (callee_info_lto->loads, &parm_map, - false); + &chain_map, false); } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-12.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-12.c new file mode 100644 index 0000000..f8ce047 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-12.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +void foo (); +int +test() +{ + struct {int a,b;} a = {0,0}; + __attribute__ ((noinline)) + void nested () + { + a.b++; + } + nested (); + return a.a; +} +/* { dg-final { scan-tree-dump "return 0" "optimized"} } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index ce667ff..eabf680 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -2594,14 +2594,18 @@ modref_may_conflict (const gimple *stmt, if (num_tests >= max_tests) return true; - if (access_node->parm_index == -1 - || (unsigned)access_node->parm_index - >= gimple_call_num_args (stmt)) + if (access_node->parm_index == MODREF_UNKNOWN_PARM + || access_node->parm_index + >= (int)gimple_call_num_args (stmt)) return true; alias_stats.modref_baseptr_tests++; + tree arg; - tree arg = gimple_call_arg (stmt, access_node->parm_index); + if (access_node->parm_index == MODREF_STATIC_CHAIN_PARM) + arg = gimple_call_chain (stmt); + else + arg = gimple_call_arg (stmt, access_node->parm_index); if (integer_zerop (arg) && flag_delete_null_pointer_checks) continue; |