diff options
author | Jan Hubicka <jh@suse.cz> | 2021-11-11 16:06:48 +0100 |
---|---|---|
committer | Jan Hubicka <jh@suse.cz> | 2021-11-11 16:07:47 +0100 |
commit | 8d3abf42d5c2ccd5c5e879088fdf6e071c3d1b9e (patch) | |
tree | 13251c4e2b5b00ad45b96c51eb6ca3a8f2ea6ae9 | |
parent | fac4c4bdab1735bd8a87e37c519f0260e4769f2a (diff) | |
download | gcc-8d3abf42d5c2ccd5c5e879088fdf6e071c3d1b9e.zip gcc-8d3abf42d5c2ccd5c5e879088fdf6e071c3d1b9e.tar.gz gcc-8d3abf42d5c2ccd5c5e879088fdf6e071c3d1b9e.tar.bz2 |
Fix some side cases of side effects discovery
I wrote script comparing modref pure/const discovery with ipa-pure-const
and found mistakes on both ends. This plugs the modref differences in handling
looping pure consts which were previously missed due to early exits on
ECF_CONST | ECF_PURE. Those early exists are bit anoying and I think as
a cleanup I may just drop some of them as premature optimizations coming from
time modref was very simplistic on what it propagates.
gcc/ChangeLog:
2021-11-11 Jan Hubicka <hubicka@ucw.cz>
* ipa-modref.c (modref_summary::useful_p): Check also for side-effects
with looping const/pure.
(modref_summary_lto::useful_p): Likewise.
(merge_call_side_effects): Merge side effects before early exit
for pure/const.
(process_fnspec): Also handle pure functions.
(analyze_call): Do not early exit on looping pure const.
(propagate_unknown_call): Also handle nontrivial SCC as side-effect.
(modref_propagate_in_scc): Update.
-rw-r--r-- | gcc/ipa-modref.c | 100 |
1 files changed, 61 insertions, 39 deletions
diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index f8b7b90..45b391a 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -331,11 +331,11 @@ modref_summary::useful_p (int ecf_flags, bool check_flags) && remove_useless_eaf_flags (static_chain_flags, ecf_flags, false)) return true; if (ecf_flags & (ECF_CONST | ECF_NOVOPS)) - return false; + return (!side_effects && (ecf_flags & ECF_LOOPING_CONST_OR_PURE)); if (loads && !loads->every_base) return true; if (ecf_flags & ECF_PURE) - return false; + return (!side_effects && (ecf_flags & ECF_LOOPING_CONST_OR_PURE)); return stores && !stores->every_base; } @@ -416,11 +416,11 @@ modref_summary_lto::useful_p (int ecf_flags, bool check_flags) && remove_useless_eaf_flags (static_chain_flags, ecf_flags, false)) return true; if (ecf_flags & (ECF_CONST | ECF_NOVOPS)) - return false; + return (!side_effects && (ecf_flags & ECF_LOOPING_CONST_OR_PURE)); if (loads && !loads->every_base) return true; if (ecf_flags & ECF_PURE) - return false; + return (!side_effects && (ecf_flags & ECF_LOOPING_CONST_OR_PURE)); return stores && !stores->every_base; } @@ -925,6 +925,18 @@ merge_call_side_effects (modref_summary *cur_summary, auto_vec <modref_parm_map, 32> parm_map; modref_parm_map chain_map; bool changed = false; + int flags = gimple_call_flags (stmt); + + if (!cur_summary->side_effects && callee_summary->side_effects) + { + if (dump_file) + fprintf (dump_file, " - merging side effects.\n"); + cur_summary->side_effects = true; + changed = true; + } + + if (flags & (ECF_CONST | ECF_NOVOPS)) + return changed; /* We can not safely optimize based on summary of callee if it does not always bind to current def: it is possible that memory load @@ -988,12 +1000,6 @@ merge_call_side_effects (modref_summary *cur_summary, changed = true; } } - if (!cur_summary->side_effects - && callee_summary->side_effects) - { - cur_summary->side_effects = true; - changed = true; - } return changed; } @@ -1091,7 +1097,7 @@ process_fnspec (modref_summary *cur_summary, attr_fnspec fnspec = gimple_call_fnspec (call); int flags = gimple_call_flags (call); - if (!(flags & (ECF_CONST | ECF_NOVOPS)) + if (!(flags & (ECF_CONST | ECF_NOVOPS | ECF_PURE)) || (flags & ECF_LOOPING_CONST_OR_PURE) || (cfun->can_throw_non_call_exceptions && stmt_could_throw_p (cfun, call))) @@ -1101,6 +1107,8 @@ process_fnspec (modref_summary *cur_summary, if (cur_summary_lto) cur_summary_lto->side_effects = true; } + if (flags & (ECF_CONST | ECF_NOVOPS)) + return true; if (!fnspec.known_p ()) { if (dump_file && gimple_call_builtin_p (call, BUILT_IN_NORMAL)) @@ -1203,7 +1211,8 @@ analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto, /* Check flags on the function call. In certain cases, analysis can be simplified. */ int flags = gimple_call_flags (stmt); - if (flags & (ECF_CONST | ECF_NOVOPS)) + if ((flags & (ECF_CONST | ECF_NOVOPS)) + && !(flags & ECF_LOOPING_CONST_OR_PURE)) { if (dump_file) fprintf (dump_file, @@ -3963,7 +3972,8 @@ static bool propagate_unknown_call (cgraph_node *node, cgraph_edge *e, int ecf_flags, modref_summary *cur_summary, - modref_summary_lto *cur_summary_lto) + modref_summary_lto *cur_summary_lto, + bool nontrivial_scc) { bool changed = false; class fnspec_summary *fnspec_sum = fnspec_summaries->get (e); @@ -3973,12 +3983,12 @@ propagate_unknown_call (cgraph_node *node, if (e->callee && builtin_safe_for_const_function_p (&looping, e->callee->decl)) { - if (cur_summary && !cur_summary->side_effects) + if (looping && cur_summary && !cur_summary->side_effects) { cur_summary->side_effects = true; changed = true; } - if (cur_summary_lto && !cur_summary_lto->side_effects) + if (looping && cur_summary_lto && !cur_summary_lto->side_effects) { cur_summary_lto->side_effects = true; changed = true; @@ -3986,8 +3996,9 @@ propagate_unknown_call (cgraph_node *node, return changed; } - if (!(ecf_flags & (ECF_CONST | ECF_NOVOPS)) - || (ecf_flags & ECF_LOOPING_CONST_OR_PURE)) + if (!(ecf_flags & (ECF_CONST | ECF_NOVOPS | ECF_PURE)) + || (ecf_flags & ECF_LOOPING_CONST_OR_PURE) + || nontrivial_scc) { if (cur_summary && !cur_summary->side_effects) { @@ -4000,6 +4011,8 @@ propagate_unknown_call (cgraph_node *node, changed = true; } } + if (ecf_flags & (ECF_CONST | ECF_NOVOPS)) + return changed; if (fnspec_sum && compute_parm_map (e, &parm_map)) @@ -4126,6 +4139,8 @@ modref_propagate_in_scc (cgraph_node *component_node) while (changed) { + bool nontrivial_scc + = ((struct ipa_dfs_info *) component_node->aux)->next_cycle; changed = false; for (struct cgraph_node *cur = component_node; cur; cur = ((struct ipa_dfs_info *) cur->aux)->next_cycle) @@ -4151,14 +4166,12 @@ modref_propagate_in_scc (cgraph_node *component_node) for (cgraph_edge *e = cur->indirect_calls; e; e = e->next_callee) { - if (e->indirect_info->ecf_flags & (ECF_CONST | ECF_NOVOPS)) - continue; if (dump_file) - fprintf (dump_file, " Indirect call" - "collapsing loads\n"); + fprintf (dump_file, " Indirect call\n"); if (propagate_unknown_call (node, e, e->indirect_info->ecf_flags, - cur_summary, cur_summary_lto)) + cur_summary, cur_summary_lto, + nontrivial_scc)) { changed = true; remove_useless_summaries (node, &cur_summary, @@ -4180,8 +4193,9 @@ modref_propagate_in_scc (cgraph_node *component_node) modref_summary_lto *callee_summary_lto = NULL; struct cgraph_node *callee; - if (flags & (ECF_CONST | ECF_NOVOPS) - || !callee_edge->inline_failed) + if (!callee_edge->inline_failed + || ((flags & (ECF_CONST | ECF_NOVOPS)) + && !(flags & ECF_LOOPING_CONST_OR_PURE))) continue; /* Get the callee and its summary. */ @@ -4210,7 +4224,8 @@ modref_propagate_in_scc (cgraph_node *component_node) " or not available\n"); changed |= propagate_unknown_call (node, callee_edge, flags, - cur_summary, cur_summary_lto); + cur_summary, cur_summary_lto, + nontrivial_scc); if (!cur_summary && !cur_summary_lto) break; continue; @@ -4226,7 +4241,8 @@ modref_propagate_in_scc (cgraph_node *component_node) fprintf (dump_file, " No call target summary\n"); changed |= propagate_unknown_call (node, callee_edge, flags, - cur_summary, NULL); + cur_summary, NULL, + nontrivial_scc); } if (cur_summary_lto && !(callee_summary_lto = summaries_lto->get (callee))) @@ -4235,9 +4251,27 @@ modref_propagate_in_scc (cgraph_node *component_node) fprintf (dump_file, " No call target summary\n"); changed |= propagate_unknown_call (node, callee_edge, flags, - NULL, cur_summary_lto); + NULL, cur_summary_lto, + nontrivial_scc); } + if (callee_summary && !cur_summary->side_effects + && (callee_summary->side_effects + || callee_edge->recursive_p ())) + { + cur_summary->side_effects = true; + changed = true; + } + if (callee_summary_lto && !cur_summary_lto->side_effects + && (callee_summary_lto->side_effects + || callee_edge->recursive_p ())) + { + cur_summary_lto->side_effects = true; + changed = true; + } + if (flags & (ECF_CONST | ECF_NOVOPS)) + continue; + /* We can not safely optimize based on summary of callee if it does not always bind to current def: it is possible that memory load was optimized out earlier which may not happen in @@ -4265,12 +4299,6 @@ modref_propagate_in_scc (cgraph_node *component_node) changed |= cur_summary->loads->merge (callee_summary->loads, &parm_map, &chain_map, !first); - if (!cur_summary->side_effects - && callee_summary->side_effects) - { - cur_summary->side_effects = true; - changed = true; - } if (!ignore_stores) { changed |= cur_summary->stores->merge @@ -4289,12 +4317,6 @@ modref_propagate_in_scc (cgraph_node *component_node) changed |= cur_summary_lto->loads->merge (callee_summary_lto->loads, &parm_map, &chain_map, !first); - if (!cur_summary_lto->side_effects - && callee_summary_lto->side_effects) - { - cur_summary_lto->side_effects = true; - changed = true; - } if (!ignore_stores) { changed |= cur_summary_lto->stores->merge |