aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ipa-modref-tree.c2
-rw-r--r--gcc/ipa-modref-tree.h71
-rw-r--r--gcc/ipa-modref.c152
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/modref-12.c16
-rw-r--r--gcc/tree-ssa-alias.c12
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;