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 combiner issues with shifts (PR c/37924)


Hi!

This patch fixes a couple of combiner issues.
1) simplify_shift_const_1 does something only if a shift count is within
   its range, but then can add or subtract shift counts without checking the
   result.  This is because each such addition or subtraction is followed by
   continue and expects next iteration to canonicalize the count. 
   Unfortunately if complement_p is true, the loop is exited before that
   canonicalization.  This patch moves if (complement_p) break; after
   the shift count canonicalization.
2) make_compound_operation in several places didn't check if shift count is
   in its range, and calling make_extraction with negative length results in
   ICE.  We should leave out-of-range shift counts unmodified.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2008-10-27  Jakub Jelinek  <jakub@redhat.com>

	PR c/37924
	* combine.c (make_compound_operation): Don't call make_extraction with
	non-positive length.
	(simplify_shift_const_1): Canonicalize count even if complement_p.

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

--- gcc/combine.c.jj	2008-10-23 13:21:41.000000000 +0200
+++ gcc/combine.c	2008-10-27 17:05:29.000000000 +0100
@@ -6996,7 +6996,8 @@ make_compound_operation (rtx x, enum rtx
       if (GET_CODE (rhs) == CONST_INT
 	  && GET_CODE (lhs) == ASHIFT
 	  && GET_CODE (XEXP (lhs, 1)) == CONST_INT
-	  && INTVAL (rhs) >= INTVAL (XEXP (lhs, 1)))
+	  && INTVAL (rhs) >= INTVAL (XEXP (lhs, 1))
+	  && INTVAL (rhs) < mode_width)
 	{
 	  new_rtx = make_compound_operation (XEXP (lhs, 0), next_code);
 	  new_rtx = make_extraction (mode, new_rtx,
@@ -7016,6 +7017,7 @@ make_compound_operation (rtx x, enum rtx
 		&& (OBJECT_P (SUBREG_REG (lhs))))
 	  && GET_CODE (rhs) == CONST_INT
 	  && INTVAL (rhs) < HOST_BITS_PER_WIDE_INT
+	  && INTVAL (rhs) < mode_width
 	  && (new_rtx = extract_left_shift (lhs, INTVAL (rhs))) != 0)
 	new_rtx = make_extraction (mode, make_compound_operation (new_rtx, next_code),
 			       0, NULL_RTX, mode_width - INTVAL (rhs),
@@ -9003,11 +9005,6 @@ simplify_shift_const_1 (enum rtx_code co
       if (GET_CODE (varop) == CLOBBER)
 	return NULL_RTX;
 
-      /* If we discovered we had to complement VAROP, leave.  Making a NOT
-	 here would cause an infinite loop.  */
-      if (complement_p)
-	break;
-
       /* Convert ROTATERT to ROTATE.  */
       if (code == ROTATERT)
 	{
@@ -9053,6 +9050,11 @@ simplify_shift_const_1 (enum rtx_code co
 	    }
 	}
 
+      /* If we discovered we had to complement VAROP, leave.  Making a NOT
+	 here would cause an infinite loop.  */
+      if (complement_p)
+	break;
+
       /* An arithmetic right shift of a quantity known to be -1 or 0
 	 is a no-op.  */
       if (code == ASHIFTRT
--- gcc/testsuite/gcc.c-torture/execute/pr37924.c.jj	2008-10-27 19:24:11.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr37924.c	2008-10-27 19:23:10.000000000 +0100
@@ -0,0 +1,29 @@
+/* PR c/37924 */
+
+extern void abort (void);
+
+char a;
+
+int
+test (void)
+{
+  int b = -1;
+  return ((unsigned int) (a ^ b)) >> 9;
+}
+
+int
+main (void)
+{
+  if (test () != (-1U >> 9))
+    abort ();
+  a = 0x40;
+  if (test () != (-1U >> 9))
+    abort ();
+  a = 0x80;
+  if (test () != (a < 0) ? 0 : (-1U >> 9))
+    abort ();
+  a = 0xff;
+  if (test () != (a < 0) ? 0 : (-1U >> 9))
+    abort ();
+  return 0;
+}

	Jakub


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