2010-12-14  Sandra Loosemore  <sandra@codesourcery.com>

	Backport from mainline:

	2010-12-14  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/46909

	gcc/
	* tree-ssa-ccp.c (and_var_with_comparison_1): Save partial
	result even in the is_and case, if both partial results
	are the same, return it.
	(or_var_with_comparison_1): Use is_or predicate instead of
	innercode == TRUTH_OR_EXPR test.  Save partial result
	even in the is_or case, if both partial results are the
	same, return it.  In the !is_or case when both partial
	results are the same, return the partial result instead
	of boolean_true_node.

	gcc/testsuite/
	* gcc.c-torture/execute/pr46909-1.c: New test.
	* gcc.c-torture/execute/pr46909-2.c: New test.
	* gcc.dg/pr46909.c: New test.

=== added file 'gcc/testsuite/gcc.c-torture/execute/pr46909-1.c'
--- old/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c	1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c	2011-01-05 11:27:00 +0000
@@ -0,0 +1,22 @@
+/* PR tree-optimization/46909 */
+
+extern void abort ();
+
+int
+__attribute__ ((__noinline__))
+foo (unsigned int x)
+{
+  if (! (x == 4 || x == 6) || (x == 2 || x == 6))
+    return 1;
+  return -1;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = -10; i < 10; i++)
+    if (foo (i) != 1 - 2 * (i == 4))
+      abort ();
+  return 0;
+}

=== added file 'gcc/testsuite/gcc.c-torture/execute/pr46909-2.c'
--- old/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c	1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c	2011-01-05 11:27:00 +0000
@@ -0,0 +1,22 @@
+/* PR tree-optimization/46909 */
+
+extern void abort (void);
+
+int
+__attribute__((noinline))
+foo (int x)
+{
+  if ((x != 0 && x != 13) || x == 5 || x == 20)
+    return 1;
+  return -1;
+}
+
+int
+main (void)
+{
+  int i;
+  for (i = -10; i < 30; i++)
+    if (foo (i) != 1 - 2 * (i == 0) - 2 * (i == 13))
+      abort ();
+  return 0;
+}

=== added file 'gcc/testsuite/gcc.dg/pr46909.c'
--- old/gcc/testsuite/gcc.dg/pr46909.c	1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.dg/pr46909.c	2011-01-05 11:27:00 +0000
@@ -0,0 +1,17 @@
+/* PR tree-optimization/46909 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ifcombine" } */
+
+extern void abort ();
+
+int
+__attribute__ ((__noinline__))
+foo (unsigned int x)
+{
+  if (! (x == 4 || x == 6) || (x == 2 || x == 6))
+    return 1;
+  return -1;
+}
+
+/* { dg-final { scan-tree-dump "optimizing two comparisons to x_\[0-9\]+\\(D\\) != 4" "ifcombine" } } */
+/* { dg-final { cleanup-tree-dump "ifcombine" } } */

=== modified file 'gcc/tree-ssa-ccp.c'
--- old/gcc/tree-ssa-ccp.c	2010-09-16 09:15:46 +0000
+++ new/gcc/tree-ssa-ccp.c	2011-01-05 11:27:00 +0000
@@ -3508,14 +3508,11 @@
 	  /* Handle the OR case, where we are redistributing:
 	     (inner1 OR inner2) AND (op2a code2 op2b)
 	     => (t OR (inner2 AND (op2a code2 op2b)))  */
-	  else
-	    {
-	      if (integer_onep (t))
-		return boolean_true_node;
-	      else
-		/* Save partial result for later.  */
-		partial = t;
-	    }
+	  else if (integer_onep (t))
+	    return boolean_true_node;
+
+	  /* Save partial result for later.  */
+	  partial = t;
 	}
       
       /* Compute the second partial result, (inner2 AND (op2a code op2b)) */
@@ -3536,6 +3533,10 @@
 		return inner1;
 	      else if (integer_zerop (t))
 		return boolean_false_node;
+	      /* If both are the same, we can apply the identity
+		 (x AND x) == x.  */
+	      else if (partial && same_bool_result_p (t, partial))
+		return t;
 	    }
 
 	  /* Handle the OR case. where we are redistributing:
@@ -3945,7 +3946,7 @@
 	     => (t OR inner2)
 	     If the partial result t is a constant, we win.  Otherwise
 	     continue on to try reassociating with the other inner test.  */
-	  if (innercode == TRUTH_OR_EXPR)
+	  if (is_or)
 	    {
 	      if (integer_onep (t))
 		return boolean_true_node;
@@ -3956,14 +3957,11 @@
 	  /* Handle the AND case, where we are redistributing:
 	     (inner1 AND inner2) OR (op2a code2 op2b)
 	     => (t AND (inner2 OR (op2a code op2b)))  */
-	  else
-	    {
-	      if (integer_zerop (t))
-		return boolean_false_node;
-	      else
-		/* Save partial result for later.  */
-		partial = t;
-	    }
+	  else if (integer_zerop (t))
+	    return boolean_false_node;
+
+	  /* Save partial result for later.  */
+	  partial = t;
 	}
       
       /* Compute the second partial result, (inner2 OR (op2a code op2b)) */
@@ -3977,13 +3975,18 @@
 	{
 	  /* Handle the OR case, where we are reassociating:
 	     (inner1 OR inner2) OR (op2a code2 op2b)
-	     => (inner1 OR t)  */
-	  if (innercode == TRUTH_OR_EXPR)
+	     => (inner1 OR t)
+	     => (t OR partial)  */
+	  if (is_or)
 	    {
 	      if (integer_zerop (t))
 		return inner1;
 	      else if (integer_onep (t))
 		return boolean_true_node;
+	      /* If both are the same, we can apply the identity
+		 (x OR x) == x.  */
+	      else if (partial && same_bool_result_p (t, partial))
+		return t;
 	    }
 	  
 	  /* Handle the AND case, where we are redistributing:
@@ -4000,13 +4003,13 @@
 		     operand to the redistributed AND expression.  The
 		     interesting case is when at least one is true.
 		     Or, if both are the same, we can apply the identity
-		     (x AND x) == true.  */
+		     (x AND x) == x.  */
 		  if (integer_onep (partial))
 		    return t;
 		  else if (integer_onep (t))
 		    return partial;
 		  else if (same_bool_result_p (t, partial))
-		    return boolean_true_node;
+		    return t;
 		}
 	    }
 	}

