OSDN Git Service

* fold-const.c (negate_expr_p) <RSHIFT_EXPR>: We can optimize
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Mar 2004 17:45:03 +0000 (17:45 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Mar 2004 17:45:03 +0000 (17:45 +0000)
-((int)X>>C) where C is an integer constant one bit less than the
size of X into (unsigned)X>>C.  Similarly for unsigned->signed.
(negate_expr) <RSHIFT_EXPR>: Implement the above transformations.

* simplify-rtx.c (simplify_unary_operation): Also implement the
above transformations at the RTL level.

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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@79334 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20040311-1.c [new file with mode: 0644]

index 318b12f..dcaa0b6 100644 (file)
@@ -1,3 +1,13 @@
+2004-03-11  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (negate_expr_p) <RSHIFT_EXPR>: We can optimize
+       -((int)X>>C) where C is an integer constant one bit less than the
+       size of X into (unsigned)X>>C.  Similarly for unsigned->signed.
+       (negate_expr) <RSHIFT_EXPR>: Implement the above transformations.
+
+       * simplify-rtx.c (simplify_unary_operation): Also implement the
+       above transformations at the RTL level.
+
 2004-03-11  Alan Modra  <amodra@bigpond.net.au>
 
        * real.c (encode_ibm_extended): Do round low word.
index 58b6c70..5e18d68 100644 (file)
@@ -920,6 +920,18 @@ negate_expr_p (tree t)
        return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1)));
       break;
 
+    case RSHIFT_EXPR:
+      /* Optimize -((int)x >> 31) into (unsigned)x >> 31.  */
+      if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
+       {
+         tree op1 = TREE_OPERAND (t, 1);
+         if (TREE_INT_CST_HIGH (op1) == 0
+             && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1)
+                == TREE_INT_CST_LOW (op1))
+           return true;
+       }
+      break;
+
     default:
       break;
     }
@@ -1065,6 +1077,25 @@ negate_expr (tree t)
        }
       break;
 
+    case RSHIFT_EXPR:
+      /* Optimize -((int)x >> 31) into (unsigned)x >> 31.  */
+      if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
+       {
+         tree op1 = TREE_OPERAND (t, 1);
+         if (TREE_INT_CST_HIGH (op1) == 0
+             && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1)
+                == TREE_INT_CST_LOW (op1))
+           {
+             tree ntype = TREE_UNSIGNED (type)
+                          ? (*lang_hooks.types.signed_type) (type)
+                          : (*lang_hooks.types.unsigned_type) (type);
+             tree temp = fold_convert (ntype, TREE_OPERAND (t, 0));
+             temp = fold (build2 (RSHIFT_EXPR, ntype, temp, op1));
+             return fold_convert (type, temp);
+           }
+       }
+      break;
+
     default:
       break;
     }
index 3647c24..2846bb7 100644 (file)
@@ -1013,6 +1013,22 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
                                            XEXP (op, 1));
            }
 
+         /* (neg (ashiftrt X C)) can be replaced by (lshiftrt X C) when
+            C is equal to the width of MODE minus 1.  */
+         if (GET_CODE (op) == ASHIFTRT
+             && GET_CODE (XEXP (op, 1)) == CONST_INT
+             && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
+               return simplify_gen_binary (LSHIFTRT, mode,
+                                           XEXP (op, 0), XEXP (op, 1));
+
+         /* (neg (lshiftrt X C)) can be replaced by (ashiftrt X C) when
+            C is equal to the width of MODE minus 1.  */
+         if (GET_CODE (op) == LSHIFTRT
+             && GET_CODE (XEXP (op, 1)) == CONST_INT
+             && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
+               return simplify_gen_binary (ASHIFTRT, mode,
+                                           XEXP (op, 0), XEXP (op, 1));
+
          break;
 
        case SIGN_EXTEND:
index fb762d5..90916b8 100644 (file)
@@ -1,3 +1,7 @@
+2004-03-11  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.c-torture/execute/20040311-1.c: New test case.
+
 2004-03-11  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/14476
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040311-1.c b/gcc/testsuite/gcc.c-torture/execute/20040311-1.c
new file mode 100644 (file)
index 0000000..013d869
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+   Check that constant folding and RTL simplification of -(x >> y) doesn't
+   break anything and produces the expected results.
+
+   Written by Roger Sayle, 11th March 2004.  */
+
+extern void abort (void);
+
+#define INT_BITS  (sizeof(int)*8)
+
+int test1(int x)
+{
+  return -(x >> (INT_BITS-1));
+}
+
+int test2(unsigned int x)
+{
+  return -((int)(x >> (INT_BITS-1)));
+}
+
+int test3(int x)
+{
+  int y;
+  y = INT_BITS-1;
+  return -(x >> y);
+}
+
+int test4(unsigned int x)
+{
+  int y;
+  y = INT_BITS-1;
+  return -((int)(x >> y));
+}
+
+int main()
+{
+  if (test1(0) != 0)
+    abort ();
+  if (test1(1) != 0)
+    abort ();
+  if (test1(-1) != 1)
+    abort ();
+
+  if (test2(0) != 0)
+    abort ();
+  if (test2(1) != 0)
+    abort ();
+  if (test2((unsigned int)-1) != -1)
+    abort ();
+
+  if (test3(0) != 0)
+    abort ();
+  if (test3(1) != 0)
+    abort ();
+  if (test3(-1) != 1)
+    abort ();
+
+  if (test4(0) != 0)
+    abort ();
+  if (test4(1) != 0)
+    abort ();
+  if (test4((unsigned int)-1) != -1)
+    abort ();
+
+  return 0;
+}
+