https://gcc.gnu.org/g:d5b42d1aa0cdfc11dc400ce66fcd4d13f8622b57

commit r13-9112-gd5b42d1aa0cdfc11dc400ce66fcd4d13f8622b57
Author: Jan Hubicka <hubi...@ucw.cz>
Date:   Mon Jul 22 23:01:50 2024 +0200

    Fix handling of ICF_NOVOPS in ipa-modref
    
    As shown in somewhat convoluted testcase, ipa-modref is mistreating
    ECF_NOVOPS as "having no side effects".  This come from time when
    modref cared only about memory accesses and thus it was possible to
    shortcut on it.
    
    This patch removes (hopefully) all those bad shortcuts.
    Bootstrapped/regtested x86_64-linux, comitted.
    
    gcc/ChangeLog:
    
            PR ipa/109985
    
            * ipa-modref.cc (modref_summary::useful_p): Fix handling of 
ECF_NOVOPS.
            (modref_access_analysis::process_fnspec): Likevise.
            (modref_access_analysis::analyze_call): Likevise.
            (propagate_unknown_call): Likevise.
            (modref_propagate_in_scc): Likevise.
            (modref_propagate_flags_in_scc): Likewise.
            (ipa_merge_modref_summary_after_inlining): Likewise.
    
    (cherry picked from commit efcbe7b985e24ac002a863afd609c44a67761195)

Diff:
---
 gcc/ipa-modref.cc | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc
index d62a5703a21b..c98e38524dfb 100644
--- a/gcc/ipa-modref.cc
+++ b/gcc/ipa-modref.cc
@@ -332,7 +332,7 @@ modref_summary::useful_p (int ecf_flags, bool check_flags)
   if (check_flags
       && remove_useless_eaf_flags (static_chain_flags, ecf_flags, false))
     return true;
-  if (ecf_flags & (ECF_CONST | ECF_NOVOPS))
+  if (ecf_flags & ECF_CONST)
     return ((!side_effects || !nondeterministic)
            && (ecf_flags & ECF_LOOPING_CONST_OR_PURE));
   if (loads && !loads->every_base)
@@ -1261,7 +1261,7 @@ modref_access_analysis::merge_call_side_effects
   int flags = gimple_call_flags (call);
 
   /* Nothing to do for non-looping cont functions.  */
-  if ((flags & (ECF_CONST | ECF_NOVOPS))
+  if ((flags & ECF_CONST)
       && !(flags & ECF_LOOPING_CONST_OR_PURE))
     return false;
 
@@ -1274,7 +1274,7 @@ modref_access_analysis::merge_call_side_effects
   /* Merge side effects and non-determinism.
      PURE/CONST flags makes functions deterministic and if there is
      no LOOPING_CONST_OR_PURE they also have no side effects.  */
-  if (!(flags & (ECF_CONST | ECF_NOVOPS | ECF_PURE))
+  if (!(flags & (ECF_CONST | ECF_PURE))
       || (flags & ECF_LOOPING_CONST_OR_PURE))
     {
       if (!m_summary->side_effects && callee_summary->side_effects)
@@ -1463,7 +1463,7 @@ modref_access_analysis::process_fnspec (gcall *call)
 
   /* PURE/CONST flags makes functions deterministic and if there is
      no LOOPING_CONST_OR_PURE they also have no side effects.  */
-  if (!(flags & (ECF_CONST | ECF_NOVOPS | ECF_PURE))
+  if (!(flags & (ECF_CONST | ECF_PURE))
       || (flags & ECF_LOOPING_CONST_OR_PURE)
       || (cfun->can_throw_non_call_exceptions
          && stmt_could_throw_p (cfun, call)))
@@ -1602,12 +1602,12 @@ modref_access_analysis::analyze_call (gcall *stmt)
       print_gimple_stmt (dump_file, stmt, 0);
     }
 
-  if ((flags & (ECF_CONST | ECF_NOVOPS))
+  if ((flags & ECF_CONST)
       && !(flags & ECF_LOOPING_CONST_OR_PURE))
     {
       if (dump_file)
        fprintf (dump_file,
-                " - ECF_CONST | ECF_NOVOPS, ignoring all stores and all loads "
+                " - ECF_CONST, ignoring all stores and all loads "
                 "except for args.\n");
       return;
     }
@@ -1622,7 +1622,13 @@ modref_access_analysis::analyze_call (gcall *stmt)
       if (dump_file)
        fprintf (dump_file, gimple_call_internal_p (stmt)
                 ? " - Internal call" : " - Indirect call.\n");
-      process_fnspec (stmt);
+      if (flags & ECF_NOVOPS)
+        {
+         set_side_effects ();
+         set_nondeterministic ();
+        }
+      else
+       process_fnspec (stmt);
       return;
     }
   /* We only need to handle internal calls in IPA mode.  */
@@ -4514,7 +4520,7 @@ propagate_unknown_call (cgraph_node *node,
       return changed;
     }
 
-  if (!(ecf_flags & (ECF_CONST | ECF_NOVOPS | ECF_PURE))
+  if (!(ecf_flags & (ECF_CONST | ECF_PURE))
       || (ecf_flags & ECF_LOOPING_CONST_OR_PURE)
       || nontrivial_scc)
     {
@@ -4728,7 +4734,7 @@ modref_propagate_in_scc (cgraph_node *component_node)
              struct cgraph_node *callee;
 
              if (!callee_edge->inline_failed
-                || ((flags & (ECF_CONST | ECF_NOVOPS))
+                || ((flags & ECF_CONST)
                     && !(flags & ECF_LOOPING_CONST_OR_PURE)))
                continue;
 
@@ -5151,8 +5157,8 @@ modref_propagate_flags_in_scc (cgraph_node 
*component_node)
            {
              escape_summary *sum = escape_summaries->get (e);
 
-             if (!sum || (e->indirect_info->ecf_flags
-                          & (ECF_CONST | ECF_NOVOPS)))
+             if (!sum || ((e->indirect_info->ecf_flags & ECF_CONST)
+                 && !(e->indirect_info->ecf_flags & 
ECF_LOOPING_CONST_OR_PURE)))
                continue;
 
              changed |= modref_merge_call_site_flags
@@ -5177,8 +5183,8 @@ modref_propagate_flags_in_scc (cgraph_node 
*component_node)
              modref_summary_lto *callee_summary_lto = NULL;
              struct cgraph_node *callee;
 
-             if (ecf_flags & (ECF_CONST | ECF_NOVOPS)
-                 || !callee_edge->inline_failed)
+             if ((ecf_flags & ECF_CONST)
+                 && !(ecf_flags & ECF_LOOPING_CONST_OR_PURE))
                continue;
 
              /* Get the callee and its summary.  */
@@ -5276,7 +5282,7 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge 
*edge)
 
   if (!callee_info && to_info)
     {
-      if (!(flags & (ECF_CONST | ECF_NOVOPS)))
+      if (!(flags & (ECF_CONST | ECF_PURE | ECF_NOVOPS)))
        to_info->loads->collapse ();
       if (!ignore_stores)
        to_info->stores->collapse ();
@@ -5291,7 +5297,7 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge 
*edge)
   /* Merge side effects and non-determinism.
      PURE/CONST flags makes functions deterministic and if there is
      no LOOPING_CONST_OR_PURE they also have no side effects.  */
-  if (!(flags & (ECF_CONST | ECF_NOVOPS | ECF_PURE))
+  if (!(flags & (ECF_CONST | ECF_PURE))
       || (flags & ECF_LOOPING_CONST_OR_PURE))
     {
       if (to_info)

Reply via email to