Hi!

This code dates back to 1994, and as the testcase shows, is broken
if mask contains some bits outside of mode (as ASHIFTRT is signed,
I think it is fine if it is sign extended from mode to the HWI).
On this particular testcase, mode is SImode,  trueop1 is (const_int 2),
count is 31, so we get mask 0x100000000, and mask & nonzero_bits (something, 
SImode)
will be always 0, because nonzero_bits won't have any bits beyond those in
SImode set.  But that means we haven't actually verified that the
optimization is correct.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk/4.8?

2013-07-05  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/57829
        * simplify-rtx.c (simplify_binary_operation_1) <case IOR>: Ensure that
        mask bits outside of mode are just sign-extension from mode to HWI.

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

--- gcc/simplify-rtx.c.jj       2013-07-04 16:55:19.000000000 +0200
+++ gcc/simplify-rtx.c  2013-07-05 16:37:50.100920805 +0200
@@ -2818,6 +2818,7 @@ simplify_binary_operation_1 (enum rtx_co
           HOST_WIDE_INT mask = INTVAL (trueop1) << count;
 
           if (mask >> count == INTVAL (trueop1)
+             && trunc_int_for_mode (mask, mode) == mask
               && (mask & nonzero_bits (XEXP (op0, 0), mode)) == 0)
            return simplify_gen_binary (ASHIFTRT, mode,
                                        plus_constant (mode, XEXP (op0, 0),
--- gcc/testsuite/gcc.c-torture/execute/pr57829.c.jj    2013-07-05 
16:27:12.167405677 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr57829.c       2013-07-05 
16:28:28.000000000 +0200
@@ -0,0 +1,31 @@
+/* PR rtl-optimization/57829 */
+
+__attribute__((noinline, noclone))
+int
+f1 (int k)
+{
+  return 2 | ((k - 1) >> ((int) sizeof (int) * __CHAR_BIT__ - 1));
+}
+
+__attribute__((noinline, noclone))
+long int
+f2 (long int k)
+{
+  return 2L | ((k - 1L) >> ((int) sizeof (long int) * __CHAR_BIT__ - 1));
+}
+
+__attribute__((noinline, noclone))
+int
+f3 (int k)
+{
+  k &= 63;
+  return 4 | ((k + 2) >> 5);
+}
+
+int
+main ()
+{
+  if (f1 (1) != 2 || f2 (1L) != 2L || f3 (63) != 6 || f3 (1) != 4)
+    __builtin_abort ();
+  return 0;
+}

        Jakub

Reply via email to