aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-01-21 18:55:34 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2013-01-21 18:55:34 +0100
commit8f498c1bdcb9d3b99905f654faa0a343c3e9ef99 (patch)
treea3bdef1e25a778da35e6160d0a5f3bf467d3ae9b
parent35d59da7f7e282a68589d8c857ee7f0503d588d2 (diff)
downloadgcc-8f498c1bdcb9d3b99905f654faa0a343c3e9ef99.zip
gcc-8f498c1bdcb9d3b99905f654faa0a343c3e9ef99.tar.gz
gcc-8f498c1bdcb9d3b99905f654faa0a343c3e9ef99.tar.bz2
re PR tree-optimization/56051 (Wrong expression evaluation)
PR tree-optimization/56051 * fold-const.c (fold_binary_loc): Don't fold X < (cast) (1 << Y) into (X >> Y) != 0 if cast is either a narrowing conversion, or widening conversion from signed to unsigned. * gcc.c-torture/execute/pr56051.c: New test. From-SVN: r195343
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c12
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr56051.c32
4 files changed, 57 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 196a26e..8ec4ee2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2013-01-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/56051
+ * fold-const.c (fold_binary_loc): Don't fold
+ X < (cast) (1 << Y) into (X >> Y) != 0 if cast is either
+ a narrowing conversion, or widening conversion from signed
+ to unsigned.
+
2012-01-21 Uros Bizjak <ubizjak@gmail.com>
PR rtl-optimization/56023
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 4e1e63b..efad9a9 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -13556,10 +13556,22 @@ fold_binary_loc (location_t loc,
TREE_OPERAND (arg1, 1)),
build_zero_cst (TREE_TYPE (arg0)));
+ /* Similarly for X < (cast) (1 << Y). But cast can't be narrowing,
+ otherwise Y might be >= # of bits in X's type and thus e.g.
+ (unsigned char) (1 << Y) for Y 15 might be 0.
+ If the cast is widening, then 1 << Y should have unsigned type,
+ otherwise if Y is number of bits in the signed shift type minus 1,
+ we can't optimize this. E.g. (unsigned long long) (1 << Y) for Y
+ 31 might be 0xffffffff80000000. */
if ((code == LT_EXPR || code == GE_EXPR)
&& TYPE_UNSIGNED (TREE_TYPE (arg0))
&& CONVERT_EXPR_P (arg1)
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
+ && (TYPE_PRECISION (TREE_TYPE (arg1))
+ >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))))
+ && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0)))
+ || (TYPE_PRECISION (TREE_TYPE (arg1))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)))))
&& integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
{
tem = build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 385cd9c..a88bfa8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2013-01-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/56051
+ * gcc.c-torture/execute/pr56051.c: New test.
+
2012-01-21 Uros Bizjak <ubizjak@gmail.com>
PR rtl-optimization/56023
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr56051.c b/gcc/testsuite/gcc.c-torture/execute/pr56051.c
new file mode 100644
index 0000000..4ff6b9e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr56051.c
@@ -0,0 +1,32 @@
+/* PR tree-optimization/56051 */
+
+extern void abort (void);
+
+int
+main ()
+{
+ unsigned char x1[1] = { 0 };
+ unsigned int s1 = __CHAR_BIT__;
+ int a1 = x1[0] < (unsigned char) (1 << s1);
+ unsigned char y1 = (unsigned char) (1 << s1);
+ int b1 = x1[0] < y1;
+ if (a1 != b1)
+ abort ();
+#if __SIZEOF_LONG_LONG__ > __SIZEOF_INT__
+ unsigned long long x2[1] = { 2ULL << (sizeof (int) * __CHAR_BIT__) };
+ unsigned int s2 = sizeof (int) * __CHAR_BIT__ - 1;
+ int a2 = x2[0] >= (unsigned long long) (1 << s2);
+ unsigned long long y2 = 1 << s2;
+ int b2 = x2[0] >= y2;
+ if (a2 != b2)
+ abort ();
+ unsigned long long x3[1] = { 2ULL << (sizeof (int) * __CHAR_BIT__) };
+ unsigned int s3 = sizeof (int) * __CHAR_BIT__ - 1;
+ int a3 = x3[0] >= (unsigned long long) (1U << s3);
+ unsigned long long y3 = 1U << s3;
+ int b3 = x3[0] >= y3;
+ if (a3 != b3)
+ abort ();
+#endif
+ return 0;
+}