OSDN Git Service

PR middle-end/34337
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Dec 2007 22:24:08 +0000 (22:24 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Dec 2007 22:24:08 +0000 (22:24 +0000)
* fold-const.c (fold_binary) <case BIT_IOR_EXPR>: Don't minimize
number of bits set in C1 if a mode mask for some mode can be used
instead.

* gcc.c-torture/execute/20071205-1.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@130635 138bc75d-0d04-0410-961f-82ee72b054a4

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

index da6a6c3..189286b 100644 (file)
@@ -1,3 +1,10 @@
+2007-12-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/34337
+       * fold-const.c (fold_binary) <case BIT_IOR_EXPR>: Don't minimize
+       number of bits set in C1 if a mode mask for some mode can be used
+       instead.
+
 2007-12-05  Bernhard Fischer  <aldot@gcc.gnu.org>
 
        * varasm.c (merge_weak, weak_finish, assemble_alias): Commentary typo
index 1502994..8519e68 100644 (file)
@@ -10570,8 +10570,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, mlo, mhi;
-         int width = TYPE_PRECISION (type);
+         unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, hi3, lo3, mlo, mhi;
+         int width = TYPE_PRECISION (type), w;
          hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1));
          lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1));
          hi2 = TREE_INT_CST_HIGH (arg1);
@@ -10599,16 +10599,35 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            return fold_build2 (BIT_IOR_EXPR, type,
                                TREE_OPERAND (arg0, 0), arg1);
 
-         /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2.  */
+         /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2,
+            unless (C1 & ~C2) | (C2 & C3) for some C3 is a mask of some
+            mode which allows further optimizations.  */
          hi1 &= mhi;
          lo1 &= mlo;
-         if ((hi1 & ~hi2) != hi1 || (lo1 & ~lo2) != lo1)
+         hi2 &= mhi;
+         lo2 &= mlo;
+         hi3 = hi1 & ~hi2;
+         lo3 = lo1 & ~lo2;
+         for (w = BITS_PER_UNIT;
+              w <= width && w <= HOST_BITS_PER_WIDE_INT;
+              w <<= 1)
+           {
+             unsigned HOST_WIDE_INT mask
+               = (unsigned HOST_WIDE_INT) -1 >> (HOST_BITS_PER_WIDE_INT - w);
+             if (((lo1 | lo2) & mask) == mask
+                 && (lo1 & ~mask) == 0 && hi1 == 0)
+               {
+                 hi3 = 0;
+                 lo3 = mask;
+                 break;
+               }
+           }
+         if (hi3 != hi1 || lo3 != lo1)
            return fold_build2 (BIT_IOR_EXPR, type,
                                fold_build2 (BIT_AND_EXPR, type,
                                             TREE_OPERAND (arg0, 0),
                                             build_int_cst_wide (type,
-                                                                lo1 & ~lo2,
-                                                                hi1 & ~hi2)),
+                                                                lo3, hi3)),
                                arg1);
        }
 
index 1acb944..70aa1df 100644 (file)
@@ -1,3 +1,8 @@
+2007-12-05  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/34337
+       * gcc.c-torture/execute/20071205-1.c: New test.
+
 2007-12-05  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        * gfortran.dg/module_nan.f90: Add -mieee for sh.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20071205-1.c b/gcc/testsuite/gcc.c-torture/execute/20071205-1.c
new file mode 100644 (file)
index 0000000..fa19ec0
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR middle-end/34337 */
+
+extern void abort (void);
+
+int
+foo (int x)
+{
+  return ((x << 8) & 65535) | 255;
+}
+
+int
+main (void)
+{
+  if (foo (0x32) != 0x32ff || foo (0x174) != 0x74ff)
+    abort ();
+  return 0;
+}