fold-const.c (fold): Optimize ~X|X and X|~X as -1.
authorRoger Sayle <roger@eyesopen.com>
Sun, 27 Jun 2004 15:23:46 +0000 (15:23 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sun, 27 Jun 2004 15:23:46 +0000 (15:23 +0000)
* fold-const.c (fold) <BIT_IOR_EXPR>: Optimize ~X|X and X|~X as -1.
<BIT_XOR_EXPR>: Optimize ~X|X and X|~X as -1.
<BIT_AND_EXPR>: Optimize ~X&X and X&~X as 0.
<TRUTH_AND_EXPR, TRUTH_ANDIF_EXPR>: Optimize !X&&X and X&&!X as false.
        <TRUTH_OR_EXPR, TRUTH_ORIF_EXPR>: Optimize !X||X and !X||X as true.
<TRUTH_XOR_EXPR>: Optimize !X^X and X^X! as true.  Now that
TRUTH_XOR_EXPR is a commutative tree code, don't test whether arg0
is a constant.

* gcc.dg/20040527-1.c: New test case.

From-SVN: r83733

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20040627-1.c [new file with mode: 0644]

index b37f066fd5f90be342759c36330400f4fb82f151..69f8d327c8133e550654ef4d8b3d9efbb1fd89c7 100644 (file)
@@ -1,3 +1,14 @@
+2004-06-27  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (fold) <BIT_IOR_EXPR>: Optimize ~X|X and X|~X as -1.
+       <BIT_XOR_EXPR>: Optimize ~X|X and X|~X as -1.
+       <BIT_AND_EXPR>: Optimize ~X&X and X&~X as 0.
+       <TRUTH_AND_EXPR, TRUTH_ANDIF_EXPR>: Optimize !X&&X and X&&!X as false.
+        <TRUTH_OR_EXPR, TRUTH_ORIF_EXPR>: Optimize !X||X and !X||X as true.
+       <TRUTH_XOR_EXPR>: Optimize !X^X and X^X! as true.  Now that
+       TRUTH_XOR_EXPR is a commutative tree code, don't test whether arg0
+       is a constant.
+
 2004-06-26  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR 13334
index 24bde0fc323361937f972fba27e2653e3cef2f76..21cb85d32fa8a485f255c11a2fee9545440b1af4 100644 (file)
@@ -7185,6 +7185,27 @@ fold (tree expr)
        return non_lvalue (fold_convert (type, arg0));
       if (operand_equal_p (arg0, arg1, 0))
        return non_lvalue (fold_convert (type, arg0));
+
+      /* ~X | X is -1.  */
+      if (TREE_CODE (arg0) == BIT_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       {
+         t1 = build_int_2 (-1, -1);
+         TREE_TYPE (t1) = type;
+         force_fit_type (t1, 0);
+         return omit_one_operand (type, t1, arg1);
+       }
+
+      /* X | ~X is -1.  */
+      if (TREE_CODE (arg1) == BIT_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       {
+         t1 = build_int_2 (-1, -1);
+         TREE_TYPE (t1) = type;
+         force_fit_type (t1, 0);
+         return omit_one_operand (type, t1, arg0);
+       }
+
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
@@ -7216,6 +7237,26 @@ fold (tree expr)
       if (operand_equal_p (arg0, arg1, 0))
        return omit_one_operand (type, integer_zero_node, arg0);
 
+      /* ~X ^ X is -1.  */
+      if (TREE_CODE (arg0) == BIT_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       {
+         t1 = build_int_2 (-1, -1);
+         TREE_TYPE (t1) = type;
+         force_fit_type (t1, 0);
+         return omit_one_operand (type, t1, arg1);
+       }
+
+      /* X ^ ~X is -1.  */
+      if (TREE_CODE (arg1) == BIT_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       {
+         t1 = build_int_2 (-1, -1);
+         TREE_TYPE (t1) = type;
+         force_fit_type (t1, 0);
+         return omit_one_operand (type, t1, arg0);
+       }
+
       /* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
          with a constant, and the two constants have no bits in common,
         we should treat this as a BIT_IOR_EXPR since this may produce more
@@ -7243,6 +7284,17 @@ fold (tree expr)
        return omit_one_operand (type, arg1, arg0);
       if (operand_equal_p (arg0, arg1, 0))
        return non_lvalue (fold_convert (type, arg0));
+
+      /* ~X & X is always zero.  */
+      if (TREE_CODE (arg0) == BIT_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       return omit_one_operand (type, integer_zero_node, arg1);
+
+      /* X & ~X is always zero.  */
+      if (TREE_CODE (arg1) == BIT_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand (type, integer_zero_node, arg0);
+
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
@@ -7625,6 +7677,15 @@ fold (tree expr)
       if (integer_zerop (arg0))
        return omit_one_operand (type, arg0, arg1);
 
+      /* !X && X is always false.  */
+      if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       return omit_one_operand (type, integer_zero_node, arg1);
+      /* X && !X is always false.  */
+      if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand (type, integer_zero_node, arg0);
+
     truth_andor:
       /* We only do these simplifications if we are optimizing.  */
       if (!optimize)
@@ -7712,22 +7773,39 @@ fold (tree expr)
         TRUTH_OR_EXPR.  */
       if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
        return omit_one_operand (type, arg0, arg1);
+
+      /* !X || X is always true.  */
+      if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       return omit_one_operand (type, integer_one_node, arg1);
+      /* X || !X is always true.  */
+      if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand (type, integer_one_node, arg0);
+
       goto truth_andor;
 
     case TRUTH_XOR_EXPR:
-      /* If either arg is constant zero, drop it.  */
-      if (integer_zerop (arg0))
-       return non_lvalue (fold_convert (type, arg1));
+      /* If the second arg is constant zero, drop it.  */
       if (integer_zerop (arg1))
        return non_lvalue (fold_convert (type, arg0));
-      /* If either arg is constant true, this is a logical inversion.  */
-      if (integer_onep (arg0))
-       return non_lvalue (fold_convert (type, invert_truthvalue (arg1)));
+      /* If the second arg is constant true, this is a logical inversion.  */
       if (integer_onep (arg1))
        return non_lvalue (fold_convert (type, invert_truthvalue (arg0)));
       /* Identical arguments cancel to zero.  */
       if (operand_equal_p (arg0, arg1, 0))
        return omit_one_operand (type, integer_zero_node, arg0);
+
+      /* !X ^ X is always true.  */
+      if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+       return omit_one_operand (type, integer_one_node, arg1);
+
+      /* X ^ !X is always true.  */
+      if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       return omit_one_operand (type, integer_one_node, arg0);
+
       return t;
 
     case EQ_EXPR:
index 16661d340b2dc035ae40d919dc6afd7b7797f573..ab98b2a9126764c8d547949d97f5edecb4be038d 100644 (file)
@@ -1,3 +1,7 @@
+2004-06-27  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/20040527-1.c: New test case.
+
 2004-06-26  Bud Davis  <bdavis9659@comcast.net>
 
        PR gfortran/pr16196
diff --git a/gcc/testsuite/gcc.dg/20040627-1.c b/gcc/testsuite/gcc.dg/20040627-1.c
new file mode 100644 (file)
index 0000000..2b4f09f
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+extern void link_error (void);
+
+
+void test(int x)
+{
+  if ((x & ~x) != 0)
+    link_error ();
+  if ((~x & x) != 0)
+    link_error ();
+
+  if ((x ^ ~x) != -1)
+    link_error ();
+  if ((~x ^ x) != -1)
+    link_error ();
+
+  if ((x | ~x) != -1)
+    link_error ();
+  if ((~x | x) != -1)
+    link_error ();
+
+  if (x && !x)
+    link_error ();
+  if (!x && x)
+    link_error ();
+
+  if (!(x || !x))
+    link_error ();
+  if (!(!x || x))
+    link_error ();
+}
+
+int main()
+{
+  test (0);
+  test (1);
+  test (-1);
+  return 0;
+}
+