Hi,
while analyzing the previous bug I noticed that nothrow propagation handles
visibility wrong wrt aliases.  This patch fixes it and also makes the code a bit
more effective.

Bootstrapped/regtested x86_64-linux, comitted.

Honza

        * ipa-pure-const.c (ignore_edge): Rename to ...
        (ignore_edge_for_nothrow) ... this one; also ignore eges to
        interposable functions or ones that can not throw.
        (propagate_nothrow): Fix handling of availability.
Index: ipa-pure-const.c
===================================================================
--- ipa-pure-const.c    (revision 231216)
+++ ipa-pure-const.c    (working copy)
@@ -1124,11 +1124,18 @@ pure_const_read_summary (void)
     }
 }
 
+/* We only propagate across edges that can throw externally and their callee
+   is not interposable.  */
 
 static bool
-ignore_edge (struct cgraph_edge *e)
+ignore_edge_for_nothrow (struct cgraph_edge *e)
 {
-  return (!e->can_throw_external);
+  if (!e->can_throw_external || TREE_NOTHROW (e->callee->decl))
+    return true;
+
+  enum availability avail;
+  cgraph_node *n = e->callee->function_or_virtual_thunk_symbol (&avail);
+  return (avail <= AVAIL_INTERPOSABLE || TREE_NOTHROW (n->decl));
 }
 
 /* Return true if NODE is self recursive function.
@@ -1491,7 +1498,8 @@ propagate_nothrow (void)
   int i;
   struct ipa_dfs_info * w_info;
 
-  order_pos = ipa_reduced_postorder (order, true, false, ignore_edge);
+  order_pos = ipa_reduced_postorder (order, true, false,
+                                    ignore_edge_for_nothrow);
   if (dump_file)
     {
       cgraph_node::dump_cgraph (dump_file);
@@ -1515,32 +1523,38 @@ propagate_nothrow (void)
       while (w && !can_throw)
        {
          struct cgraph_edge *e, *ie;
-         funct_state w_l = get_function_state (w);
-
-         if (w_l->can_throw
-             || w->get_availability () == AVAIL_INTERPOSABLE)
-           can_throw = true;
 
-         for (e = w->callees; e && !can_throw; e = e->next_callee)
+         if (!TREE_NOTHROW (w->decl))
            {
-             enum availability avail;
-             struct cgraph_node *y = e->callee->
-                               function_or_virtual_thunk_symbol (&avail);
+             funct_state w_l = get_function_state (w);
 
-             if (avail > AVAIL_INTERPOSABLE)
+             if (w_l->can_throw
+                 || w->get_availability () == AVAIL_INTERPOSABLE)
+               can_throw = true;
+
+             for (e = w->callees; e && !can_throw; e = e->next_callee)
                {
-                 funct_state y_l = get_function_state (y);
+                 enum availability avail;
+
+                 if (!e->can_throw_external || TREE_NOTHROW (e->callee->decl))
+                   continue;
+
+                 struct cgraph_node *y = e->callee->
+                                   function_or_virtual_thunk_symbol (&avail);
 
-                 if (y_l->can_throw && !TREE_NOTHROW (w->decl)
-                     && e->can_throw_external)
+                 /* We can use info about the callee only if we know it can
+                    not be interposed.  */
+                 if (avail <= AVAIL_INTERPOSABLE
+                     || (!TREE_NOTHROW (y->decl)
+                         && get_function_state (y)->can_throw))
                    can_throw = true;
                }
-             else if (e->can_throw_external && !TREE_NOTHROW (y->decl))
-               can_throw = true;
+             for (ie = w->indirect_calls; ie && !can_throw;
+                  ie = ie->next_callee)
+               if (ie->can_throw_external
+                   && !(ie->indirect_info->ecf_flags & ECF_NOTHROW))
+                 can_throw = true;
            }
-          for (ie = w->indirect_calls; ie && !can_throw; ie = ie->next_callee)
-           if (ie->can_throw_external)
-             can_throw = true;
          w_info = (struct ipa_dfs_info *) w->aux;
          w = w_info->next_cycle;
        }
@@ -1650,7 +1664,7 @@ skip_function_for_local_pure_const (stru
   if (node->get_availability () <= AVAIL_INTERPOSABLE)
     {
       if (dump_file)
-        fprintf (dump_file, "Function is not available or overwritable; not 
analyzing.\n");
+        fprintf (dump_file, "Function is not available or interposable; not 
analyzing.\n");
       return true;
     }
   return false;

Reply via email to