[PATCH] Fix simplify_const_relational_operation unsigned comparisons of sign-extended values (PR rtl-optimization/34490)

Jakub Jelinek jakub@redhat.com
Sun Dec 16 16:28:00 GMT 2007


Hi!

The attached testcase distilled from glibc is miscompiled on x86_64-linux,
simplify_const_relational_operation (LEU, DImode, (sign_extend:DI (reg:SI 59)), (const_int -4096))
returns (const_int 1), eventhough for unsigned comparisons nothing like that
can be deduced from the arguments.  If op0 is sign extended and the
comparison is unsigned (GTU, GEU, LTU, LEU), then all we know is that
op0 falls into one of two disjunct ranges, in the above case for DImode
and num_sign_bit_copies == 33
0 ... 0x7fffffff and 0xffffffff80000000 ... -1ULL
so all we can deduce is that for op0 >= 0 and op0 <= -1ULL, nothing else.

This is a recent regression (on the trunk only), introduced by
http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=128833

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

2007-12-16  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/34490
	* simplify-rtx.c (simplify_const_relational_operation): If !sign,
	don't reduce mmin/mmax using num_sign_bit_copies.

	* gcc.c-torture/execute/20071216-1.c: New test.

--- gcc/simplify-rtx.c.jj	2007-10-08 10:45:03.000000000 +0200
+++ gcc/simplify-rtx.c	2007-12-16 12:22:04.000000000 +0100
@@ -4233,15 +4233,17 @@ simplify_const_relational_operation (enu
       else
 	{
 	  rtx mmin_rtx, mmax_rtx;
-	  unsigned int sign_copies = num_sign_bit_copies (trueop0, mode);
 	  get_mode_bounds (mode, sign, mode, &mmin_rtx, &mmax_rtx);
 
-	  /* Since unsigned mmin will never be interpreted as negative, use
-	     INTVAL (and an arithmetic right shift).  */
-	  mmin = INTVAL (mmin_rtx) >> (sign_copies - 1);
-	  /* Since signed mmax will always be positive, use UINTVAL (and
-	     a logical right shift).  */
-	  mmax = UINTVAL (mmax_rtx) >> (sign_copies - 1);
+	  mmin = INTVAL (mmin_rtx);
+	  mmax = INTVAL (mmax_rtx);
+	  if (sign)
+	    {
+	      unsigned int sign_copies = num_sign_bit_copies (trueop0, mode);
+
+	      mmin >>= (sign_copies - 1);
+	      mmax >>= (sign_copies - 1);
+	    }
 	}
 
       switch (code)
--- gcc/testsuite/gcc.c-torture/execute/20071216-1.c.jj	2007-12-16 12:25:58.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20071216-1.c	2007-12-16 10:38:34.000000000 +0100
@@ -0,0 +1,38 @@
+/* PR rtl-optimization/34490 */
+
+extern void abort (void);
+
+static int x;
+
+int
+__attribute__((noinline))
+bar (void)
+{
+  return x;
+}
+
+int
+foo (void)
+{
+  long int b = bar ();
+  if ((unsigned long) b < -4095L)
+    return b;
+  if (-b != 38)
+    b = -2;
+  return b + 1;
+}
+
+int
+main (void)
+{
+  x = 26;
+  if (foo () != 26)
+    abort ();
+  x = -39;
+  if (foo () != -1)
+    abort ();
+  x = -38;
+  if (foo () != -37)
+    abort ();
+  return 0;
+}

	Jakub



More information about the Gcc-patches mailing list