Patchwork Backport a patch to 4.6 branch

login
register
mail settings
Submitter Jakub Jelinek
Date Feb. 23, 2012, 6:42 p.m.
Message ID <20120223184257.GV18768@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/142695/
State New
Headers show

Comments

Jakub Jelinek - Feb. 23, 2012, 6:42 p.m.
Hi!

I've backported this to 4.6 branch, after bootstrapping/regtesting
it on x86_64-linux and i686-linux.

2012-02-23  Jakub Jelinek  <jakub@redhat.com>

	Backported from trunk
	2012-02-20  Georg-Johann Lay  <avr@gjlay.de>

	* gcc.c-torture/execute/pr52286.c: Fix FAIL on 16-bit int platforms.

	2012-02-20  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/52286
	* fold-const.c (fold_binary_loc): For (X & C1) | C2
	optimization use double_int_to_tree instead of build_int_cst_wide,
	rewrite to use double_int vars.

	* gcc.c-torture/execute/pr52286.c: New test.


	Jakub

Patch

--- gcc/fold-const.c	(revision 184390)
+++ gcc/fold-const.c	(revision 184391)
@@ -10959,66 +10959,50 @@  fold_binary_loc (location_t loc,
 	  && TREE_CODE (arg1) == INTEGER_CST
 	  && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
 	{
-	  unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, hi3, lo3, mlo, mhi;
+	  double_int c1, c2, c3, msk;
 	  int width = TYPE_PRECISION (type), w;
-	  hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1));
-	  lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1));
-	  hi2 = TREE_INT_CST_HIGH (arg1);
-	  lo2 = TREE_INT_CST_LOW (arg1);
+	  c1 = tree_to_double_int (TREE_OPERAND (arg0, 1));
+	  c2 = tree_to_double_int (arg1);
 
 	  /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2).  */
-	  if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1)
+	  if (double_int_equal_p (double_int_and (c1, c2), c1))
 	    return omit_one_operand_loc (loc, type, arg1,
-				     TREE_OPERAND (arg0, 0));
+					 TREE_OPERAND (arg0, 0));
 
-	  if (width > HOST_BITS_PER_WIDE_INT)
-	    {
-	      mhi = (unsigned HOST_WIDE_INT) -1
-		    >> (2 * HOST_BITS_PER_WIDE_INT - width);
-	      mlo = -1;
-	    }
-	  else
-	    {
-	      mhi = 0;
-	      mlo = (unsigned HOST_WIDE_INT) -1
-		    >> (HOST_BITS_PER_WIDE_INT - width);
-	    }
+	  msk = double_int_mask (width);
 
 	  /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2.  */
-	  if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0)
+	  if (double_int_zero_p (double_int_and_not (msk,
+						     double_int_ior (c1, c2))))
 	    return fold_build2_loc (loc, BIT_IOR_EXPR, type,
-				TREE_OPERAND (arg0, 0), arg1);
+				    TREE_OPERAND (arg0, 0), arg1);
 
 	  /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2,
 	     unless (C1 & ~C2) | (C2 & C3) for some C3 is a mask of some
 	     mode which allows further optimizations.  */
-	  hi1 &= mhi;
-	  lo1 &= mlo;
-	  hi2 &= mhi;
-	  lo2 &= mlo;
-	  hi3 = hi1 & ~hi2;
-	  lo3 = lo1 & ~lo2;
+	  c1 = double_int_and (c1, msk);
+	  c2 = double_int_and (c2, msk);
+	  c3 = double_int_and_not (c1, c2);
 	  for (w = BITS_PER_UNIT;
 	       w <= width && w <= HOST_BITS_PER_WIDE_INT;
 	       w <<= 1)
 	    {
 	      unsigned HOST_WIDE_INT mask
 		= (unsigned HOST_WIDE_INT) -1 >> (HOST_BITS_PER_WIDE_INT - w);
-	      if (((lo1 | lo2) & mask) == mask
-		  && (lo1 & ~mask) == 0 && hi1 == 0)
+	      if (((c1.low | c2.low) & mask) == mask
+		  && (c1.low & ~mask) == 0 && c1.high == 0)
 		{
-		  hi3 = 0;
-		  lo3 = mask;
+		  c3 = uhwi_to_double_int (mask);
 		  break;
 		}
 	    }
-	  if (hi3 != hi1 || lo3 != lo1)
+	  if (!double_int_equal_p (c3, c1))
 	    return fold_build2_loc (loc, BIT_IOR_EXPR, type,
-				fold_build2_loc (loc, BIT_AND_EXPR, type,
-					     TREE_OPERAND (arg0, 0),
-					     build_int_cst_wide (type,
-								 lo3, hi3)),
-				arg1);
+				    fold_build2_loc (loc, BIT_AND_EXPR, type,
+						     TREE_OPERAND (arg0, 0),
+						     double_int_to_tree (type,
+									 c3)),
+				    arg1);
 	}
 
       /* (X & Y) | Y is (X, Y).  */
--- gcc/testsuite/gcc.c-torture/execute/pr52286.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr52286.c	(revision 184394)
@@ -0,0 +1,20 @@ 
+/* PR tree-optimization/52286 */
+
+extern void abort (void);
+
+int
+main ()
+{
+#if __SIZEOF_INT__ > 2
+  int a, b;
+  asm ("" : "=r" (a) : "0" (0));
+  b = (~a | 1) & -2038094497;
+#else
+  long a, b;
+  asm ("" : "=r" (a) : "0" (0));
+  b = (~a | 1) & -2038094497L;
+#endif
+  if (b >= 0)
+    abort ();
+  return 0;
+}