Hi!

As the first hunk in the testcase shows, we can't perform this optimization
if the conversion is narrowing.
As the second hunk shows, if we allow 1 << 31 (we don't optimize
int foo (int x) { return (1 << x) < 0; } so I think it would be surprising
if we did optimize it in this case, plus I'm afraid it could break a lot
of code if we started optimizing (1 << x) < 0 into 0), we can't optimize
a widening conversion from signed to unsigned either.

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

For 4.9, I think we should see why e.g.
X < (unsigned) (1 << Y)
optimization isn't performed e.g. when X is just an unsigned int variable
(rather than say ARRAY_REF as in the testcase), probably we need to handle
it for arg1 being X and arg0 being (1 << Y) too.

2013-01-20  Jakub Jelinek  <ja...@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.

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

--- gcc/fold-const.c.jj 2013-01-11 09:02:35.000000000 +0100
+++ gcc/fold-const.c    2013-01-20 17:37:45.787761247 +0100
@@ -13560,6 +13560,11 @@ fold_binary_loc (location_t loc,
          && 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,
--- gcc/testsuite/gcc.c-torture/execute/pr56051.c.jj    2013-01-20 
17:40:09.070945296 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr56051.c       2013-01-20 
17:38:31.000000000 +0100
@@ -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;
+}

        Jakub

Reply via email to