This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix ipa-pure-const can_throw propagation


Hi!

The following testcase is miscompiled starting with 4.6.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

For 4.9/4.8, I'd prefer to use a one-liner instead:
-          for (ie = node->indirect_calls; ie; ie = ie->next_callee)
+          for (ie = w->indirect_calls; ie; ie = ie->next_callee)

2014-11-12  Jakub Jelinek  <jakub@redhat.com>

	PR ipa/63838
	* ipa-pure-const.c (propagate_nothrow): Walk w->indirect_calls
	chain instead of node->indirect_calls.  Put !can_throw into
	conditions of all the loops.

	* g++.dg/ipa/pr63838.C: New test.

--- gcc/ipa-pure-const.c.jj	2014-11-11 00:06:11.000000000 +0100
+++ gcc/ipa-pure-const.c	2014-11-12 18:32:56.351139726 +0100
@@ -1448,7 +1448,7 @@ propagate_nothrow (void)
 
       /* Find the worst state for any node in the cycle.  */
       w = node;
-      while (w)
+      while (w && !can_throw)
 	{
 	  struct cgraph_edge *e, *ie;
 	  funct_state w_l = get_function_state (w);
@@ -1457,10 +1457,7 @@ propagate_nothrow (void)
 	      || w->get_availability () == AVAIL_INTERPOSABLE)
 	    can_throw = true;
 
-	  if (can_throw)
-	    break;
-
-	  for (e = w->callees; e; e = e->next_callee)
+	  for (e = w->callees; e && !can_throw; e = e->next_callee)
 	    {
 	      enum availability avail;
 	      struct cgraph_node *y = e->callee->function_symbol (&avail);
@@ -1469,8 +1466,6 @@ propagate_nothrow (void)
 		{
 		  funct_state y_l = get_function_state (y);
 
-		  if (can_throw)
-		    break;
 		  if (y_l->can_throw && !TREE_NOTHROW (w->decl)
 		      && e->can_throw_external)
 		    can_throw = true;
@@ -1478,12 +1473,9 @@ propagate_nothrow (void)
 	      else if (e->can_throw_external && !TREE_NOTHROW (y->decl))
 	        can_throw = true;
 	    }
-          for (ie = node->indirect_calls; ie; ie = ie->next_callee)
+          for (ie = w->indirect_calls; ie && !can_throw; ie = ie->next_callee)
 	    if (ie->can_throw_external)
-	      {
-		can_throw = true;
-		break;
-	      }
+	      can_throw = true;
 	  w_info = (struct ipa_dfs_info *) w->aux;
 	  w = w_info->next_cycle;
 	}
@@ -1794,5 +1786,3 @@ make_pass_warn_function_noreturn (gcc::c
 {
   return new pass_warn_function_noreturn (ctxt);
 }
-
-
--- gcc/testsuite/g++.dg/ipa/pr63838.C.jj	2014-11-12 19:48:50.403403040 +0100
+++ gcc/testsuite/g++.dg/ipa/pr63838.C	2014-11-12 19:48:59.650247907 +0100
@@ -0,0 +1,56 @@
+// PR ipa/63838
+// { dg-do run }
+// { dg-options "-O2 -fdump-ipa-pure-const" }
+// { dg-final { scan-ipa-dump-not "Function found to be nothrow: void foo" "pure-const" } }
+// { dg-final { scan-ipa-dump-not "Function found to be nothrow: void bar" "pure-const" } }
+// { dg-final { cleanup-ipa-dump "pure-const" } }
+
+__attribute__((noinline, noclone)) static void bar (int);
+volatile int v;
+void (*fn) ();
+struct S { S () { v++; } ~S () { v++; } };
+
+__attribute__((noinline, noclone)) static void
+foo (int x)
+{
+  v++;
+  if (x == 5)
+    bar (x);
+}
+
+__attribute__((noinline, noclone)) static void
+bar (int x)
+{
+  v++;
+  if (x == 6)
+    foo (x);
+  else if (x == 5)
+    fn ();
+}
+
+__attribute__((noinline, noclone)) int
+baz (int x)
+{
+  S s;
+  foo (x);
+}
+
+void
+throw0 ()
+{
+  throw 0;
+}
+
+int
+main ()
+{
+  fn = throw0;
+  asm volatile ("" : : : "memory");
+  try
+    {
+      baz (5);
+    }
+  catch (int)
+    {
+    }
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]