From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from nikam.ms.mff.cuni.cz (nikam.ms.mff.cuni.cz [195.113.20.16]) by sourceware.org (Postfix) with ESMTPS id E5179385701E; Sun, 27 Sep 2020 22:31:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E5179385701E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=ucw.cz Authentication-Results: sourceware.org; spf=none smtp.mailfrom=hubicka@kam.mff.cuni.cz Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 706BB282ADB; Mon, 28 Sep 2020 00:31:50 +0200 (CEST) Date: Mon, 28 Sep 2020 00:31:50 +0200 From: Jan Hubicka To: gcc-patches@gcc.gnu.org, d@dcepelik.cz, rbiener@suse.de, fortran@gcc.gnu.org Subject: Add handling of bulitins to ipa-modref Message-ID: <20200927223150.GE52458@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-Spam-Status: No, score=-14.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Sep 2020 22:31:55 -0000 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 * 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 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 *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 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))