[PATCH] Fix num_sign_bit_copies UMOD handling (PR rtl-optimization/41917)

View: New views
2 Messages — Rating Filter:   Alert me  

[PATCH] Fix num_sign_bit_copies UMOD handling (PR rtl-optimization/41917)

by Jakub Jelinek :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi!

This testcase fails on x86_64-linux, because num_sign_bit_copies
sees UMOD (reg:SI) (X | 0xfffffffe), so num_sign_bit_copies of the second
argument is large, yet it doesn't say anything about the number of sign bits
in the result.  It can be anything from 0 up to that number.
Only when we know that second operand's sign bit is zero and it has more
than one sign bit copy (== 0 bits), we know the result has also at least
that many sign bit copies (== 0 bits).
UDIV handling already has a similar condition like this.

Bootstrapped/regtested on x86_64-linux and i686-linux.  Ok for trunk/4.4?

For trunk we could perhaps optimize more and handle both operands of UMOD
similarly and take the larger number of sign bit copies (== 0 most
significant bits), as UMOD result is not just < the second operand, but
also <= the first operand.

2009-11-03  Jakub Jelinek  <jakub@...>

        PR rtl-optimization/41917
        * rtlanal.c (num_sign_bit_copies1) <case UMOD>: If sign bit of second
        operand isn't known to be 0, return 1.

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

--- gcc/rtlanal.c.jj 2009-09-03 09:59:32.000000000 +0200
+++ gcc/rtlanal.c 2009-11-03 10:23:31.000000000 +0100
@@ -4501,8 +4501,16 @@ num_sign_bit_copies1 (const_rtx x, enum
    known_x, known_mode, known_ret);
 
     case UMOD:
-      /* The result must be <= the second operand.  */
-      return cached_num_sign_bit_copies (XEXP (x, 1), mode,
+      /* The result must be <= the second operand.  If the second operand
+ has (or just might have) the high bit set, we know nothing about
+ the number of sign bit copies.  */
+      if (bitwidth > HOST_BITS_PER_WIDE_INT)
+ return 1;
+      else if ((nonzero_bits (XEXP (x, 1), mode)
+ & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
+ return 1;
+      else
+ return cached_num_sign_bit_copies (XEXP (x, 1), mode,
    known_x, known_mode, known_ret);
 
     case DIV:
--- gcc/testsuite/gcc.c-torture/execute/pr41917.c.jj 2009-11-03 10:36:50.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr41917.c 2009-11-03 10:36:19.000000000 +0100
@@ -0,0 +1,21 @@
+/* PR rtl-optimization/41917 */
+
+extern void abort (void);
+unsigned int a = 1;
+
+int
+main (void)
+{
+  unsigned int b, c, d;
+
+  if (sizeof (int) != 4 || (int) 0xc7d24b5e > 0)
+    return 0;
+
+  c = 0xc7d24b5e;
+  d = a | -2;
+  b = (d == 0) ? c : (c % d);
+  if (b != c)
+    abort ();
+
+  return 0;
+}

        Jakub

Re: [PATCH] Fix num_sign_bit_copies UMOD handling (PR rtl-optimization/41917)

by Jeff Law :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 11/03/09 05:53, Jakub Jelinek wrote:

> Hi!
>
> This testcase fails on x86_64-linux, because num_sign_bit_copies
> sees UMOD (reg:SI) (X | 0xfffffffe), so num_sign_bit_copies of the second
> argument is large, yet it doesn't say anything about the number of sign bits
> in the result.  It can be anything from 0 up to that number.
> Only when we know that second operand's sign bit is zero and it has more
> than one sign bit copy (== 0 bits), we know the result has also at least
> that many sign bit copies (== 0 bits).
> UDIV handling already has a similar condition like this.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux.  Ok for trunk/4.4?
>
> For trunk we could perhaps optimize more and handle both operands of UMOD
> similarly and take the larger number of sign bit copies (== 0 most
> significant bits), as UMOD result is not just<  the second operand, but
> also<= the first operand.
>
> 2009-11-03  Jakub Jelinek<jakub@...>
>
> PR rtl-optimization/41917
> * rtlanal.c (num_sign_bit_copies1)<case UMOD>: If sign bit of second
> operand isn't known to be 0, return 1.
>
> * gcc.c-torture/execute/pr41917.c: New test.
>    
OK.
jeff