re PR tree-optimization/56051 (Wrong expression evaluation)
authorJakub Jelinek <jakub@redhat.com>
Mon, 21 Jan 2013 17:55:34 +0000 (18:55 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 21 Jan 2013 17:55:34 +0000 (18:55 +0100)
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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr56051.c [new file with mode: 0644]

index 196a26e06ff129a06e72b3681e9fb4dd9951c630..8ec4ee2afa5e91ee01d4ef435ff87927446a1b02 100644 (file)
@@ -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
index 4e1e63b8405feeb5dec5fb82f6301860d8423d1d..efad9a9d833d9b56ac2ae6cd2dd90a9dca8690f7 100644 (file)
@@ -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,
index 385cd9cebb10be7ca9cec1ca42d2b523b9f74763..a88bfa86c1fcd97afd2c987b3b09aa7113b473ec 100644 (file)
@@ -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 (file)
index 0000000..4ff6b9e
--- /dev/null
@@ -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;
+}