summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2004-03-11 17:45:03 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2004-03-11 17:45:03 +0000
commit239a625ee83ff08df15beab3ca2f1b37881e7f10 (patch)
tree53c0a411f358defff23d8e0c39b1dc0819424479
parent4b0b51c9706b25603247ec6e48d8ac53e8db64f3 (diff)
downloadgcc-239a625ee83ff08df15beab3ca2f1b37881e7f10.tar.gz
fold-const.c (negate_expr_p): We can optimize -((int)X>>C) where C is an integer constant one bit less than...
* 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. * gcc.c-torture/execute/20040311-1.c: New test case. From-SVN: r79334
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/fold-const.c31
-rw-r--r--gcc/simplify-rtx.c16
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20040311-1.c68
5 files changed, 129 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 318b12f554a..dcaa0b67b49 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 58b6c70df4c..5e18d6862ac 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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;
}
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 3647c244077..2846bb7a80d 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fb762d54db6..90916b8b98a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..013d869abf4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20040311-1.c
@@ -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;
+}
+