Improve tracking of bases in modref
Commit Message
Hi,
on exchange2 benchamrk we miss some useful propagation because modref gives
up very early on analyzing accesses through pointers. For example in
int test (int *a)
{
int i;
for (i=0; a[i];i++);
return i+a[i];
}
We are not able to determine that a[i] accesses are relative to a.
This is because get_access requires the SSA name that is in MEM_REF to be
PARM_DECL while on other places we use ipa-prop helper to work out the proper
base pointers.
This patch commonizes the code in get_access and parm_map_for_arg so both
use the check properly and extends it to also figure out that newly allocated
memory is not a side effect to caller.
It improves disambiguation rates:
Alias oracle query stats:
refs_may_alias_p: 77359588 disambiguations, 102170294 queries
ref_maybe_used_by_call_p: 645390 disambiguations, 78392252 queries
call_may_clobber_ref_p: 386653 disambiguations, 389576 queries
stmt_kills_ref_p: 106470 kills, 5685744 queries
nonoverlapping_component_refs_p: 0 disambiguations, 8923 queries
nonoverlapping_refs_since_match_p: 30581 disambiguations, 65481 must overlaps, 97009 queries
aliasing_component_refs_p: 56854 disambiguations, 15459249 queries
TBAA oracle: 28236957 disambiguations 104812620 queries
15360807 are in alias set 0
8863925 queries asked about the same object
99 queries asked about the same alias set
0 access volatile
50367859 are dependent in the DAG
1982973 are aritificially in conflict with void *
Modref stats:
modref kill: 71 kills, 8151 queries
modref use: 25273 disambiguations, 704264 queries
modref clobber: 1676006 disambiguations, 21805867 queries
5264985 tbaa queries (0.241448 per modref query)
762265 base compares (0.034957 per modref query)
PTA query stats:
pt_solution_includes: 13460623 disambiguations, 40881373 queries
pt_solutions_intersect: 1668037 disambiguations, 13958255 queries
to:
Alias oracle query stats:
refs_may_alias_p: 77575173 disambiguations, 102390852 queries
ref_maybe_used_by_call_p: 645932 disambiguations, 78607413 queries
call_may_clobber_ref_p: 386813 disambiguations, 389693 queries
stmt_kills_ref_p: 106551 kills, 5688432 queries
nonoverlapping_component_refs_p: 0 disambiguations, 8936 queries
nonoverlapping_refs_since_match_p: 30583 disambiguations, 65514 must overlaps, 97044 queries
aliasing_component_refs_p: 56847 disambiguations, 15459371 queries
TBAA oracle: 28238952 disambiguations 104938558 queries
15435200 are in alias set 0
8876784 queries asked about the same object
89 queries asked about the same alias set
0 access volatile
50400613 are dependent in the DAG
1986920 are aritificially in conflict with void *
Modref stats:
modref kill: 71 kills, 8130 queries
modref use: 30684 disambiguations, 704287 queries
modref clobber: 1694295 disambiguations, 21697882 queries
5233712 tbaa queries (0.241208 per modref query)
902240 base compares (0.041582 per modref query)
PTA query stats:
pt_solution_includes: 13495059 disambiguations, 40917961 queries
pt_solutions_intersect: 1667032 disambiguations, 13951159 queries
So 20% more modref use disambiguations which accounts to 0.3% overal
disambiguation and alo improves a bit situation with exchange2 benchmark,
while the real problem is still present (as dicussed in the pr)
gcc/ChangeLog:
2021-11-21 Jan Hubicka <hubicka@ucw.cz>
PR ipa/103227
* ipa-modref.c (parm_map_for_arg): Rename to ...
(parm_map_for_ptr): .. this one; handle static chain and calls to
malloc functions.
(modref_access_analysis::get_access): Use parm_map_for_ptr.
(modref_access_analysis::process_fnspec): Update.
(modref_access_analysis::analyze_load): Update.
(modref_access_analysis::analyze_store): Update.
gcc/testsuite/ChangeLog:
2021-11-21 Jan Hubicka <hubicka@ucw.cz>
PR ipa/103227
* gcc.dg/tree-ssa/modref-15.c: New test.
@@ -812,14 +812,15 @@ ignore_stores_p (tree caller, int flags)
return false;
}
-/* Determine parm_map for argument OP. */
+/* Determine parm_map for PTR which is supposed to be a pointer. */
modref_parm_map
-parm_map_for_arg (tree op)
+parm_map_for_ptr (tree op)
{
bool offset_known;
poly_int64 offset;
struct modref_parm_map parm_map;
+ gcall *call;
parm_map.parm_offset_known = false;
parm_map.parm_offset = 0;
@@ -830,22 +831,26 @@ parm_map_for_arg (tree op)
&& TREE_CODE (SSA_NAME_VAR (op)) == PARM_DECL)
{
int index = 0;
- for (tree t = DECL_ARGUMENTS (current_function_decl);
- t != SSA_NAME_VAR (op); t = DECL_CHAIN (t))
- {
- if (!t)
- {
- index = MODREF_UNKNOWN_PARM;
- break;
- }
+
+ if (cfun->static_chain_decl
+ && op == ssa_default_def (cfun, cfun->static_chain_decl))
+ index = MODREF_STATIC_CHAIN_PARM;
+ else
+ for (tree t = DECL_ARGUMENTS (current_function_decl);
+ t != SSA_NAME_VAR (op); t = DECL_CHAIN (t))
index++;
- }
parm_map.parm_index = index;
parm_map.parm_offset_known = offset_known;
parm_map.parm_offset = offset;
}
else if (points_to_local_or_readonly_memory_p (op))
parm_map.parm_index = MODREF_LOCAL_MEMORY_PARM;
+ /* Memory allocated in the function is not visible to caller before the
+ call and thus we do not need to record it as load/stores/kills. */
+ else if (TREE_CODE (op) == SSA_NAME
+ && (call = dyn_cast<gcall *>(SSA_NAME_DEF_STMT (op))) != NULL
+ && gimple_call_flags (call) & ECF_MALLOC)
+ parm_map.parm_index = MODREF_LOCAL_MEMORY_PARM;
else
parm_map.parm_index = MODREF_UNKNOWN_PARM;
return parm_map;
@@ -955,33 +960,19 @@ modref_access_analysis::get_access (ao_ref *ref)
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;
- if (cfun->static_chain_decl
- && base == ssa_default_def (cfun, cfun->static_chain_decl))
- a.parm_index = MODREF_STATIC_CHAIN_PARM;
- else
- 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;
+ modref_parm_map m = parm_map_for_ptr (TREE_OPERAND (base, 0));
- if (a.parm_index != MODREF_UNKNOWN_PARM
- && TREE_CODE (memref) == MEM_REF)
+ a.parm_index = m.parm_index;
+ 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);
+ if (a.parm_offset_known && m.parm_offset_known)
+ a.parm_offset += m.parm_offset;
+ else
+ a.parm_offset_known = false;
}
- else
- a.parm_offset_known = false;
}
else
a.parm_index = MODREF_UNKNOWN_PARM;
@@ -1220,7 +1211,7 @@ modref_access_analysis::merge_call_side_effects
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 (gimple_call_arg (stmt, i));
+ parm_map[i] = parm_map_for_ptr (gimple_call_arg (stmt, i));
if (dump_file)
{
fprintf (dump_file, " %i", parm_map[i].parm_index);
@@ -1236,7 +1227,7 @@ modref_access_analysis::merge_call_side_effects
modref_parm_map chain_map;
if (gimple_call_chain (stmt))
{
- chain_map = parm_map_for_arg (gimple_call_chain (stmt));
+ chain_map = parm_map_for_ptr (gimple_call_chain (stmt));
if (dump_file)
{
fprintf (dump_file, "static chain %i", chain_map.parm_index);
@@ -1390,7 +1381,7 @@ modref_access_analysis::process_fnspec (gcall *call)
else if (!fnspec.arg_specified_p (i)
|| fnspec.arg_maybe_read_p (i))
{
- modref_parm_map map = parm_map_for_arg
+ modref_parm_map map = parm_map_for_ptr
(gimple_call_arg (call, i));
if (map.parm_index == MODREF_LOCAL_MEMORY_PARM)
@@ -1401,6 +1392,8 @@ modref_access_analysis::process_fnspec (gcall *call)
break;
}
modref_access_node a = get_access_for_fnspec (call, fnspec, i, map);
+ if (a.parm_index == MODREF_LOCAL_MEMORY_PARM)
+ continue;
if (m_summary)
m_summary->loads->insert (0, 0, a, false);
if (m_summary_lto)
@@ -1419,7 +1412,7 @@ modref_access_analysis::process_fnspec (gcall *call)
else if (!fnspec.arg_specified_p (i)
|| fnspec.arg_maybe_written_p (i))
{
- modref_parm_map map = parm_map_for_arg
+ modref_parm_map map = parm_map_for_ptr
(gimple_call_arg (call, i));
if (map.parm_index == MODREF_LOCAL_MEMORY_PARM)
@@ -1430,6 +1423,8 @@ modref_access_analysis::process_fnspec (gcall *call)
break;
}
modref_access_node a = get_access_for_fnspec (call, fnspec, i, map);
+ if (a.parm_index == MODREF_LOCAL_MEMORY_PARM)
+ continue;
if (m_summary)
m_summary->stores->insert (0, 0, a, false);
if (m_summary_lto)
@@ -1553,6 +1548,8 @@ modref_access_analysis::analyze_load (gimple *, tree, tree op, void *data)
ao_ref r;
ao_ref_init (&r, op);
modref_access_node a = get_access (&r);
+ if (a.parm_index == MODREF_LOCAL_MEMORY_PARM)
+ return false;
if (t->m_summary)
t->record_access (t->m_summary->loads, &r, a);
@@ -1581,6 +1578,8 @@ modref_access_analysis::analyze_store (gimple *stmt, tree, tree op, void *data)
ao_ref r;
ao_ref_init (&r, op);
modref_access_node a = get_access (&r);
+ if (a.parm_index == MODREF_LOCAL_MEMORY_PARM)
+ return false;
if (t->m_summary)
t->record_access (t->m_summary->stores, &r, a);
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-modref1" } */
+int test (int *a)
+{
+ int i;
+ for (i=0; a[i];i++);
+ return i+a[i];
+}
+/* { dg-final { scan-tree-dump "access: Parm 0" "modref1"} } */