diff mbox

One possible fix for the compute_bb_predicate oscillation (PR ipa/60013)

Message ID 20140206064317.GA29096@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Feb. 6, 2014, 6:43 a.m. UTC
Hi,
this is variant of patch I am testing (thanks Jakub for the hard analysis).
The dataflow was supposed to be monotonous by keeping the rule that oldvalue
imply new value at each step.  This is broken by the approximation done by
and/or operations.

Instead of dropping to true, it seems easier to simply or the result before
updating.  This operation should be no-op until we hit the clause limit.

Bootstrapping/regtesting x86_64-linux, will commit if it passes.

Honza

	* ipa-inline-analysis.c (compute_bb_predicates): Ensure monotonicity
	of the dataflow.

	gcc.dg/pr60013.c: New testcase.
diff mbox

Patch

Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c	(revision 207514)
+++ ipa-inline-analysis.c	(working copy)
@@ -310,7 +310,7 @@  add_clause (conditions conditions, struc
   if (false_predicate_p (p))
     return;
 
-  /* No one should be sily enough to add false into nontrivial clauses.  */
+  /* No one should be silly enough to add false into nontrivial clauses.  */
   gcc_checking_assert (!(clause & (1 << predicate_false_condition)));
 
   /* Look where to insert the clause.  At the same time prune out
@@ -1035,7 +1035,7 @@  inline_node_removal_hook (struct cgraph_
   memset (info, 0, sizeof (inline_summary_t));
 }
 
-/* Remap predicate P of former function to be predicate of duplicated functoin.
+/* Remap predicate P of former function to be predicate of duplicated function.
    POSSIBLE_TRUTHS is clause of possible truths in the duplicated node,
    INFO is inline summary of the duplicated node.  */
 
@@ -1887,8 +1887,15 @@  compute_bb_predicates (struct cgraph_nod
 		}
 	      else if (!predicates_equal_p (&p, (struct predicate *) bb->aux))
 		{
-		  done = false;
-		  *((struct predicate *) bb->aux) = p;
+		  /* This OR operation is needed to ensure monotonous data flow
+		     in the case we hit the limit on number of clauses and the
+		     and/or operations above give approximate answers.  */
+		  p = or_predicates (summary->conds, &p, (struct predicate *)bb->aux);
+	          if (!predicates_equal_p (&p, (struct predicate *) bb->aux))
+		    {
+		      done = false;
+		      *((struct predicate *) bb->aux) = p;
+		    }
 		}
 	    }
 	}
Index: testsuite/gcc.dg/pr60013.c
===================================================================
--- testsuite/gcc.dg/pr60013.c	(revision 0)
+++ testsuite/gcc.dg/pr60013.c	(revision 0)
@@ -0,0 +1,47 @@ 
+/* PR ipa/60013 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef long int jmp_buf[64];
+extern int _setjmp (jmp_buf) __attribute__ ((__nothrow__));
+struct S { int a, b, c; };
+extern struct S *baz (struct S *);
+static jmp_buf j;
+
+static inline int
+bar (int b, int d)
+{
+  return (b & d) < 0;
+}
+
+struct S *
+foo (int a, struct S *b, struct S *c, struct S *d)
+{
+  if (b->a == 0)
+    {
+      switch (a)
+	{
+	case 8:
+	  return baz (b);
+	case 7:
+	  bar (b->c, c->b);
+	  return 0;
+	case 6:
+	case 5:
+	case 4:
+	  return baz (c);
+	case 3:
+	case 2:
+	  return baz (d);
+	}
+      return 0;
+    }
+  if (b->a == 1)
+    {
+      if (baz (c))
+	return c;
+      else if (_setjmp (j))
+	baz (b);
+    }
+  return 0;
+}