* Add handling of bulitins to ipa-modref
@ 2020-09-27 22:31 Jan Hubicka
0 siblings, 0 replies; only message in thread
From: Jan Hubicka @ 2020-09-27 22:31 UTC (permalink / raw)
To: gcc-patches, d, rbiener, fortran
Hi,
this patch implements basic builtins handling to ipa-modref.
It breaks three additional Fortran testcases due to Fortran frontend
TBAA bugs as discussed in
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/554936.html
Otherwise it bootstraps and regtests x86_64-linux. With cc1plus I now
get:
Alias oracle query stats:
refs_may_alias_p: 63538841 disambiguations, 73864959 queries
ref_maybe_used_by_call_p: 142582 disambiguations, 64434151 queries
call_may_clobber_ref_p: 23601 disambiguations, 30140 queries
nonoverlapping_component_refs_p: 0 disambiguations, 38132 queries
nonoverlapping_refs_since_match_p: 19438 disambiguations, 55708 must overlaps, 75971 queries
aliasing_component_refs_p: 55152 disambiguations, 755956 queries
TBAA oracle: 25191597 disambiguations 58468366 queries
16860532 are in alias set 0
10457818 queries asked about the same object
125 queries asked about the same alias set
0 access volatile
4033743 are dependent in the DAG
1924551 are aritificially in conflict with void *
Modref stats:
modref use: 12085 disambiguations, 56415 queries
modref clobber: 1613560 disambiguations, 2391667 queries
6026445 tbaa queries (2.519768 per modref query)
433921 base compares (0.181430 per modref query)
PTA query stats:
pt_solution_includes: 982378 disambiguations, 13627506 queries
pt_solutions_intersect: 1029380 disambiguations, 13198579 queries
This is 15% more use disambiguations and 38% clobber disambiguations
compared to previous build in
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/554930.html
Good part of clobber disambiguation is probalby due to the bugfix
https://gcc.gnu.org/pipermail/gcc-patches/2020-September/554937.html
but that should not affect uses and thus there is certainly noticeable
improvement for builtin handling.
I get no noticeable difference for tramp3d presumably because most
alocations are on-stack or via C++ new.
gcc/ChangeLog:
2020-09-28 Jan Hubicka <hubicka@ucw.cz>
* ipa-modref.c: Include tree-ssa-alias.h.
(modref_summary::dump): Dump writes_errno.
(parm_map_for): Break out from...
(merge_call_side_effects): ... here.
(analyze_call): Handle builtins.
(analyze_function): Initialize writes_errno.
(modref_summaries::duplicate): Copy writes_errno.
(modref_write): Stream writes_errno.
(read_section): Stream writes_errno.
(compute_parm_map): Be ready for missing callee info.
(ipa_merge_modref_summary_after_inlining): Skip stores for pure
functions.
(collapse_stores): New function.
(modref_propagate_in_scc): Handle bultins.
* ipa-modref.h (modref_summary): Add writes_errno.
* tree-ssa-alias.c (call_may_clobber_ref_p_1): Check for errno.
diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
index 6225552e41a..bba9f0db71d 100644
--- a/gcc/ipa-modref.c
+++ b/gcc/ipa-modref.c
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see
#include "value-range.h"
#include "ipa-prop.h"
#include "ipa-fnsummary.h"
+#include "tree-ssa-alias.h"
/* Class (from which there is one global instance) that holds modref summaries
for all analyzed functions. */
@@ -257,6 +258,8 @@ modref_summary::dump (FILE *out)
fprintf (out, " LTO stores:\n");
dump_lto_records (stores_lto, out);
}
+ if (writes_errno)
+ fprintf (out, " Writes errno\n");
}
@@ -437,6 +440,35 @@ ignore_stores_p (tree caller, int flags)
return false;
}
+/* Return parm map value for OP.
+ This means returning nonnegative value if OP is function parameter,
+ -2 is OP points to local or readonly memory and -1 otherwise. */
+static int
+parm_map_for (tree op)
+{
+ if (TREE_CODE (op) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (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 = -1;
+ break;
+ }
+ index++;
+ }
+ return index;
+ }
+ else if (points_to_local_or_readonly_memory_p (op))
+ return -2;
+ else
+ return -1;
+}
+
/* Merge side effects of call STMT to function with CALLEE_SUMMARY
int CUR_SUMMARY. Return true if something changed.
If IGNORE_STORES is true, do not merge stores. */
@@ -451,31 +483,7 @@ merge_call_side_effects (modref_summary *cur_summary,
parm_map.safe_grow (gimple_call_num_args (stmt));
for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
- {
- tree op = gimple_call_arg (stmt, i);
- STRIP_NOPS (op);
- if (TREE_CODE (op) == SSA_NAME
- && SSA_NAME_IS_DEFAULT_DEF (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 = -1;
- break;
- }
- index++;
- }
- parm_map[i] = index;
- }
- else if (points_to_local_or_readonly_memory_p (op))
- parm_map[i] = -2;
- else
- parm_map[i] = -1;
- }
+ parm_map[i] = parm_map_for (gimple_call_arg (stmt, i));
/* Merge with callee's summary. */
if (cur_summary->loads)
@@ -491,6 +499,7 @@ merge_call_side_effects (modref_summary *cur_summary,
if (cur_summary->stores_lto)
changed |= cur_summary->stores_lto->merge (callee_summary->stores_lto,
&parm_map);
+ cur_summary->writes_errno |= callee_summary->writes_errno;
}
return changed;
}
@@ -544,6 +553,85 @@ analyze_call (modref_summary *cur_summary,
return false;
}
+ struct ao_function_info info;
+ if (callee
+ && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
+ && ao_classify_builtin (callee, &info)
+ && !(info.flags & AO_FUNCTION_BARRIER))
+ {
+ bool collapse_loads = false, collapse_stores = false;
+ if (info.num_param_reads >= 0)
+ {
+ for (int i = 0; i < info.num_param_reads && !collapse_loads; i++)
+ {
+ int map = parm_map_for
+ (gimple_call_arg (stmt,
+ info.reads[i].param));
+ if (map == -2)
+ continue;
+ else if (map == -1)
+ collapse_loads = true;
+ else
+ {
+ modref_access_node a = {map};
+ if (cur_summary->loads)
+ cur_summary->loads->insert (0, 0, a);
+ if (cur_summary->loads_lto)
+ cur_summary->loads_lto->insert (NULL, NULL, a);
+ }
+ }
+ }
+ else
+ collapse_loads = true;
+ if (collapse_loads)
+ {
+ if (cur_summary->loads)
+ cur_summary->loads->collapse ();
+ if (cur_summary->loads_lto)
+ cur_summary->loads_lto->collapse ();
+ }
+ if (ignore_stores)
+ ;
+ else if (info.num_param_writes >= 0)
+ {
+ if ((info.flags & AO_FUNCTION_ERRNO) && flag_errno_math)
+ cur_summary->writes_errno = true;
+ for (int i = 0; i < info.num_param_writes && !collapse_stores;
+ i++)
+ {
+ int map = parm_map_for
+ (gimple_call_arg (stmt,
+ info.writes[i].param));
+ if (map == -2)
+ continue;
+ else if (map == -1)
+ collapse_stores = true;
+ else
+ {
+ modref_access_node a = {map};
+ if (cur_summary->stores)
+ cur_summary->stores->insert (0, 0, a);
+ if (cur_summary->stores_lto)
+ cur_summary->stores_lto->insert (NULL, NULL, a);
+ }
+ }
+ }
+ else
+ collapse_stores = true;
+
+ if (collapse_stores)
+ {
+ if (cur_summary->stores)
+ cur_summary->stores->collapse ();
+ if (cur_summary->stores_lto)
+ cur_summary->stores_lto->collapse ();
+ }
+ return true;
+ }
+ else if (dump_file && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
+ fprintf (dump_file, " Unclassified builtin %s\n",
+ IDENTIFIER_POINTER (DECL_NAME (callee)));
+
struct cgraph_node *callee_node = cgraph_node::get_create (callee);
/* We can not safely optimize based on summary of callee if it does
@@ -772,6 +860,7 @@ analyze_function (function *f, bool ipa)
param_modref_max_accesses);
}
summary->finished = false;
+ summary->writes_errno = false;
int ecf_flags = flags_from_decl_or_type (current_function_decl);
auto_vec <gimple *, 32> recursive_calls;
@@ -872,6 +961,7 @@ modref_summaries::duplicate (cgraph_node *, cgraph_node *,
There are many missing cases that could be added incrementally: I tried to
keep only the logic that was there before.
modref_summary *dst_data)
{
dst_data->finished = src_data->finished;
+ dst_data->writes_errno = src_data->writes_errno;
if (src_data->stores)
{
dst_data->stores = modref_records::create_ggc
@@ -1151,6 +1241,7 @@ modref_write ()
write_modref_records (r->loads_lto, ob);
if (r->stores_lto)
write_modref_records (r->stores_lto, ob);
+ streamer_write_uhwi (ob, r->writes_errno);
}
}
streamer_write_char_stream (ob->main_stream, 0);
@@ -1204,6 +1295,7 @@ read_section (struct lto_file_decl_data *file_data, const char *data,
read_modref_records (&ib, data_in,
&modref_sum->stores,
&modref_sum->stores_lto);
+ modref_sum->writes_errno = streamer_read_uhwi (&ib);
if (dump_file)
{
fprintf (dump_file, "Read modref for %s\n",
@@ -1365,10 +1457,10 @@ compute_parm_map (cgraph_edge *callee_edge, vec<int> *parm_map)
= ipa_get_ith_jump_func (args, i);
if (jf)
{
- tree cst = ipa_value_from_jfunc (caller_parms_info,
- jf,
- ipa_get_type
- (callee_pi, i));
+ tree cst = NULL;
+ if (callee_pi)
+ cst = ipa_value_from_jfunc (caller_parms_info, jf,
+ ipa_get_type (callee_pi, i));
if (cst && points_to_local_or_readonly_memory_p (cst))
{
(*parm_map)[i] = -2;
@@ -1438,12 +1530,16 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
if (to_info->loads)
to_info->loads->merge (callee_info->loads, &parm_map);
- if (to_info->stores)
- to_info->stores->merge (callee_info->stores, &parm_map);
if (to_info->loads_lto)
to_info->loads_lto->merge (callee_info->loads_lto, &parm_map);
- if (to_info->stores_lto)
- to_info->stores_lto->merge (callee_info->stores_lto, &parm_map);
+ if (!ignore_stores_p (edge->callee->decl, flags))
+ {
+ if (to_info->stores)
+ to_info->stores->merge (callee_info->stores, &parm_map);
+ if (to_info->stores_lto)
+ to_info->stores_lto->merge (callee_info->stores_lto, &parm_map);
+ to_info->writes_errno |= callee_info->writes_errno;
+ }
}
if (!to_info->useful_p (flags))
summaries->remove (to);
@@ -1472,6 +1568,27 @@ collapse_loads (modref_summary *cur_summary)
return changed;
}
+/* Collapse stores and return true if something changed. */
+
+bool
+collapse_stores (modref_summary *cur_summary)
+{
+ bool changed = false;
+
+ if (cur_summary->stores && !cur_summary->stores->every_base)
+ {
+ cur_summary->stores->collapse ();
+ changed = true;
+ }
+ if (cur_summary->stores_lto
+ && !cur_summary->stores_lto->every_base)
+ {
+ cur_summary->stores_lto->collapse ();
+ changed = true;
+ }
+ return changed;
+}
+
/* Perform iterative dataflow on SCC component starting in COMPONENT_NODE. */
static void
@@ -1553,6 +1670,94 @@ modref_propagate_in_scc (cgraph_node *component_node)
bool ignore_stores = ignore_stores_p (cur->decl, flags);
+ struct ao_function_info info;
+ if (callee
+ && fndecl_built_in_p (callee->decl, BUILT_IN_NORMAL)
+ && ao_classify_builtin (callee->decl, &info)
+ && !(info.flags & AO_FUNCTION_BARRIER))
+ {
+ bool collapse_loads_p = false, collapse_stores_p = false;
+ auto_vec <int, 32> parm_map;
+
+ compute_parm_map (callee_edge, &parm_map);
+
+ if (info.num_param_reads >= 0)
+ {
+ for (int i = 0; i < info.num_param_reads
+ && !collapse_loads_p; i++)
+ {
+ int map = i < (int) parm_map.length ()
+ ? parm_map[i] : -1;
+
+ if (dump_file && i >= (int) parm_map.length ())
+ fprintf (dump_file, " Untracked param %i\n",
+ i);
+
+ if (map == -2)
+ continue;
+ else if (map == -1)
+ collapse_loads_p = true;
+ else
+ {
+ modref_access_node a = {map};
+ if (cur_summary->loads)
+ changed |= cur_summary->loads->insert (0, 0, a);
+ if (cur_summary->loads_lto)
+ changed |= cur_summary->loads_lto->insert
+ (NULL, NULL, a);
+ }
+ }
+ }
+ else
+ collapse_loads_p = true;
+ if (collapse_loads_p)
+ changed |= collapse_loads (cur_summary);
+ if (ignore_stores)
+ ;
+ else if (info.num_param_writes >= 0)
+ {
+ if ((info.flags & AO_FUNCTION_ERRNO) && flag_errno_math)
+ cur_summary->writes_errno = true;
+ for (int i = 0;
+ i < info.num_param_writes && !collapse_stores_p;
+ i++)
+ {
+ int map = i < (int) parm_map.length ()
+ ? parm_map[i] : -1;
+
+ if (dump_file && i >= (int) parm_map.length ())
+ fprintf (dump_file, " Untracked param %i\n",
+ i);
+
+ if (map == -2)
+ continue;
+ else if (map == -1)
+ collapse_stores_p = true;
+ else
+ {
+ modref_access_node a = {map};
+ if (cur_summary->stores)
+ changed |= cur_summary->stores->insert
+ (0, 0, a);
+ if (cur_summary->stores_lto)
+ changed |= cur_summary->stores_lto->insert
+ (NULL, NULL, a);
+ }
+ }
+ }
+ else
+ collapse_stores_p = true;
+
+ if (collapse_stores_p)
+ changed |= collapse_stores (cur_summary);
+
+ continue;
+ }
+ else if (dump_file && callee
+ && fndecl_built_in_p (callee->decl, BUILT_IN_NORMAL))
+ fprintf (dump_file, " Unclassified builtin %s\n",
+ IDENTIFIER_POINTER (DECL_NAME (callee->decl)));
+
/* We don't know anything about CALLEE, hence we cannot tell
anything about the entire component. */
diff --git a/gcc/ipa-modref.h b/gcc/ipa-modref.h
index b6621b498f0..a9c71800750 100644
--- a/gcc/ipa-modref.h
+++ b/gcc/ipa-modref.h
@@ -37,6 +37,7 @@ struct GTY(()) modref_summary
modref_records_lto *loads_lto;
modref_records_lto *stores_lto;
bool finished;
+ bool writes_errno;
modref_summary ();
~modref_summary ();
diff --git a/gcc/ipa-modref.h b/gcc/ipa-modref.h
index b6621b498f0..a9c71800750 100644
--- a/gcc/ipa-modref.h
+++ b/gcc/ipa-modref.h
@@ -37,6 +37,7 @@ struct GTY(()) modref_summary
modref_records_lto *loads_lto;
modref_records_lto *stores_lto;
bool finished;
+ bool writes_errno;
modref_summary ();
~modref_summary ();
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index fe390d4ffbe..c182e7bb39c 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -2961,7 +3280,9 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, bool tbaa_p)
modref_summary *summary = get_modref_function_summary (node);
if (summary)
{
- if (!modref_may_conflict (call, summary->stores, ref, tbaa_p))
+ if (!modref_may_conflict (call, summary->stores, ref, tbaa_p)
+ && (!summary->writes_errno
+ || !targetm.ref_may_alias_errno (ref)))
{
alias_stats.modref_clobber_no_alias++;
if (dump_file && (dump_flags & TDF_DETAILS))
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-09-27 22:31 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-27 22:31 Add handling of bulitins to ipa-modref Jan Hubicka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).