Improve modref tracking of base pointers

Message ID 20211122093028.GD68091@kam.mff.cuni.cz
State New
Headers show
Series
  • Improve modref tracking of base pointers
Related show

Commit Message

Marek Polacek via Gcc-patches Nov. 22, 2021, 9:30 a.m.
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.

Patch

diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
index a04e5855a9a..4f9323165ea 100644
--- a/gcc/ipa-modref.c
+++ b/gcc/ipa-modref.c
@@ -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);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-15.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-15.c
new file mode 100644
index 00000000000..06881f2a760
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-15.c
@@ -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"} } */