]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/gcc-tumbl.git/commitdiff
Backported from mainline
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Feb 2013 14:11:46 +0000 (14:11 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Feb 2013 14:11:46 +0000 (14:11 +0000)
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.

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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@195658 138bc75d-0d04-0410-961f-82ee72b054a4

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

index dd6f030315defd7df0690e9d62b39d46c4900b13..3a98e757370061cf5b3ec6360908f386dad7b8e0 100644 (file)
@@ -1,6 +1,14 @@
 2013-02-01  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       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.
+
        2013-01-18  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/56015
index 6302568ace04d5546aa997d201b5c0844d3b9367..7f17b89b6d3c19139810def16432c1e334463a36 100644 (file)
@@ -13453,10 +13453,22 @@ fold_binary_loc (location_t loc,
                                   TREE_OPERAND (arg1, 1)),
                           build_int_cst (TREE_TYPE (arg0), 0));
 
+      /* 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 37fbb5346d5283b5295f32f5091cc84a923c46f9..3afb0c6794c34ed03681d05de295eca5029c2d3c 100644 (file)
@@ -1,6 +1,11 @@
 2013-02-01  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2013-01-21  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/56051
+       * gcc.c-torture/execute/pr56051.c: New test.
+
        2013-01-18  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/56015
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;
+}